=> {
+ // if both color prop and color scheme are defined, we are merging them
+ if (colorProp && colorScheme) {
+ return typeof colorProp === 'string'
+ ? _.get(colorScheme, colorProp as string, colorScheme.default)
+ : { ...colorScheme.default, ...getColorSchemeFromObject(colorScheme, colorProp) }
+ }
+
+ // if the color prop is not defined, but the the color scheme is defined, then we are returning
+ // the defaults from the color scheme if they exists
+ if (colorScheme) {
+ return colorScheme && colorScheme.default ? colorScheme.default : {}
+ }
+
+ // if the color scheme is not defined, then if the color prop is a scheme object we are
+ // returning it, otherwise we return an empty object, as it means that the component is
+ // implementing the simple color prop
+ if (colorProp) {
+ return typeof colorProp === 'string' ? {} : colorProp
+ }
+
+ // if neither the color prop, nor the color scheme are defined, we are returning empty object
+ return {}
+}
diff --git a/src/lib/commonPropInterfaces.ts b/src/lib/commonPropInterfaces.ts
index df04272e05..8dbeb7776f 100644
--- a/src/lib/commonPropInterfaces.ts
+++ b/src/lib/commonPropInterfaces.ts
@@ -25,21 +25,32 @@ export interface UIComponentProps
className?: string
}
-export interface ColorComponentProps {
+export type ColorValue =
+ | 'primary'
+ | 'secondary'
+ | 'blue'
+ | 'green'
+ | 'grey'
+ | 'orange'
+ | 'pink'
+ | 'purple'
+ | 'teal'
+ | 'red'
+ | 'yellow'
+ | string
+
+export type ComplexColorPropType =
+ | {
+ foreground?: ColorValue
+ background?: ColorValue
+ border?: ColorValue
+ shadow?: ColorValue
+ }
+ | ColorValue
+
+export interface ColorComponentProps {
/** A component can have a color. */
- color?:
- | 'primary'
- | 'secondary'
- | 'blue'
- | 'green'
- | 'grey'
- | 'orange'
- | 'pink'
- | 'purple'
- | 'teal'
- | 'red'
- | 'yellow'
- | string
+ color?: TColor
}
export interface ContentComponentProps {
diff --git a/src/lib/commonPropTypes.ts b/src/lib/commonPropTypes.ts
index 0dab2712a4..699e023cc7 100644
--- a/src/lib/commonPropTypes.ts
+++ b/src/lib/commonPropTypes.ts
@@ -6,11 +6,38 @@ export interface CreateCommonConfig {
children?: boolean | 'node' | 'element'
as?: boolean
className?: boolean
- color?: boolean
+ color?: boolean | 'simple' | 'complex'
content?: boolean | 'node' | 'shorthand'
styled?: boolean
}
+const colorPropType = PropTypes.oneOfType([
+ PropTypes.oneOf([
+ 'primary',
+ 'secondary',
+ 'blue',
+ 'green',
+ 'grey',
+ 'orange',
+ 'pink',
+ 'purple',
+ 'teal',
+ 'red',
+ 'yellow',
+ ]),
+ PropTypes.string,
+])
+
+export const complexColorPropType = PropTypes.oneOfType([
+ PropTypes.shape({
+ foreground: colorPropType,
+ background: colorPropType,
+ border: colorPropType,
+ shadow: colorPropType,
+ }),
+ colorPropType,
+])
+
export const createCommon = (config: CreateCommonConfig = {}) => {
const {
animated = true,
@@ -35,22 +62,7 @@ export const createCommon = (config: CreateCommonConfig = {}) => {
className: PropTypes.string,
}),
...(color && {
- color: PropTypes.oneOfType([
- PropTypes.oneOf([
- 'primary',
- 'secondary',
- 'blue',
- 'green',
- 'grey',
- 'orange',
- 'pink',
- 'purple',
- 'teal',
- 'red',
- 'yellow',
- ]),
- PropTypes.string,
- ]),
+ color: color === true || color === 'simple' ? colorPropType : complexColorPropType,
}),
...(content && {
content:
diff --git a/src/lib/index.ts b/src/lib/index.ts
index ae64df0ebb..bff791ebbd 100644
--- a/src/lib/index.ts
+++ b/src/lib/index.ts
@@ -3,7 +3,7 @@ import * as commonPropTypes from './commonPropTypes'
export { default as AutoControlledComponent } from './AutoControlledComponent'
export { default as childrenExist } from './childrenExist'
-export { mapColorsToScheme } from './colorUtils'
+export * from './colorUtils'
export { default as UIComponent } from './UIComponent'
export { EventStack } from './eventStack'
export { felaRenderer, felaRtlRenderer } from './felaRenderer'
diff --git a/src/lib/renderComponent.tsx b/src/lib/renderComponent.tsx
index eb8bce6c37..ee859554b0 100644
--- a/src/lib/renderComponent.tsx
+++ b/src/lib/renderComponent.tsx
@@ -32,6 +32,7 @@ import { mergeComponentStyles, mergeComponentVariables } from './mergeThemes'
import { FocusZoneProps, FocusZone, FocusZone as FabricFocusZone } from './accessibility/FocusZone'
import { FOCUSZONE_WRAP_ATTRIBUTE } from './accessibility/FocusZone/focusUtilities'
import createAnimationStyles from './createAnimationStyles'
+import { generateColorScheme } from './index'
export interface RenderResultConfig {
// TODO: Switch back to React.ReactType after issue will be resolved
@@ -159,6 +160,7 @@ const renderComponent =
(config: RenderConfig
): React.ReactElem
const {
siteVariables = {
+ colorScheme: {},
colors: {},
contextualColors: {},
emphasisColors: {},
@@ -202,10 +204,14 @@ const renderComponent =
(config: RenderConfig
): React.ReactElem
{ handledProps: [...handledProps, ...accessibility.handledProps] },
props,
)
+
+ const colors = generateColorScheme(stateAndProps.color, resolvedVariables.colorScheme)
+
const styleParam: ComponentStyleFunctionParam = {
props: stateAndProps,
variables: resolvedVariables,
theme,
+ colors,
}
mergedStyles.root = {
diff --git a/src/themes/base/colors.ts b/src/themes/base/colors.ts
index 640888e214..e49ca7af62 100644
--- a/src/themes/base/colors.ts
+++ b/src/themes/base/colors.ts
@@ -1,4 +1,12 @@
-import { ColorPalette, ContextualColors, EmphasisColors, NaturalColors } from '../types'
+import * as _ from 'lodash'
+
+import {
+ ColorPalette,
+ ContextualColors,
+ EmphasisColors,
+ NaturalColors,
+ ColorSchemeMapping,
+} from '../types'
export const naturalColors: NaturalColors = {
blue: {
@@ -135,11 +143,38 @@ export const contextualColors: ContextualColors = {
warning: naturalColors.yellow,
}
-export const colors: ColorPalette = {
- ...contextualColors,
+const emphasisAndNaturalColors: EmphasisColors & NaturalColors = {
...emphasisColors,
...naturalColors,
+}
+
+const lightBackgroundColors = ['teal', 'yellow']
+const isLightBackground = (colorName: string) => _.includes(lightBackgroundColors, colorName)
+
+export const colors: ColorPalette = {
+ ...emphasisAndNaturalColors,
+ ...contextualColors,
black: '#000',
white: '#fff',
}
+
+export const colorScheme: ColorSchemeMapping = _.mapValues(
+ emphasisAndNaturalColors,
+ (colorVariants, colorName) => {
+ const foreground = isLightBackground(colorName) ? colors.black : colorVariants[50]
+
+ return {
+ foreground,
+ border: foreground,
+ shadow: foreground,
+ background: colorVariants[500],
+ default: {
+ foreground: colors.grey[600],
+ border: colors.grey[600],
+ shadow: colors.grey[600],
+ background: colors.grey[100],
+ },
+ }
+ },
+)
diff --git a/src/themes/base/siteVariables.ts b/src/themes/base/siteVariables.ts
index 45a44de555..81ced90456 100644
--- a/src/themes/base/siteVariables.ts
+++ b/src/themes/base/siteVariables.ts
@@ -2,7 +2,7 @@
// COLORS
//
-export { colors, contextualColors, emphasisColors, naturalColors } from './colors'
+export { colors, contextualColors, emphasisColors, naturalColors, colorScheme } from './colors'
//
// FONT SIZES
diff --git a/src/themes/teams/colors.ts b/src/themes/teams/colors.ts
index d342ea9d54..199794c570 100644
--- a/src/themes/teams/colors.ts
+++ b/src/themes/teams/colors.ts
@@ -1,4 +1,12 @@
-import { ColorPalette, ContextualColors, EmphasisColors, NaturalColors } from '../types'
+import * as _ from 'lodash'
+
+import {
+ ColorPalette,
+ ContextualColors,
+ EmphasisColors,
+ NaturalColors,
+ ColorSchemeMapping,
+} from '../types'
export const emphasisColors: EmphasisColors = {
primary: {
@@ -142,12 +150,39 @@ export const contextualColors: ContextualColors = {
text: naturalColors.grey,
}
-export const colors: ColorPalette = {
- ...contextualColors,
+const emphasisAndNaturalColors: EmphasisColors & NaturalColors = {
...emphasisColors,
...naturalColors,
+}
+
+const lightBackgroundColors = ['orange', 'yellow', 'lightGreen', 'postOrange']
+const isLightBackground = (colorName: string) => _.includes(lightBackgroundColors, colorName)
+
+export const colors: ColorPalette = {
+ ...emphasisAndNaturalColors,
+ ...contextualColors,
// Primitive colors
black: naturalColors.grey[900],
white: naturalColors.grey[50],
}
+
+export const colorScheme: ColorSchemeMapping = _.mapValues(
+ emphasisAndNaturalColors,
+ (colorVariants, colorName) => {
+ const foreground = isLightBackground(colorName) ? colors.black : colorVariants[50]
+
+ return {
+ foreground,
+ border: foreground,
+ shadow: foreground,
+ background: colorVariants[500],
+ default: {
+ foreground: colors.grey[600],
+ border: colors.grey[600],
+ shadow: colors.grey[600],
+ background: colors.grey[100],
+ },
+ }
+ },
+)
diff --git a/src/themes/teams/components/Label/labelStyles.ts b/src/themes/teams/components/Label/labelStyles.ts
index 20aef2a6be..a188c2dd21 100644
--- a/src/themes/teams/components/Label/labelStyles.ts
+++ b/src/themes/teams/components/Label/labelStyles.ts
@@ -1,42 +1,44 @@
+import * as _ from 'lodash'
+
import { pxToRem } from '../../../../lib'
import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types'
import { LabelProps } from '../../../../components/Label/Label'
+import { LabelVariables } from './labelVariables'
-const labelStyles: ComponentSlotStylesInput = {
- root: ({ props: { image, imagePosition, circular }, variables }): ICSSInJSStyle => ({
- padding: variables.padding,
- ...(image &&
- imagePosition === 'start' && {
- paddingLeft: variables.startPaddingLeft,
- }),
- ...(image &&
- imagePosition === 'end' && {
- paddingRight: variables.endPaddingRight,
- }),
- display: 'inline-flex',
- alignItems: 'center',
- height: variables.height,
- fontSize: pxToRem(14),
- lineHeight: variables.height,
- backgroundColor: variables.backgroundColor,
- color: variables.color,
- borderRadius: pxToRem(3),
- ...(circular && {
- borderRadius: variables.circularRadius,
- }),
- overflow: 'hidden',
- }),
- image: ({ variables }): ICSSInJSStyle => ({
- height: variables.height,
- width: variables.height,
- }),
- icon: ({ props }): ICSSInJSStyle => ({
- ...(props.icon &&
- typeof props.icon === 'object' &&
- (props.icon as any).onClick && {
- cursor: 'pointer',
+const labelStyles: ComponentSlotStylesInput = {
+ root: ({ props: p, variables: v, colors }): ICSSInJSStyle => {
+ return {
+ display: 'inline-flex',
+ alignItems: 'center',
+ overflow: 'hidden',
+ height: v.height,
+ lineHeight: v.height,
+ color: colors.foreground,
+ backgroundColor: colors.background,
+ fontSize: pxToRem(14),
+ borderRadius: pxToRem(3),
+ padding: v.padding,
+ ...(p.image &&
+ (p.imagePosition === 'start'
+ ? { paddingLeft: v.startPaddingLeft }
+ : { paddingRight: v.endPaddingRight })),
+ ...(p.circular && {
+ borderRadius: v.circularRadius,
}),
+ }
+ },
+
+ image: ({ variables: v }): ICSSInJSStyle => ({
+ height: v.height,
+ width: v.height,
}),
+
+ icon: ({ props: p }): ICSSInJSStyle =>
+ p.icon &&
+ typeof p.icon === 'object' &&
+ (p.icon as any).onClick && {
+ cursor: 'pointer',
+ },
}
export default labelStyles
diff --git a/src/themes/teams/components/Label/labelVariables.ts b/src/themes/teams/components/Label/labelVariables.ts
index 4391b63417..8f9256fc05 100644
--- a/src/themes/teams/components/Label/labelVariables.ts
+++ b/src/themes/teams/components/Label/labelVariables.ts
@@ -1,20 +1,33 @@
-import { pxToRem } from '../../../../lib'
+import { pxToRem, getColorSchemeWithCustomDefaults } from '../../../../lib'
+import { ColorValues, ColorScheme, SiteVariablesPrepared } from '../../../types'
-export default () => {
+type LabelColorScheme = Pick
+
+export interface LabelVariables {
+ colorScheme: ColorValues
+ circularRadius: string
+ padding: string
+ startPaddingLeft: string
+ endPaddingRight: string
+ height: string
+ iconColor: string
+}
+
+export default (siteVars: SiteVariablesPrepared): LabelVariables => {
const color = 'rgba(0, 0, 0, 0.6)'
return {
+ colorScheme: getColorSchemeWithCustomDefaults(siteVars.colorScheme, {
+ foreground: color,
+ background: 'rgb(232, 232, 232)',
+ }),
circularRadius: pxToRem(9999),
padding: `0 ${pxToRem(4)} 0 ${pxToRem(4)}`,
- color,
- backgroundColor: 'rgb(232, 232, 232)',
startPaddingLeft: '0px',
endPaddingRight: '0px',
height: pxToRem(20),
// variables for 'icon' part
- icon: {
- color,
- },
+ iconColor: color,
}
}
diff --git a/src/themes/teams/components/Menu/menuItemStyles.ts b/src/themes/teams/components/Menu/menuItemStyles.ts
index ee58466747..f0553f481a 100644
--- a/src/themes/teams/components/Menu/menuItemStyles.ts
+++ b/src/themes/teams/components/Menu/menuItemStyles.ts
@@ -142,7 +142,7 @@ const pointingBeak: ComponentSlotStyleFunction = {
- wrapper: ({ props, variables: v, theme }): ICSSInJSStyle => {
+ wrapper: ({ props, variables: v, theme, colors }): ICSSInJSStyle => {
const {
active,
iconOnly,
@@ -198,7 +198,7 @@ const menuItemStyles: ComponentSlotStylesInput
/**
* A type for extracting the color names.
*/
-type ColorNames = keyof (EmphasisColorsStrict & NaturalColorsStrict)
+export type ColorNames = keyof (EmphasisColorsStrict & NaturalColorsStrict)
/**
* A type for an extendable set of ColorNames properties of type T
@@ -96,6 +96,18 @@ export type ColorPalette = ExtendablePalette<
EmphasisColorsStrict & ContextualColorsStrict & NaturalColorsStrict & PrimitiveColors
>
+/**
+ * A type for the generic color scheme of a component based on CSS property names
+ */
+export type ColorScheme = {
+ foreground: string
+ background: string
+ border: string
+ shadow: string
+}
+
+export type ColorSchemeMapping = ColorValues & { default?: ColorScheme }
+
// ========================================================
// Props
// ========================================================
@@ -117,6 +129,7 @@ export type State = ObjectOf
export interface SiteVariablesInput extends ObjectOf {
colors?: ColorPalette
+ colorScheme?: ColorSchemeMapping
contextualColors?: ContextualColors
emphasisColors?: EmphasisColors
naturalColors?: NaturalColorsStrict
@@ -124,13 +137,7 @@ export interface SiteVariablesInput extends ObjectOf {
htmlFontSize?: string
}
-export interface SiteVariablesPrepared extends ObjectOf {
- colors?: ColorPalette
- contextualColors?: ContextualColors
- emphasisColors?: EmphasisColors
- naturalColors?: NaturalColorsStrict
- brand?: string
- htmlFontSize?: string
+export interface SiteVariablesPrepared extends SiteVariablesInput {
fontSizes: ObjectOf
}
@@ -190,6 +197,7 @@ export interface ComponentStyleFunctionParam<
props: State & TProps
variables: TVars
theme: ThemePrepared
+ colors: Partial
}
export type ComponentSlotStyleFunction = ((