Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

feat(icon): color prop #651

Merged
merged 4 commits into from
Dec 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
@@ -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 = () => (
<Grid columns="repeat(4, auto)" styles={{ alignItems: 'center' }} variables={{ gridGap: '10px' }}>
Expand All @@ -15,27 +16,17 @@ const IconExampleColor = () => (
<Icon name="call" bordered variables={{ outline: true }} />
<Icon name="call-video" bordered variables={{ outline: true }} />
</div>
<Text
content={
<span>
USING THE <code>color</code> VARIABLE:
</span>
}
weight="bold"
/>
<Text weight="bold">
USING THE <code>color</code> VARIABLE:
</Text>
<div>
<Icon name="calendar" bordered variables={{ color: 'violet' }} />
<Icon name="call" bordered variables={{ color: 'yellowgreen' }} />
<Icon name="call-video" bordered variables={{ color: 'cornflowerblue' }} />
</div>
<Text
content={
<span>
USING THE <code>borderColor</code> VARIABLE:
</span>
}
weight="bold"
/>
<Text weight="bold">
USING THE <code>borderColor</code> VARIABLE:
</Text>
<div>
<Icon
name="calendar"
Expand All @@ -53,6 +44,18 @@ const IconExampleColor = () => (
variables={{ color: 'cornflowerblue', borderColor: 'orangered' }}
/>
</div>
<Text weight="bold">
USING THE <code>color</code> PROP:
</Text>
<div>
<ProviderConsumer
render={({ siteVariables: { emphasisColors, naturalColors } }) =>
_.take(_.keys({ ...emphasisColors, ...naturalColors }), 3).map(color => (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this expression is very confusing - there should be a way to simplify this example. Actually, why slicing is necessary here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

screenshot 2018-12-19 at 19 38 04
just to make the example fit nicely, any suggestions for improving, @kuzhelov ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kuzhelov can I resolve this?

<Icon key={color} name="call" bordered color={color} />
))
}
/>
</div>
</Grid>
)

Expand Down
4 changes: 3 additions & 1 deletion src/components/Icon/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
createShorthandFactory,
UIComponentProps,
commonPropTypes,
ColorComponentProps,
} from '../../lib'
import { iconBehavior } from '../../lib/accessibility/'
import { Accessibility } from '../../lib/accessibility/types'
Expand All @@ -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
Expand Down Expand Up @@ -57,6 +58,7 @@ class Icon extends UIComponent<ReactProps<IconProps>, any> {
...commonPropTypes.createCommon({
children: false,
content: false,
color: true,
}),
accessibility: PropTypes.func,
bordered: PropTypes.bool,
Expand Down
47 changes: 26 additions & 21 deletions src/themes/teams/components/Icon/iconStyles.ts
Original file line number Diff line number Diff line change
@@ -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)()
Expand Down Expand Up @@ -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(),

Expand All @@ -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,
Expand All @@ -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<IconProps, any> = {
const iconStyles: ComponentSlotStylesInput<IconProps, IconVariables> = {
root: ({
props: { disabled, name, size, bordered, circular, xSpacing },
props: { disabled, name, size, bordered, circular, color, xSpacing },
variables: v,
theme,
}): ICSSInJSStyle => {
Expand All @@ -105,7 +110,7 @@ const iconStyles: ComponentSlotStylesInput<IconProps, any> = {
...(isFontBased && getFontStyles(getIconSize(size, v.sizeModifier), name)),

...(isFontBased && {
color: getIconColor(v.color),
color: getIconColor(color, v),

...(disabled && {
color: v.disabledColor,
Expand All @@ -115,7 +120,7 @@ const iconStyles: ComponentSlotStylesInput<IconProps, any> = {
...getXSpacingStyles(xSpacing, v.horizontalSpace),

...((bordered || v.borderColor || circular) &&
getBorderedStyles(circular, v.borderColor || getIconColor(v.color))),
getBorderedStyles(circular, v.borderColor || getIconColor(color, v))),
}
},

Expand All @@ -137,14 +142,14 @@ const iconStyles: ComponentSlotStylesInput<IconProps, any> = {
}
},

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,
Expand Down
33 changes: 21 additions & 12 deletions src/themes/teams/components/Icon/iconVariables.ts
Original file line number Diff line number Diff line change
@@ -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<string>
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,
})