Skip to content

Commit

Permalink
new
Browse files Browse the repository at this point in the history
  • Loading branch information
AlbertCarreras committed Sep 22, 2021
1 parent 6940df8 commit 420658b
Show file tree
Hide file tree
Showing 7 changed files with 408 additions and 160 deletions.
9 changes: 8 additions & 1 deletion docs/components/sidebarIndex.js
Expand Up @@ -27,7 +27,14 @@ const sidebarIndex: Array<sidebarIndexType> = [
},
{
sectionName: 'Guidelines',
pages: ['Accessibility', 'Design Tokens', 'Color', 'Layouts', 'Screen Sizes'],
pages: [
'Accessibility',
'Design Tokens',
'Color',
'Iconography and SVGs',
'Layouts',
'Screen Sizes',
],
},
{
sectionName: 'Foundation',
Expand Down
27 changes: 0 additions & 27 deletions docs/pages/faq.js
Expand Up @@ -212,33 +212,6 @@ yarn cypress run
</Card>,
);

card(
<MainSection name="Icons and SVGs">
<MainSection.Subsection
description={`
If you need a new icon for an experiment that is not listed on our [Icon](/Icon) documentation, use the \`dangerouslySetSvgPath\` prop on [Icon](/Icon), [IconButton](/IconButton), and [Pog](/Pog). However, \`dangerouslySetSvgPath\` only works with one SVG path. For icons with multiple paths and groups, use [Box](/Box) and \`dangerouslySetInlineStyle\` to pass the custom icon as \`backgroundImage\`.
Once your experiment ships to 100%, ask your designer to follow the directions in the [Icon kit](https://www.figma.com/file/N60WnDx9j6Moz3Dt1rNsq9/Icon-Kit). Once the asset is ready, we can add the Icon to Gestalt.
We recommend streamlining (removing strokes, transforms, ...) and optimizing the SVGs to improve the performance and the pinner experience using the tools [svgo](https://github.com/svg/svgo) or [ImageOptim](https://imageoptim.com/mac)
Gestalt Icon svg files follow a particular format and use automatic file validation testing.
\`<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg">
<path d="_______________"/>
</svg>\`
We override the color in the Gestalt Icon component and Gestalt only uses the \`d\` attribute in the \`path\` tag and the basic attributes for visualizing the raw file in the \`svg\` tag . For consistency, we don't include unnecessary attributes in the \`svg\` and \`path\` tags.
Accessibility notes:
- Icons must meet the [Non-Text Contrast](https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast.html) requirement.
- Avoid using unfamiliar icons. Always refer to Gestalt available icons. A new icon needs to be user tested to evaluate comprehension.
- Some icons don’t translate well in all cultures, so it's preferred to user-test each Icon before it gets added to Gestalt.
`}
/>
</MainSection>,
);

