diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bfc9d5e76..1e312ccd84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Export `table-add` and `table-delete` SVG icon in Teams theme @VyshnaviDasari ([#643](https://github.com/stardust-ui/react/pull/643)) - Add handling of `Enter` and `Spacebar` in List component @ jurokapsiar ([#279](https://github.com/stardust-ui/react/pull/279)) - Enable RTL for keyboard handlers @sophieH29 ([#656](https://github.com/stardust-ui/react/pull/656)) +- Add `color` prop to `Icon` component @Bugaa92 ([#651](https://github.com/stardust-ui/react/pull/651)) ### Documentation - Add more accessibility descriptions to components and behaviors @jurokapsiar ([#648](https://github.com/stardust-ui/react/pull/648)) diff --git a/docs/src/examples/components/Icon/Variations/IconExampleColor.shorthand.tsx b/docs/src/examples/components/Icon/Variations/IconExampleColor.shorthand.tsx index f23e0cf846..4d35cec7de 100644 --- a/docs/src/examples/components/Icon/Variations/IconExampleColor.shorthand.tsx +++ b/docs/src/examples/components/Icon/Variations/IconExampleColor.shorthand.tsx @@ -1,5 +1,6 @@ import * as React from 'react' -import { Icon, Grid, Text } from '@stardust-ui/react' +import * as _ from 'lodash' +import { Icon, Grid, Text, ProviderConsumer } from '@stardust-ui/react' const IconExampleColor = () => ( @@ -15,27 +16,17 @@ const IconExampleColor = () => ( - - USING THE color VARIABLE: - - } - weight="bold" - /> + + USING THE color VARIABLE: + - - USING THE borderColor VARIABLE: - - } - weight="bold" - /> + + USING THE borderColor VARIABLE: + ( variables={{ color: 'cornflowerblue', borderColor: 'orangered' }} /> + + USING THE color PROP: + + + + _.take(_.keys({ ...emphasisColors, ...naturalColors }), 3).map(color => ( + + )) + } + /> + ) diff --git a/src/components/Icon/Icon.tsx b/src/components/Icon/Icon.tsx index 9b614b71f8..0d78aedab7 100644 --- a/src/components/Icon/Icon.tsx +++ b/src/components/Icon/Icon.tsx @@ -6,6 +6,7 @@ import { createShorthandFactory, UIComponentProps, commonPropTypes, + ColorComponentProps, } from '../../lib' import { iconBehavior } from '../../lib/accessibility/' import { Accessibility } from '../../lib/accessibility/types' @@ -17,7 +18,7 @@ export type IconXSpacing = 'none' | 'before' | 'after' | 'both' export type IconSize = 'smallest' | 'smaller' | 'small' | 'medium' | 'large' | 'larger' | 'largest' -export interface IconProps extends UIComponentProps { +export interface IconProps extends UIComponentProps, ColorComponentProps { /** * Accessibility behavior if overriden by the user. * @default iconBehavior @@ -57,6 +58,7 @@ class Icon extends UIComponent, any> { ...commonPropTypes.createCommon({ children: false, content: false, + color: true, }), accessibility: PropTypes.func, bordered: PropTypes.bool, diff --git a/src/themes/teams/components/Icon/iconStyles.ts b/src/themes/teams/components/Icon/iconStyles.ts index ecd468d561..72c172ecc7 100644 --- a/src/themes/teams/components/Icon/iconStyles.ts +++ b/src/themes/teams/components/Icon/iconStyles.ts @@ -1,21 +1,24 @@ +import * as _ from 'lodash' + import fontAwesomeIcons from './fontAwesomeIconStyles' import { callable } from '../../../../lib' import { fittedStyle } from '../../../../styles/customCSS' import { ComponentSlotStylesInput, ICSSInJSStyle, FontIconSpec } from '../../../types' import { ResultOf } from '../../../../../types/utils' -import { IconXSpacing, IconProps } from '../../../../components/Icon/Icon' +import { IconXSpacing, IconProps, IconSize } from '../../../../components/Icon/Icon' import { pxToRem } from '../../utils' import { getStyle as getSvgStyle } from './svg' - -const sizes = new Map([ - ['smallest', 7], - ['smaller', 10], - ['small', 12], - ['medium', 16], - ['large', 20], - ['larger', 32], - ['largest', 40], -]) +import { IconVariables, IconSizeModifier } from './iconVariables' + +const sizes: { [key in IconSize]: number } = { + smallest: 7, + smaller: 10, + small: 12, + medium: 16, + large: 20, + larger: 32, + largest: 40, +} const getDefaultFontIcon = (iconName: string) => { return callable(fontAwesomeIcons(iconName).icon)() @@ -57,7 +60,7 @@ const getXSpacingStyles = (xSpacing: IconXSpacing, horizontalSpace: string): ICS } } -const getBorderedStyles = (circular, boxShadowColor): ICSSInJSStyle => { +const getBorderedStyles = (circular: boolean, boxShadowColor: string): ICSSInJSStyle => { return { ...getPaddedStyle(), @@ -70,10 +73,11 @@ const getPaddedStyle = (): ICSSInJSStyle => ({ padding: pxToRem(4), }) -const getIconSize = (size, sizeModifier): number => { +const getIconSize = (size: IconSize, sizeModifier: IconSizeModifier): number => { if (!sizeModifier) { - return sizes.get(size) + return sizes[size] } + const modifiedSizes = { large: { x: 24, @@ -84,11 +88,12 @@ const getIconSize = (size, sizeModifier): number => { return modifiedSizes[size] && modifiedSizes[size][sizeModifier] } -const getIconColor = color => color || 'currentColor' +const getIconColor = (colorProp: string, variables: IconVariables) => + _.get(variables.colors, colorProp, variables.color || 'currentColor') -const iconStyles: ComponentSlotStylesInput = { +const iconStyles: ComponentSlotStylesInput = { root: ({ - props: { disabled, name, size, bordered, circular, xSpacing }, + props: { disabled, name, size, bordered, circular, color, xSpacing }, variables: v, theme, }): ICSSInJSStyle => { @@ -105,7 +110,7 @@ const iconStyles: ComponentSlotStylesInput = { ...(isFontBased && getFontStyles(getIconSize(size, v.sizeModifier), name)), ...(isFontBased && { - color: getIconColor(v.color), + color: getIconColor(color, v), ...(disabled && { color: v.disabledColor, @@ -115,7 +120,7 @@ const iconStyles: ComponentSlotStylesInput = { ...getXSpacingStyles(xSpacing, v.horizontalSpace), ...((bordered || v.borderColor || circular) && - getBorderedStyles(circular, v.borderColor || getIconColor(v.color))), + getBorderedStyles(circular, v.borderColor || getIconColor(color, v))), } }, @@ -137,14 +142,14 @@ const iconStyles: ComponentSlotStylesInput = { } }, - svg: ({ props: { size, disabled }, variables: v }): ICSSInJSStyle => { + svg: ({ props: { size, color, disabled }, variables: v }): ICSSInJSStyle => { const iconSizeInRems = pxToRem(getIconSize(size, v.sizeModifier)) return { display: 'block', width: iconSizeInRems, height: iconSizeInRems, - fill: getIconColor(v.color), + fill: getIconColor(color, v), ...(disabled && { fill: v.disabledColor, diff --git a/src/themes/teams/components/Icon/iconVariables.ts b/src/themes/teams/components/Icon/iconVariables.ts index 154aa225ea..34fc180f19 100644 --- a/src/themes/teams/components/Icon/iconVariables.ts +++ b/src/themes/teams/components/Icon/iconVariables.ts @@ -1,31 +1,40 @@ +import { ColorValues } from '../../../types' +import { mapColorsToScheme } from '../../../../lib' import { pxToRem } from '../../utils' -export interface IconVariables { - [key: string]: string | number | boolean | undefined +export type IconSizeModifier = 'x' | 'xx' - redColor?: string - brandColor?: string +export interface IconVariables { + [key: string]: object | string | number | boolean | undefined - outline?: boolean + colors: ColorValues color?: string backgroundColor?: string borderColor?: string - horizontalSpace: string - margin: string + brandColor?: string secondaryColor: string + redColor?: string disabledColor: string + + horizontalSpace: string + margin: string + outline?: boolean + sizeModifier?: IconSizeModifier } +const colorVariant = 500 + export default (siteVars): IconVariables => ({ - outline: undefined, + colors: mapColorsToScheme(siteVars, colorVariant), color: undefined, backgroundColor: undefined, borderColor: undefined, - horizontalSpace: pxToRem(10), - margin: `0 ${pxToRem(8)} 0 0`, + brandColor: siteVars.brandColor, secondaryColor: siteVars.white, + redColor: siteVars.red, disabledColor: siteVars.gray06, - redColor: siteVars.red, - brandColor: siteVars.brandColor, + horizontalSpace: pxToRem(10), + margin: `0 ${pxToRem(8)} 0 0`, + outline: undefined, })
color
borderColor