-
Notifications
You must be signed in to change notification settings - Fork 54
feat(themes): add FontAwesome theme #1337
Changes from 24 commits
cc9befa
75de2bb
2d89de6
04a0fed
62a807c
acbc177
82b3934
83a7732
aa3d935
6931faa
4fe3fa8
4f36475
55d9490
816ac38
c0fc01a
c231413
9b19f65
d4d8917
e70b839
a13e630
aa17a05
ebfe10a
9ce2080
66453f0
8a97ad1
3ec7f3d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -498,7 +498,7 @@ class ComponentExample extends React.Component<ComponentExampleProps, ComponentE | |
description, | ||
title, | ||
} = this.props | ||
const { showCode, showRtl, showTransparent } = this.state | ||
const { showCode, showRtl, showTransparent, themeName } = this.state | ||
|
||
return ( | ||
<Flex column> | ||
|
@@ -540,6 +540,7 @@ class ComponentExample extends React.Component<ComponentExampleProps, ComponentE | |
render={this.renderElement} | ||
renderHtml={showCode} | ||
resolver={importResolver} | ||
themeName={themeName} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will allow us to access |
||
> | ||
<Provider.Consumer | ||
render={({ siteVariables }) => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,7 @@ const AvatarExampleImageCustomizationShorthand = () => ( | |
// This example does not react to the avatar size variable | ||
// and otherwise produces bad results when border is applied compared to "normal" image | ||
<Icon | ||
name="user" | ||
name="lock" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Teams theme doesn't have this icon and font icons will not be supported inside of it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am a bit confuse here. We are changing only this icon because Teams' theme doesn't support font icons? What about all other examples like: 'chess rook', 'book' etc. Are we planning to move all examples for now to reflect the Teams' theme icon names? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This slot in attachment requires an additional styling for font icons that is not present, so yes. |
||
circular | ||
bordered | ||
variables={{ color: 'blue' }} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,46 @@ | ||
import * as React from 'react' | ||
import { Grid, Divider, Header, Icon, Provider } from '@stardust-ui/react' | ||
import { Grid, Divider, Header, Icon, themes } from '@stardust-ui/react' | ||
|
||
const cellStyles = { | ||
margin: '10px 0', | ||
} | ||
|
||
const IconSetExampleShorthand = () => ( | ||
<Provider.Consumer | ||
render={theme => ( | ||
<> | ||
<div> | ||
<Divider> | ||
<Header as="h3" content="Regular" /> | ||
</Divider> | ||
<Grid columns={4} styles={{ textAlign: 'center' }}> | ||
{Object.keys(theme.icons).map(name => ( | ||
<div key={name} style={cellStyles}> | ||
<Icon name={name} /> | ||
<br /> | ||
<code>{name}</code> | ||
</div> | ||
))} | ||
</Grid> | ||
</div> | ||
const IconSetExampleShorthand: React.FunctionComponent<{ themeName: string }> = ({ themeName }) => ( | ||
<> | ||
<div> | ||
<Divider> | ||
<Header as="h3" content="Regular" /> | ||
</Divider> | ||
<Grid columns={4} styles={{ textAlign: 'center' }}> | ||
{Object.keys(themes[themeName].icons).map(name => ( | ||
mnajdova marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<div key={name} style={cellStyles}> | ||
<Icon name={name} /> | ||
<br /> | ||
<code>{name}</code> | ||
</div> | ||
))} | ||
</Grid> | ||
</div> | ||
|
||
<div> | ||
<Divider> | ||
<Header as="h3" content="Outline" /> | ||
</Divider> | ||
<Grid columns={4} styles={{ textAlign: 'center' }}> | ||
{Object.keys(theme.icons).map(name => ( | ||
<div key={`${name}-outline`} style={cellStyles}> | ||
<Icon name={name} outline /> | ||
<br /> | ||
<code>{name} outline</code> | ||
</div> | ||
))} | ||
</Grid> | ||
</div> | ||
</> | ||
)} | ||
/> | ||
<div> | ||
<Divider> | ||
<Header as="h3" content="Outline" /> | ||
</Divider> | ||
<Grid columns={4} styles={{ textAlign: 'center' }}> | ||
{Object.keys(themes[themeName].icons).map(name => ( | ||
<div key={`${name}-outline`} style={cellStyles}> | ||
<Icon name={name} outline /> | ||
<br /> | ||
<code>{name} outline</code> | ||
</div> | ||
))} | ||
</Grid> | ||
</div> | ||
</> | ||
) | ||
|
||
IconSetExampleShorthand.defaultProps = { | ||
themeName: 'teams', | ||
} | ||
|
||
export default IconSetExampleShorthand |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
import * as customPropTypes from '@stardust-ui/react-proptypes' | ||
import * as React from 'react' | ||
import cx from 'classnames' | ||
import * as PropTypes from 'prop-types' | ||
import { | ||
callable, | ||
|
@@ -12,9 +12,8 @@ import { | |
} from '../../lib' | ||
import { iconBehavior } from '../../lib/accessibility' | ||
import { Accessibility } from '../../lib/accessibility/types' | ||
|
||
import { SvgIconSpec } from '../../themes/types' | ||
import { WithAsProp, withSafeTypeForAs } from '../../types' | ||
import Box from '../Box/Box' | ||
|
||
export type IconXSpacing = 'none' | 'before' | 'after' | 'both' | ||
|
||
|
@@ -80,46 +79,28 @@ class Icon extends UIComponent<WithAsProp<IconProps>, any> { | |
rotate: 0, | ||
} | ||
|
||
private renderFontIcon(ElementType, classes, unhandledProps, accessibility): React.ReactNode { | ||
return ( | ||
<ElementType | ||
className={classes.root} | ||
{...accessibility.attributes.root} | ||
{...unhandledProps} | ||
/> | ||
) | ||
} | ||
|
||
private renderSvgIcon( | ||
ElementType, | ||
svgIconDescriptor: SvgIconSpec, | ||
classes, | ||
unhandledProps, | ||
accessibility, | ||
rtl, | ||
): React.ReactNode { | ||
return ( | ||
<ElementType className={classes.root} {...accessibility.attributes.root} {...unhandledProps}> | ||
{svgIconDescriptor && callable(svgIconDescriptor)({ classes, rtl })} | ||
</ElementType> | ||
) | ||
} | ||
|
||
public renderComponent({ ElementType, classes, unhandledProps, accessibility, theme, rtl }) { | ||
renderComponent({ ElementType, classes, unhandledProps, accessibility, theme, rtl, styles }) { | ||
const { className, name } = this.props | ||
const { icons = {} } = theme | ||
|
||
const maybeIcon = icons[this.props.name] | ||
|
||
return maybeIcon && maybeIcon.isSvg | ||
? this.renderSvgIcon( | ||
ElementType, | ||
maybeIcon.icon as SvgIconSpec, | ||
classes, | ||
unhandledProps, | ||
accessibility, | ||
rtl, | ||
) | ||
: this.renderFontIcon(ElementType, classes, unhandledProps, accessibility) | ||
const maybeIcon = icons[name] | ||
const isSvgIcon = maybeIcon && maybeIcon.isSvg | ||
|
||
return Box.create( | ||
{ content: isSvgIcon && callable(maybeIcon.icon)({ classes, rtl }) }, | ||
{ | ||
defaultProps: { | ||
as: ElementType, | ||
className: cx(Icon.className, className), | ||
...accessibility.attributes.root, | ||
...unhandledProps, | ||
styles: { | ||
...styles.root, | ||
mnajdova marked this conversation as resolved.
Show resolved
Hide resolved
|
||
...(isSvgIcon ? styles.svgRoot : styles.fontRoot), | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have to use |
||
}, | ||
}, | ||
) | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,9 @@ | ||
import icons from './index' | ||
import { callable, pxToRem } from '../../../../lib' | ||
import { pxToRem } from '../../../../lib' | ||
import { ComponentSlotStylesInput, ICSSInJSStyle, FontIconSpec } from '../../../types' | ||
import { ResultOf } from '../../../../types' | ||
import { IconXSpacing, IconProps } from '../../../../components/Icon/Icon' | ||
import { IconVariables } from './iconVariables' | ||
|
||
const getDefaultFontIcon = (iconName: string) => { | ||
return callable(icons(iconName).icon)() | ||
} | ||
|
||
const getFontStyles = ( | ||
size: number, | ||
iconName: string, | ||
themeIcon?: ResultOf<FontIconSpec>, | ||
): ICSSInJSStyle => { | ||
const { fontFamily, content } = themeIcon || getDefaultFontIcon(iconName) | ||
const sizeInRems = pxToRem(size) | ||
|
||
return { | ||
fontFamily, | ||
fontSize: sizeInRems, | ||
lineHeight: 1, | ||
|
||
display: 'inline-flex', | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
|
||
width: sizeInRems, | ||
height: sizeInRems, | ||
|
||
'::before': { | ||
content, | ||
}, | ||
} | ||
} | ||
import { emptyIcon } from './iconNames' | ||
|
||
const getXSpacingStyles = (xSpacing: IconXSpacing, horizontalSpace: string): ICSSInJSStyle => { | ||
switch (xSpacing) { | ||
|
@@ -61,27 +31,39 @@ const getPaddedStyle = (): ICSSInJSStyle => ({ | |
}) | ||
|
||
const iconStyles: ComponentSlotStylesInput<IconProps, IconVariables> = { | ||
root: ({ props: p, variables: v, theme }): ICSSInJSStyle => { | ||
const iconSpec = theme.icons[p.name] | ||
const rtl = theme.rtl | ||
const isFontBased = p.name && (!iconSpec || !iconSpec.isSvg) | ||
root: ({ props: p, variables: v }): ICSSInJSStyle => ({ | ||
speak: 'none', | ||
verticalAlign: 'middle', | ||
|
||
...getXSpacingStyles(p.xSpacing, v.horizontalSpace), | ||
|
||
...(p.bordered && getBorderedStyles(v.borderColor)), | ||
...(p.circular && { ...getPaddedStyle(), borderRadius: '50%' }), | ||
...(p.disabled && { | ||
color: v.disabledColor, | ||
}), | ||
}), | ||
fontRoot: ({ props: p, variables: v, theme: t }): ICSSInJSStyle => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now we have separate roots for SVG and font icons that allows to apply overrides without conditions There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like that we have two things separated 👍 |
||
const iconSpec = t.icons[p.name] || emptyIcon | ||
mnajdova marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const icon = iconSpec.icon as ResultOf<FontIconSpec> | ||
|
||
return { | ||
display: 'inline-block', | ||
speak: 'none', | ||
verticalAlign: 'middle', | ||
|
||
alignItems: 'center', | ||
boxSizing: 'content-box', | ||
display: 'inline-flex', | ||
justifyContent: 'center', | ||
|
||
...(isFontBased && getFontStyles(16, p.name)), | ||
|
||
...getXSpacingStyles(p.xSpacing, v.horizontalSpace), | ||
|
||
...(p.circular && { ...getPaddedStyle(), borderRadius: '50%' }), | ||
fontFamily: icon.fontFamily, | ||
fontSize: v[`${p.size}Size`], | ||
lineHeight: 1, | ||
width: v[`${p.size}Size`], | ||
height: v[`${p.size}Size`], | ||
|
||
...(p.bordered && getBorderedStyles(v.borderColor)), | ||
'::before': { | ||
content: icon.content, | ||
}, | ||
|
||
transform: rtl ? `scaleX(-1) rotate(${-1 * p.rotate}deg)` : `rotate(${p.rotate}deg)`, | ||
transform: t.rtl ? `scaleX(-1) rotate(${-1 * p.rotate}deg)` : `rotate(${p.rotate}deg)`, | ||
} | ||
}, | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're using FA on docs, but we don't to have this theme in any other even in
base