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

fix(Icon): Redline matching sizing and spacing of icons in Teams theme #386

Closed
wants to merge 2 commits into from
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { Icon } from '@stardust-ui/react'

const IconExampleDisabled = () => (
<div>
<Icon disabled name="umbrella" size="big" />
<Icon disabled name="umbrella" size="big" variables={{ color: 'blue' }} />
<Icon disabled name="umbrella" size="big" variables={{ color: 'red' }} />
<Icon disabled name="umbrella" size="big" variables={{ color: 'orange' }} />
<Icon disabled name="call-video" xSpacing="after" />
<Icon disabled name="call-video" xSpacing="after" variables={{ color: 'blue' }} />
<Icon disabled name="call-video" xSpacing="after" variables={{ color: 'red' }} />
<Icon disabled name="call-video" xSpacing="after" variables={{ color: 'orange' }} />
</div>
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { Icon } from '@stardust-ui/react'

const IconExample = () => (
<div>
<Icon name="umbrella" size="big" />
<Icon name="chess rook" size="big" />
<Icon name="book" size="big" />
<Icon name="circle" size="big" />
<Icon name="call-video" xSpacing="after" />
<Icon name="call" xSpacing="after" />
<Icon name="chess rook" xSpacing="after" />
<Icon name="book" xSpacing="after" />
<Icon name="circle" xSpacing="after" />
</div>
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react'
import { Icon } from '@stardust-ui/react'

const IconAlignedExampleShorthand = () => (
<div style={{ backgroundColor: 'yellow' }}>
<Icon name="call-video" xSpacing="all" />
<Icon name="paperClip" xSpacing="all" />
<Icon name="book" xSpacing="all" />
<Icon name="more" xSpacing="all" />
</div>
)

export default IconAlignedExampleShorthand
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const IconSetExampleShorthand = () => (
<Grid columns={3} style={{ textAlign: 'center' }}>
{Object.keys(theme.icons).map(name => (
<span key={name}>
<Icon name={name} />
<Icon name={name} xSpacing="all" />
<br />
<code>{name}</code>
</span>
Expand Down
5 changes: 5 additions & 0 deletions docs/src/examples/components/Icon/Usage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ const Usage = () => (
description="You can access all icon names available in the current theme."
examplePath="components/Icon/Usage/IconSetExample"
/>
<ComponentExample
title="Aligned icons"
description="You can vertically line up icons of the same size."
examplePath="components/Icon/Usage/IconAlignedExample"
/>
</ExampleSection>
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const IconExampleBordered = () => (
<Icon name="chess rook" bordered />
<Icon name="book" bordered />
<Icon name="expand" bordered />
<Icon name="call" bordered />
<Icon name="call-video" bordered />
<Icon name="play" bordered />
<Icon name="stop" bordered />
<Icon name="calendar alternate outline" bordered />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const IconExampleCircular = () => (
<Icon name="chess rook" circular />
<Icon name="book" circular />
<Icon name="expand" circular />
<Icon name="call" circular />
<Icon name="call-video" circular />
<Icon name="play" circular />
<Icon name="stop" circular />
<Icon name="calendar alternate outline" circular />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
import React from 'react'
import { Icon } from '@stardust-ui/react'
import { Grid, Icon } from '@stardust-ui/react'

const IconExampleSize = () => (
<div>
<Grid rows={2} style={{ textAlign: 'center' }}>
<Icon name="home" size="micro" />
<Icon name="call-video" size="micro" />

<Icon name="home" size="mini" />
<Icon name="call-video" size="mini" />

<Icon name="home" size="tiny" />
<Icon name="call-video" size="tiny" />

<Icon name="home" size="small" />
<Icon name="call-video" size="small" />

<Icon name="home" />
<Icon name="call-video" />

<Icon name="home" size="large" />
<Icon name="call-video" size="large" />

<Icon name="home" size="big" />
<Icon name="call-video" size="big" />

<Icon name="home" size="huge" />
<Icon name="call-video" size="huge" />

<Icon name="home" size="massive" />
</div>
<Icon name="call-video" size="massive" />
</Grid>
)

export default IconExampleSize
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,34 @@ const IconExampleSpace = () => (
<div>
<div style={{ marginBottom: '1.2rem' }}>
<Label content="Default" />
<Icon name="umbrella" size="big" />
<Icon name="call-video" />
<Label content="Default" />
</div>
<div style={{ marginBottom: '1.2rem' }}>
<Label content="Before" />
<Icon name="umbrella" xSpacing="before" size="big" />
<Icon name="call-video" xSpacing="before" />
<Label content="Before" />
</div>
<div style={{ marginBottom: '1.2rem' }}>
<Label content="After" />
<Icon name="umbrella" xSpacing="after" size="big" />
<Icon name="call-video" xSpacing="after" />
<Label content="After" />
</div>
<div style={{ marginBottom: '1.2rem' }}>
<Label content="Both" />
<Icon name="umbrella" xSpacing="both" size="big" />
<Icon name="call-video" xSpacing="both" />
<Label content="Both" />
</div>
<div style={{ marginBottom: '1.2rem' }}>
<Label content="None" />
<Icon name="umbrella" xSpacing="none" size="big" />
<Icon name="call-video" xSpacing="none" />
<Label content="None" />
</div>
<div style={{ marginBottom: '1.2rem' }}>
<Label content="All" />
<Icon name="call-video" xSpacing="all" />
<Label content="All" />
</div>
</div>
)

Expand Down
4 changes: 2 additions & 2 deletions src/components/Icon/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Accessibility } from '../../lib/accessibility/types'
import { ComponentSlotStyle, ComponentVariablesInput, SvgIconSpec } from '../../themes/types'
import { Extendable } from '../../../types/utils'

export type IconXSpacing = 'none' | 'before' | 'after' | 'both'
export type IconXSpacing = 'none' | 'before' | 'after' | 'both' | 'all'
export type IconSize =
| 'micro'
| 'mini'
Expand Down Expand Up @@ -79,7 +79,7 @@ class Icon extends UIComponent<Extendable<IconProps>, any> {
variables: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),

/** Adds space to the before, after or on both sides of the icon, or removes the default space around the icon ('none' value) */
xSpacing: PropTypes.oneOf(['none', 'before', 'after', 'both']),
xSpacing: PropTypes.oneOf(['none', 'before', 'after', 'both', 'all']),

/** Accessibility behavior if overriden by the user. */
accessibility: PropTypes.func,
Expand Down
89 changes: 54 additions & 35 deletions src/themes/teams/components/Icon/iconStyles.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
import fontAwesomeIcons from './fontAwesomeIconStyles'
import { callable } from '../../../../lib'
import { disabledStyle, fittedStyle } from '../../../../styles/customCSS'
import { disabledStyle } from '../../../../styles/customCSS'
import { ComponentSlotStylesInput, ICSSInJSStyle, FontIconSpec } from '../../../types'
import { ResultOf } from '../../../../../types/utils'
import { IconXSpacing, IconProps } from '../../../../components/Icon/Icon'

import { pxToRem } from './../../../../lib'
import { getStyle as getSvgStyle } from './svg'

const sizes = new Map([
['micro', 0.3],
['mini', 0.4],
['tiny', 0.5],
['small', 0.75],
['normal', 1],
['large', 1.5],
['big', 2],
['huge', 4],
['massive', 8],
['micro', [10, 10]],
['mini', [12, 10]],
['tiny', [14, 10]],
['small', [24, 12]],
['normal', [32, 16]],
['large', [32, 20]],
['big', [40, 20]],
['huge', [64, 52]],
['massive', [72, 64]],
])

const getDefaultFontIcon = (iconName: string) => {
return callable(fontAwesomeIcons(iconName).icon)()
}

const getSize = size => `${sizes.get(size)}em`

const getFontStyles = (iconName: string, themeIcon?: ResultOf<FontIconSpec>): ICSSInJSStyle => {
const { fontFamily, content } = themeIcon || getDefaultFontIcon(iconName)

return {
fontFamily,
width: '1.18em',
fontStyle: 'normal',
fontWeight: 400,
textDecoration: 'inherit',
Expand All @@ -50,35 +47,48 @@ const getFontStyles = (iconName: string, themeIcon?: ResultOf<FontIconSpec>): IC
}
}

const getXSpacingStyles = (xSpacing: IconXSpacing, horizontalSpace: string): ICSSInJSStyle => {
const getXSpacingStyles = (
xSpacing: IconXSpacing,
iconSpaceRems: string,
iconPadding: string,
): ICSSInJSStyle => {
switch (xSpacing) {
case 'none':
return fittedStyle
return {
margin: `-${iconPadding}`,
}
case 'before':
return { ...fittedStyle, marginLeft: horizontalSpace }
return {
margin: `-${iconPadding} -${iconPadding} -${iconPadding} ${iconSpaceRems}`,
}
case 'after':
return { ...fittedStyle, marginRight: horizontalSpace }
return {
margin: `-${iconPadding} ${iconSpaceRems} -${iconPadding} -${iconPadding}`,
}
case 'both':
return { ...fittedStyle, margin: `0 ${horizontalSpace}` }
return {
margin: `-${iconPadding} ${iconSpaceRems}`,
}
case 'all':
return {
margin: 0,
}
default:
return {
margin: `-${iconPadding}`,
}
}
}

const getBorderedStyles = (isFontBased, circular, borderColor, color): ICSSInJSStyle => {
const getBorderedStyles = (circular, borderColor, color): ICSSInJSStyle => {
return {
...getPaddedStyle(isFontBased),

// TODO: "black" here should actually match the Icon's fill or text color
boxShadow: `0 0 0 0.05em ${borderColor || color || 'black'} inset`,
margin: 0,
...(circular ? { borderRadius: '50%' } : {}),
}
}

const getPaddedStyle = (isFontBased: boolean): ICSSInJSStyle => ({
padding: `0.5em ${isFontBased ? 0 : '0.5em'}`,
width: '2em',
height: '2em',
})

const iconStyles: ComponentSlotStylesInput<IconProps, any> = {
root: ({
props: { disabled, name, size, bordered, circular, xSpacing },
Expand All @@ -88,31 +98,40 @@ const iconStyles: ComponentSlotStylesInput<IconProps, any> = {
const iconSpec = theme.icons[name]
const isFontBased = !iconSpec || !iconSpec.isSvg

const sizeData = sizes.get(size)
const svgSize = sizeData[0]
const iconSize = sizeData[1]
const iconPadding = (svgSize - iconSize) / 2
const iconPaddingRems = pxToRem(iconPadding)
const iconSpaceRems = pxToRem(v.horizontalSpace - iconPadding)

return {
display: 'inline-block',
fontSize: getSize(size),

width: '1em',
height: '1em',
width: pxToRem(svgSize),
height: pxToRem(svgSize),

...(isFontBased &&
getFontStyles(name, callable(iconSpec && (iconSpec.icon as FontIconSpec))())),

...(isFontBased && { color: v.color }),
...(isFontBased && {
color: v.color,
fontSize: pxToRem(iconSize),
padding: iconPaddingRems,
}),
backgroundColor: v.backgroundColor,

opacity: 1,
margin: v.margin,

speak: 'none',

verticalAlign: 'middle',
overflow: 'hidden',

...getXSpacingStyles(xSpacing, v.horizontalSpace),
...getXSpacingStyles(xSpacing, iconSpaceRems, iconPaddingRems),

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

...(disabled && disabledStyle),
}
Expand Down
8 changes: 2 additions & 6 deletions src/themes/teams/components/Icon/iconVariables.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { pxToRem } from '../../../../lib'

export interface IconVariables {
[key: string]: string | number | undefined

color?: string
backgroundColor?: string
borderColor?: string
horizontalSpace: string
margin: string
horizontalSpace: number
secondaryColor: string
}

Expand All @@ -17,7 +14,6 @@ export default (): IconVariables => ({
// similar to how components have an info.json file
backgroundColor: undefined,
borderColor: undefined,
horizontalSpace: pxToRem(10),
margin: '0 0.25em 0 0',
horizontalSpace: 15,
secondaryColor: 'white',
})
4 changes: 2 additions & 2 deletions src/themes/teams/components/Icon/svg/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import callStopPresenting from './callControlStopPresentingNew'
import callMicrophone from './callMicrophone'
import callMicrophoneOff from './callMicrophoneOff'
import more from './more'
import paperClip from './paperClip'
import teamCreate from './teamCreate'
import umbrella from './umbrella'
import teams from './teams'

export default {
Expand All @@ -23,7 +23,7 @@ export default {
'call-microphone': callMicrophone,
'call-microphone-off': callMicrophoneOff,
more,
paperClip,
'team-create': teamCreate,
umbrella,
teams,
} as { [iconName: string]: TeamsSvgIconSpec }
16 changes: 16 additions & 0 deletions src/themes/teams/components/Icon/svg/icons/paperClip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from 'react'
import { TeamsSvgIconSpec } from '../types'

export default (
<svg role="presentation" viewBox="0 0 32 32">
<path
d="M20.7927,16.8364L16.021,21.554c-0.6099,0.6099-1.4224,0.9458-2.2876,0.9458s-1.6777-0.3359-2.2876-0.9458
c-1.2612-1.2615-1.2612-3.3137,0.0098-4.5852l6.7021-6.96c0.6567-0.6562,1.8059-0.6567,2.4622,0
c0.6787,0.679,0.6787,1.7832-0.0154,2.478l-5.7725,6.03c-0.1973,0.1931-0.2009,0.5098-0.0081,0.7073
c0.1936,0.1973,0.5098,0.2012,0.7073,0.0081l5.7957-6.0542c1.0688-1.0686,1.0688-2.8076,0-3.8762
c-0.5168-0.5171-1.2053-0.802-1.938-0.802s-1.4211,0.2849-1.9382,0.802l-6.7119,6.97c-1.6514,1.6511-1.6514,4.3381,0,5.9893
c0.8259,0.8259,1.9106,1.2388,2.9954,1.2388c1.084,0,2.1675-0.4124,2.9919-1.2368l4.7698-4.7156
c0.1963-0.1941,0.1982-0.5107,0.0039-0.707C21.3059,16.644,20.9893,16.6418,20.7927,16.8364z"
/>
</svg>
) as TeamsSvgIconSpec
Loading