-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ff16fc8
commit 2ba3db9
Showing
3 changed files
with
1,487 additions
and
386 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,77 +1,89 @@ | ||
import React from 'react'; | ||
import { styled } from '@storybook/theming'; | ||
import { storiesOf } from '@storybook/react'; | ||
import { styled, css } from '@storybook/theming'; | ||
|
||
import { Icons } from './icon'; | ||
import { icons, IconKey } from './icons'; | ||
import { icons } from './icons'; | ||
|
||
const Meta = styled.div({ | ||
color: '#333', | ||
fontSize: 12, | ||
}); | ||
const Meta = styled.div` | ||
color: #666; | ||
font-size: 12px; | ||
`; | ||
|
||
interface ItemProps { | ||
minimal?: boolean; | ||
} | ||
const Item = styled.li<{ minimal?: boolean }>` | ||
display: inline-flex; | ||
flex-direction: row; | ||
align-items: center; | ||
flex: 0 1 16%; | ||
min-width: 120px; | ||
margin: 16px; | ||
const Item = styled.div<ItemProps>( | ||
{ | ||
display: 'inline-flex', | ||
flexDirection: 'row', | ||
alignItems: 'center', | ||
flex: '0 1 20%', | ||
minWidth: 120, | ||
svg { | ||
margin-right: 6px; | ||
width: 14px; | ||
height: 14px; | ||
} | ||
padding: '0px 7.5px 20px', | ||
${(props) => | ||
props.minimal && | ||
css` | ||
flex: none; | ||
min-width: auto; | ||
padding: 0; | ||
margin: 16px; | ||
'& svg': { | ||
marginRight: 10, | ||
width: 24, | ||
height: 24, | ||
}, | ||
}, | ||
({ minimal }) => | ||
minimal | ||
? { | ||
flex: 'none', | ||
minWidth: 'auto', | ||
padding: 0, | ||
background: '#fff', | ||
border: '1px solid #666', | ||
svg { | ||
display: block; | ||
margin-right: 0; | ||
width: 14px; | ||
height: 14px; | ||
} | ||
`}; | ||
`; | ||
|
||
'& svg': { | ||
display: 'block', | ||
marginRight: 0, | ||
width: 48, | ||
height: 48, | ||
}, | ||
} | ||
: {} | ||
); | ||
const List = styled.ul` | ||
display: flex; | ||
flex-flow: row wrap; | ||
list-style: none; | ||
padding: 0; | ||
margin: 0; | ||
`; | ||
|
||
const Header = styled.h2` | ||
font-size: 16px; | ||
margin: 16px; | ||
`; | ||
|
||
const List = styled.div({ | ||
display: 'flex', | ||
flexFlow: 'row wrap', | ||
}); | ||
export default { | ||
title: 'Basics/Icon', | ||
component: Icons, | ||
}; | ||
|
||
const list = Object.keys(icons).sort() as IconKey[]; | ||
export const Basic = (args) => <Icons {...args} />; | ||
Basic.args = { icon: 'watch' }; | ||
|
||
storiesOf('Basics/Icon', module) | ||
.add('labels', () => ( | ||
export const Labels = () => ( | ||
<> | ||
<Header>{Object.keys(icons).length} icons</Header> | ||
<List> | ||
{list.map((key) => ( | ||
{Object.keys(icons).map((key) => ( | ||
<Item key={key}> | ||
<Icons icon={key} /> <Meta>{key}</Meta> | ||
<Icons icon={key as keyof typeof icons} aria-hidden /> | ||
<Meta>{key}</Meta> | ||
</Item> | ||
))} | ||
</List> | ||
)) | ||
.add('no labels', () => ( | ||
</> | ||
); | ||
|
||
export const NoLabels = () => ( | ||
<> | ||
<Header>{Object.keys(icons).length} icons</Header> | ||
<List> | ||
{list.map((key) => ( | ||
{Object.keys(icons).map((key) => ( | ||
<Item minimal key={key}> | ||
<Icons icon={key} /> | ||
<Icons icon={key as keyof typeof icons} aria-label={key} /> | ||
</Item> | ||
))} | ||
</List> | ||
)); | ||
</> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,54 @@ | ||
import React, { ComponentProps, memo } from 'react'; | ||
import React, { FunctionComponent, ComponentProps, memo } from 'react'; | ||
import { styled } from '@storybook/theming'; | ||
import icons, { IconKey } from './icons'; | ||
import { icons, IconKey } from './icons'; | ||
|
||
import Svg from './svg'; | ||
const Svg = styled.svg` | ||
display: inline-block; | ||
shape-rendering: inherit; | ||
transform: translate3d(0, 0, 0); | ||
vertical-align: middle; | ||
const Path = styled.path({ | ||
fill: 'currentColor', | ||
}); | ||
path { | ||
fill: currentColor; | ||
} | ||
`; | ||
|
||
export interface IconsProps extends ComponentProps<typeof Svg> { | ||
icon?: IconKey; | ||
symbol?: IconKey; | ||
/** | ||
* An Icon is a piece of visual element, but we must ensure its accessibility while using it. | ||
* It can have 2 purposes: | ||
* | ||
* - *decorative only*: for example, it illustrates a label next to it. We must ensure that it is ignored by screen readers, by setting `aria-hidden` attribute (ex: `<Icon icon="check" aria-hidden />`) | ||
* - *non-decorative*: it means that it delivers information. For example, an icon as only child in a button. The meaning can be obvious visually, but it must have a proper text alternative via `aria-label` for screen readers. (ex: `<Icon icon="print" aria-label="Print this document" />`) | ||
*/ | ||
export interface IconProps { | ||
icon: IconType; | ||
symbol?: IconType; | ||
} | ||
|
||
// TODO: if we can resize the 1024 to 20, we can remove the size attributes | ||
export const Icons = memo<IconsProps>(({ icon, symbol, ...props }) => ( | ||
<Svg viewBox="0 0 1024 1024" {...props}> | ||
{symbol ? <use xlinkHref={`#icon--${symbol}`} /> : <Path d={icons[icon]} />} | ||
</Svg> | ||
)); | ||
export const Icons: FunctionComponent<IconProps> = ({ icon, symbol, ...props }: IconProps) => { | ||
return ( | ||
<Svg viewBox="0 0 14 14" width="14px" height="14px" {...props}> | ||
{symbol ? <use xlinkHref={`#icon--${symbol}`} /> : icons[icon]} | ||
</Svg> | ||
); | ||
}; | ||
|
||
export type IconType = keyof typeof icons; | ||
|
||
export interface SymbolsProps extends ComponentProps<typeof Svg> { | ||
icons?: IconKey[]; | ||
} | ||
|
||
export const Symbols = memo<SymbolsProps>(({ icons: keys = Object.keys(icons) }) => ( | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
<Svg | ||
viewBox="0 0 14 14" | ||
style={{ position: 'absolute', width: 0, height: 0 }} | ||
data-chromatic="ignore" | ||
> | ||
{keys.map((key: IconKey) => ( | ||
<symbol id={`icon--${key}`} key={key}> | ||
<Path d={icons[key]} /> | ||
{icons[key]} | ||
</symbol> | ||
))} | ||
</svg> | ||
</Svg> | ||
)); |
Oops, something went wrong.