card(
<Card name="Automated Releases">
<Flex alignItems="start" direction="column" gap={4}>
Expand Down
317 changes: 197 additions & 120 deletions docs/pages/icon.js
@@ -1,133 +1,210 @@
// @flow strict
import type { Node } from 'react';
import { Icon } from 'gestalt';
import Example from '../components/Example.js';
import PropTable from '../components/PropTable.js';
import Combination from '../components/Combination.js';
import CombinationNew from '../components/CombinationNew.js';
import PageHeader from '../components/PageHeader.js';
import CardPage from '../components/CardPage.js';
import MainSection from '../components/MainSection.js';
import GeneratedPropTable from '../components/GeneratedPropTable.js';
import Page from '../components/Page.js';
import docgen, { type DocGen } from '../components/docgen.js';

const cards: Array<Node> = [];
const card = (c) => cards.push(c);

const icons: Array<string> = Icon?.icons ?? [];

card(
<PageHeader
name="Icon"
description="
Show icons with different colors and sizes in an accessible way.
"
/>,
);

card(
<PropTable
props={[
{
name: 'accessibilityLabel',
type: 'string',
required: true,
description:
'String that clients such as VoiceOver will read to describe the element. Always localize the label.',
href: 'iconWithLabel',
},
{
name: 'color',
type: `"blue" | "darkGray" | "eggplant" | "gray" | "green" | "lightGray" | "maroon" | "midnight" | "navy" | "olive" | "orange" | "orchid" | "pine" | "purple" | "red" | "watermelon" | "white"`,
defaultValue: 'gray',
href: 'sizeColorCombinations',
},
{
name: 'icon',
type: icons.map((name) => `'${name}'`).join(' | '),
description: `This allows us to type check for a valid icon name based on the keys from the list of icons shown below.`,
href: 'iconCombinations',
},
{
name: 'size',
type: `number | string`,
description: `Use a number for pixel sizes or a string for percentage based sizes`,
defaultValue: 16,
href: 'sizeColorCombinations',
},
{
name: 'inline',
type: 'boolean',
defaultValue: false,
},
{
name: 'dangerouslySetSvgPath',
type: `{ __path: string }`,
description: `When using this prop, make sure that the viewbox around the SVG path is 24x24`,
},
]}
/>,
);

card(
<MainSection name="Usage guidelines">
<MainSection.Subsection columns={2}>
<MainSection.Card
cardSize="md"
type="do"
title="When to Use"
description={`
- As symbolic communication for elements that do not have room for text, like number of pins in a carousel. In this case, ensure the icon choice is easily recognizable and makes sense to international users.
- To convey a critical meaning that cannot be communicated with words, like a downward chevron in a Button to indicate it reveals a menu.
`}
export default function IconPage({ generatedDocGen }: {| generatedDocGen: DocGen |}): Node {
return (
<Page title="Icon">
<PageHeader
name="Icon"
description="Icons are the symbolic representation of an action or information, providing visual context and improving usability."
defaultCode={`
<Flex gap={1}>
<Icon icon="pin" accessibilityLabel="Pin" color="darkGray" />
<Text align="center" color="darkGray" weight="bold">
Pinterest
</Text>
</Flex>`}
/>
<MainSection.Card
cardSize="md"
type="don't"
title="When Not to Use"
description={`
- For purposes that are decorative or for visual embellishment, such as how illustrations are typically used. Contact us if this is needed.
- As a visual reinforcement for associated text, without adding new meaning.
- To communicate status or health. Use [Status](/status) instead.
- As an interactive element (e.g., utilizing hover, focus, click/tap). Use [IconButton](/iconbutton) instead.
`}
/>
</MainSection.Subsection>
</MainSection>,
);
<GeneratedPropTable generatedDocGen={generatedDocGen} />
<MainSection name="Usage guidelines">
<MainSection.Subsection columns={2}>
<MainSection.Card
cardSize="md"
type="do"
title="When to Use"
description={`
- As symbolic communication for elements that do not have room for text, like the number of pins in a carousel. In this case, ensure the icon choice is easily recognizable and makes sense to international users.
- To convey a critical meaning that cannot be communicated with words, like a downward chevron in a Button to indicate it reveals a menu.
- To help with quick scanning by adding rhythm and hierarchy to the design.`}
/>
<MainSection.Card
cardSize="md"
type="don't"
title="When Not to Use"
description={`
- For purposes that are decorative or for visual embellishment, such as how illustrations are typically used. Contact us if this is needed.
- As a visual reinforcement for associated text, without adding new meaning.
- To communicate status or health. Use [Status](/status) instead.
- As an interactive element (e.g., utilizing hover, focus, click/tap). Use [IconButton](/iconbutton) instead.`}
/>
</MainSection.Subsection>
</MainSection>
<MainSection name="Best practices">
<MainSection.Subsection columns={2}>
<MainSection.Card
cardSize="md"
type="do"
description="Use icons intentionally, ensuring the Icon choice is easily recognizable and makes sense in the context. "
defaultCode={`
<Flex gap={1}>
<Icon icon="eye" accessibilityLabel="Number of views" color="darkGray" />
<Text weight="bold" size="lg">4</Text>
</Flex>`}
/>
<MainSection.Card
cardSize="md"
type="don't"
description="Repurpose icons. Using icons for their intended meaning supports good comprehension."
defaultCode={`
<Flex gap={2}>
<Icon icon="sound" accessibilityLabel="" color="darkGray" />
<Text size="lg" weight="bold">24 monthly views</Text>
</Flex>`}
/>
<MainSection.Card
cardSize="md"
type="do"
description="Pair text and icons when possible to provide better clarity."
defaultCode={`
<Flex gap={1}>
<Icon icon="tag" accessibilityLabel="" color="darkGray" />
<Text size="lg" weight="bold">
Shopping spotlight
</Text>
</Flex>`}
/>
<MainSection.Card
cardSize="md"
type="don't"
description="Don't create interactive Icons using TapArea. Use [IconButton](/iconbutton) instead."
defaultCode={`
<Tooltip text="Pinterest">
<TapArea>
<Icon icon="share" accessibilityLabel="" color="darkGray" />
</TapArea>
</Tooltip>
`}
/>
</MainSection.Subsection>
</MainSection>
<MainSection
name="Accessibility"
description="Icons are a great way to help users who have difficulties with reading, focus attention, and low vision impairments."
>
<MainSection.Subsection
title="ARIA attributes"
columns={2}
description={`
If the icon appears without text, the Icon requires \`accessibilityLabel\`, a text description for screen readers to announce and communicate the represented [Icon](/Icon), as shown in the first example.
Avoid using the generic words like "image" or "icon"; instead, use verbs that describe the meaning of the icon, for example: “pins".
card(
<Example
id="iconWithLabel"
description="Icon with a label"
name="Example"
defaultCode={`
<Box alignItems="center" display="flex">
<Box marginEnd={1} padding={1}>
<Icon icon="pin" accessibilityLabel="Pin" color="darkGray" />
</Box>
<Text align="center" color="darkGray" weight="bold">
Pinterest
If an icon has a visible label that describes what the icon represents, \`accessibilityLabel\` can be an empty string, as shown in the second example.
`}
>
<MainSection.Card
cardSize="md"
defaultCode={`
<Flex gap={1}>
<Icon icon="tag" accessibilityLabel="" color="darkGray" />
<Text align="center" weight="bold">
Shopping spotlight
</Text>
</Flex>`}
/>
<MainSection.Card
cardSize="md"
defaultCode={`
<Flex gap={1}>
<Icon icon="tag" accessibilityLabel="" color="darkGray" />
<Text align="center" weight="bold">
Shopping spotlight
</Text>
</Box>
</Flex>`}
/>
</MainSection.Subsection>
<MainSection.Subsection
title="Legibility and touch area"
description="Ensure that icons use a contrast ratio of 4.5:1 between icon color and background color."
/>
</MainSection>
<MainSection name="Localization" description="Be sure to localize `accessibilityLabel`." />
<MainSection name="Variants">
<MainSection.Subsection title="Primary-color combinations">
<CombinationNew color={['gray', 'darkGray', 'red']}>
{({ color }) => <Icon icon="heart" accessibilityLabel="" color={color} />}
</CombinationNew>
</MainSection.Subsection>
<MainSection.Subsection
title="Size"
description={`
These are the guidelines for icon sizes (in px):
1. \`12\`
Used sparingly in tight spaces. When possible, use a text label next to the icon, as it can be hard to see for visually impaired people. |
2. \`16\`
Used often any time an icon is needed. Default icon size.
3. \`24\`
Used frequently any time an icon is needed.
4. \`32\`
Used occasionally, on more dense UI.
5. \`32+\`
Should be used sparingly and only in places where the UI is very dense and a larger icon is required.
`}
/>,
);

card(
<Combination id="iconCombinations" name="Icon Combinations" icon={icons}>
{(props) => <Icon color="darkGray" accessibilityLabel="" size={32} {...props} />}
</Combination>,
);
/>
</MainSection>
<MainSection name="Writing">
<MainSection.Subsection columns={2}>
<MainSection.Card
cardSize="md"
type="do"
description={`
- Use a descriptive label to describe the Icon
- Be succinct. Exclude unnecessary words.
- Be informative and accurate
- Write in the active voice
- Avoid technical jargon
`}
/>
<MainSection.Card
cardSize="md"
type="don't"
description={`
- Use the words "image" or "icon" in the description label; instead, use words that indicate the purpose of the icon.
`}
/>
</MainSection.Subsection>
</MainSection>
<MainSection name="Related">
<MainSection.Subsection
description={`
**[IconButton](/IconButton)**
Use IconButton when only an icon is needed to represent an action instead of text.
card(
<Combination
id="sizeColorCombinations"
name="Size & Color Combinations"
size={[16, 24, 32]}
color={['gray', 'darkGray', 'red']}
>
{(props, i) => <Icon key={i} icon="heart" accessibilityLabel="" {...props} />}
</Combination>,
);
**[Button](/Button)**
Use Button to allow users to take an action.
`}
/>
</MainSection>
</Page>
);
}

export default function IconPage(): Node {
return <CardPage cards={cards} page="Icon" />;
export async function getStaticProps(): Promise<{| props: {| generatedDocGen: DocGen |} |}> {
const generatedDocGen = await docgen('Icon');
if (generatedDocGen?.props?.icon?.flowType) {
generatedDocGen.props.icon.flowType = {
name: 'union',
raw: (Icon?.icons ?? []).map((icon) => `'${icon}'`).join(' | '),
};
}
return {
props: { generatedDocGen },
};
}

0 comments on commit 420658b

Please sign in to comment.