├── .circleci
└── config.yml
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .github
└── workflows
│ ├── chromatic.yml
│ ├── release.yml
│ └── type-checking.yml
├── .gitignore
├── .node-version
├── .nvmrc
├── .storybook
├── main.ts
├── preview.tsx
└── static
│ └── chromatic-logo-square.png
├── .travis.yml
├── .vscode
└── settings.json
├── .yarnrc
├── CHANGELOG.md
├── README.md
├── babel.config.js
├── build-storybook.log
├── package.json
├── prettier.config.js
├── src
├── .eslintrc
├── Intro.mdx
├── components
│ ├── Avatar.stories.tsx
│ ├── Avatar.tsx
│ ├── AvatarList.stories.js
│ ├── AvatarList.tsx
│ ├── Badge.stories.tsx
│ ├── Badge.tsx
│ ├── Button.stories.tsx
│ ├── Button.tsx
│ ├── ButtonAction.stories.tsx
│ ├── ButtonAction.tsx
│ ├── ButtonToggle.stories.tsx
│ ├── ButtonToggle.tsx
│ ├── Cardinal.stories.tsx
│ ├── Cardinal.tsx
│ ├── Checkbox.stories.tsx
│ ├── Checkbox.tsx
│ ├── CodeSnippets.stories.tsx
│ ├── CodeSnippets.tsx
│ ├── Color.mdx
│ ├── FormErrorState.stories.tsx
│ ├── FormErrorState.tsx
│ ├── Highlight.stories.tsx
│ ├── Highlight.tsx
│ ├── Icon.stories.tsx
│ ├── Icon.tsx
│ ├── Input.stories.tsx
│ ├── Input.tsx
│ ├── Link.stories.tsx
│ ├── Link.tsx
│ ├── LinkTabs.stories.tsx
│ ├── LinkTabs.tsx
│ ├── OutlineCTA.stories.tsx
│ ├── OutlineCTA.tsx
│ ├── ProgressDots.stories.tsx
│ ├── ProgressDots.tsx
│ ├── Radio.stories.tsx
│ ├── Radio.tsx
│ ├── Select.stories.tsx
│ ├── Select.tsx
│ ├── ShadowBoxCTA.stories.tsx
│ ├── ShadowBoxCTA.tsx
│ ├── SharedStyles.stories.tsx
│ ├── Spinner.stories.tsx
│ ├── Spinner.tsx
│ ├── StoryLinkWrapper.tsx
│ ├── Subheading.stories.tsx
│ ├── Subheading.tsx
│ ├── Textarea.stories.tsx
│ ├── Textarea.tsx
│ ├── Typography.mdx
│ ├── TypographyStyles.stories.tsx
│ ├── clipboard
│ │ ├── Clipboard.stories.tsx
│ │ ├── Clipboard.tsx
│ │ ├── ClipboardCode.stories.tsx
│ │ ├── ClipboardCode.tsx
│ │ ├── ClipboardIcon.stories.tsx
│ │ ├── ClipboardIcon.tsx
│ │ ├── ClipboardInput.stories.tsx
│ │ └── ClipboardInput.tsx
│ ├── global.d.ts
│ ├── header
│ │ ├── Header.stories.tsx
│ │ ├── Header.tsx
│ │ ├── HeaderContext.ts
│ │ ├── Nav.tsx
│ │ ├── NavItem.tsx
│ │ └── NavLink.tsx
│ ├── index.tsx
│ ├── modal
│ │ ├── Modal.stories.tsx
│ │ ├── Modal.tsx
│ │ ├── WithModal.stories.tsx
│ │ └── WithModal.tsx
│ ├── shared
│ │ ├── animation.ts
│ │ ├── global.tsx
│ │ ├── icons.tsx
│ │ └── styles.ts
│ ├── table-of-contents
│ │ ├── BulletLink.stories.tsx
│ │ ├── BulletLink.tsx
│ │ ├── ItemLink.stories.tsx
│ │ ├── ItemLink.tsx
│ │ ├── MenuLink.stories.tsx
│ │ ├── MenuLink.tsx
│ │ ├── TableOfContents.stories.tsx
│ │ ├── TableOfContents.tsx
│ │ └── TableOfContentsItems.tsx
│ ├── tag
│ │ ├── TagItem.stories.tsx
│ │ ├── TagItem.tsx
│ │ ├── TagLink.stories.tsx
│ │ ├── TagLink.tsx
│ │ ├── TagList.stories.tsx
│ │ └── TagList.tsx
│ └── tooltip
│ │ ├── ListItem.stories.tsx
│ │ ├── ListItem.tsx
│ │ ├── Tooltip.stories.tsx
│ │ ├── Tooltip.tsx
│ │ ├── TooltipLinkList.stories.tsx
│ │ ├── TooltipLinkList.tsx
│ │ ├── TooltipMessage.stories.tsx
│ │ ├── TooltipMessage.tsx
│ │ ├── TooltipNote.stories.tsx
│ │ ├── TooltipNote.tsx
│ │ ├── WithTooltip.stories.tsx
│ │ └── WithTooltip.tsx
├── design-system.png
├── images
│ ├── Chrome.tsx
│ ├── Firefox.tsx
│ ├── Ie.tsx
│ ├── Illustrations.stories.tsx
│ ├── Safari.tsx
│ ├── chrome.svg
│ ├── colored-icons
│ │ ├── Accessibility.tsx
│ │ ├── Assign.tsx
│ │ ├── Bell.tsx
│ │ ├── Boxmodel.tsx
│ │ ├── Branch.tsx
│ │ ├── Browsers.tsx
│ │ ├── Bug.tsx
│ │ ├── Catalog.tsx
│ │ ├── Check.tsx
│ │ ├── Code.tsx
│ │ ├── CodeBrackets.tsx
│ │ ├── Colors.tsx
│ │ ├── Comments.tsx
│ │ ├── Components.tsx
│ │ ├── CustomAddon.tsx
│ │ ├── Delete.tsx
│ │ ├── Detect.tsx
│ │ ├── Direction.tsx
│ │ ├── Document.tsx
│ │ ├── DocumentAlt.tsx
│ │ ├── Email.tsx
│ │ ├── Error.tsx
│ │ ├── Eye.tsx
│ │ ├── FastForward.svg
│ │ ├── FastForward.tsx
│ │ ├── Flow.tsx
│ │ ├── Group.tsx
│ │ ├── Ignore.tsx
│ │ ├── Interact.tsx
│ │ ├── Interface.tsx
│ │ ├── Key.tsx
│ │ ├── Knob.tsx
│ │ ├── Lightning.tsx
│ │ ├── Link.tsx
│ │ ├── Overlap.tsx
│ │ ├── Pixel.tsx
│ │ ├── Plugin.tsx
│ │ ├── Plus.tsx
│ │ ├── Projects.tsx
│ │ ├── Redo.svg
│ │ ├── Redo.tsx
│ │ ├── Repo.tsx
│ │ ├── Review.tsx
│ │ ├── Rewind.tsx
│ │ ├── Runtest.tsx
│ │ ├── Scale.tsx
│ │ ├── Search.tsx
│ │ ├── Shield.tsx
│ │ ├── Soc2.tsx
│ │ ├── Stack.tsx
│ │ ├── Stoplight.tsx
│ │ ├── Testflake.tsx
│ │ ├── Testpyramid.tsx
│ │ ├── Text.tsx
│ │ ├── Turbo.tsx
│ │ ├── Undo.tsx
│ │ ├── Unignore.tsx
│ │ ├── Update.tsx
│ │ ├── accessibility.svg
│ │ ├── assign.svg
│ │ ├── bell.svg
│ │ ├── boxmodel.svg
│ │ ├── branch.svg
│ │ ├── browsers.svg
│ │ ├── bug.svg
│ │ ├── catalog.svg
│ │ ├── check.svg
│ │ ├── code-brackets.svg
│ │ ├── code.svg
│ │ ├── colors.svg
│ │ ├── comments.svg
│ │ ├── components.svg
│ │ ├── custom-addon.svg
│ │ ├── delete.svg
│ │ ├── detect.svg
│ │ ├── direction.svg
│ │ ├── document-alt.svg
│ │ ├── document.svg
│ │ ├── email.svg
│ │ ├── error.svg
│ │ ├── eye.svg
│ │ ├── flow.svg
│ │ ├── group.svg
│ │ ├── ignore.svg
│ │ ├── index.tsx
│ │ ├── interact.svg
│ │ ├── interface.svg
│ │ ├── key.svg
│ │ ├── knob.svg
│ │ ├── lightning.svg
│ │ ├── link.svg
│ │ ├── overlap.svg
│ │ ├── pixel.svg
│ │ ├── plugin.svg
│ │ ├── plus.svg
│ │ ├── projects.svg
│ │ ├── repo.svg
│ │ ├── review.svg
│ │ ├── rewind.svg
│ │ ├── runtest.svg
│ │ ├── scale.svg
│ │ ├── search.svg
│ │ ├── shield.svg
│ │ ├── soc2.svg
│ │ ├── stack.svg
│ │ ├── stoplight.svg
│ │ ├── testflake.svg
│ │ ├── testpyramid.svg
│ │ ├── text.svg
│ │ ├── turbo.svg
│ │ ├── undo.svg
│ │ ├── unignore.svg
│ │ └── update.svg
│ ├── firefox.svg
│ ├── ie.svg
│ ├── index.tsx
│ ├── logos
│ │ ├── Chromatic.tsx
│ │ ├── ChromaticInverted.tsx
│ │ ├── Circleci.tsx
│ │ ├── Netlify.tsx
│ │ ├── Storybook.tsx
│ │ ├── StorybookIcon.tsx
│ │ ├── StorybookInverted.tsx
│ │ ├── StorybookMonochrome.tsx
│ │ ├── StorybookMonochromeInverse.tsx
│ │ ├── chromatic-inverted.svg
│ │ ├── chromatic.svg
│ │ ├── circleci.svg
│ │ ├── index.tsx
│ │ ├── netlify.svg
│ │ ├── storybook-icon.svg
│ │ ├── storybook-inverted.svg
│ │ ├── storybook-monochrome-inverse.svg
│ │ ├── storybook-monochrome.svg
│ │ └── storybook.svg
│ └── safari.svg
├── index.tsx
├── styles.css
├── test.js
└── utils
│ ├── index.ts
│ └── loadFontsForStorybook.ts
├── svgr.config.js
├── tsconfig.json
└── yarn.lock
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | jobs:
4 | lint:
5 | docker:
6 | - image: cimg/node:16.17.1
7 | working_directory: ~/repo
8 | steps:
9 | - checkout
10 | - restore_cache:
11 | keys:
12 | - v1-dependencies-{{ checksum "package.json" }}
13 | - v1-dependencies-
14 | - run: yarn install
15 | - run: yarn lint
16 | build:
17 | docker:
18 | - image: cimg/node:16.17.1
19 | working_directory: ~/repo
20 | steps:
21 | - checkout
22 | - restore_cache:
23 | keys:
24 | - v1-dependencies-{{ checksum "package.json" }}
25 | - v1-dependencies-
26 | - run: yarn install
27 | - save_cache:
28 | paths:
29 | - node_modules
30 | key: v1-dependencies-{{ checksum "package.json" }}
31 |
32 | - run: yarn build
33 | - run: yarn build-storybook
34 |
35 | workflows:
36 | version: 2
37 | lint-build:
38 | jobs:
39 | - build
40 | - lint
41 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/**/*.js
2 | storybook-static/**/*.js
3 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ['@storybook/eslint-config-storybook', 'plugin:storybook/recommended'],
4 | parserOptions: {
5 | project: ['./tsconfig.json'],
6 | createDefaultProgram: true,
7 | },
8 | overrides: [
9 | {
10 | files: ['**/*.tsx'],
11 | rules: {
12 | 'react/prop-types': 'off',
13 | 'react/require-default-props': 'off',
14 | 'react/default-props-match-prop-types': 'off',
15 | },
16 | },
17 | ],
18 | settings: {
19 | jest: {
20 | version: 'latest',
21 | },
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/.github/workflows/chromatic.yml:
--------------------------------------------------------------------------------
1 | name: "Chromatic"
2 | on:
3 | push
4 |
5 | jobs:
6 | test:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v1
10 | - name: Use Node.js 16.17.1
11 | uses: actions/setup-node@v3
12 | with:
13 | node-version: 16.17.1
14 | - run: |
15 | yarn
16 | - run: |
17 | yarn build
18 | - run: |
19 | yarn build-storybook
20 | - uses: chromaui/action@v1
21 | with:
22 | projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
23 | token: ${{ secrets.GITHUB_TOKEN }}
24 | storybookBuildDir: storybook-static
25 |
26 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on: [push]
4 |
5 | jobs:
6 | release:
7 | runs-on: ubuntu-latest
8 | if: "!contains(github.event.head_commit.message, 'ci skip') && !contains(github.event.head_commit.message, 'skip ci')"
9 | steps:
10 | - uses: actions/checkout@v2
11 |
12 | - name: Prepare repository
13 | run: git fetch --unshallow --tags
14 |
15 | - name: Use Node.js 16.17.1
16 | uses: actions/setup-node@v3
17 | with:
18 | node-version: 16.17.1
19 |
20 | - name: Install dependencies
21 | uses: bahmutov/npm-install@v1
22 |
23 | - name: Create Release
24 | env:
25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
27 | run: |
28 | yarn release
29 |
--------------------------------------------------------------------------------
/.github/workflows/type-checking.yml:
--------------------------------------------------------------------------------
1 | name: "Type Checking"
2 | on:
3 | push
4 |
5 | jobs:
6 | test:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v1
10 | - run: |
11 | yarn
12 | - run: |
13 | yarn typescript:check
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # See https://help.github.com/ignore-files/ for more about ignoring files.
3 |
4 | # dependencies
5 | node_modules
6 |
7 | # builds
8 | build
9 | dist
10 | .rpt2_cache
11 | storybook-static
12 | .cache
13 |
14 | # misc
15 | .DS_Store
16 | .env
17 | .env.local
18 | .env.development.local
19 | .env.test.local
20 | .env.production.local
21 |
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 |
26 | # we use yarn
27 | package-lock.json
--------------------------------------------------------------------------------
/.node-version:
--------------------------------------------------------------------------------
1 | v12.14.1
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | v12.14.1
--------------------------------------------------------------------------------
/.storybook/main.ts:
--------------------------------------------------------------------------------
1 | import type { StorybookConfig } from '@storybook/react-webpack5';
2 |
3 | const config: StorybookConfig = {
4 | stories: ['../src/**/*.mdx', '../src/**/*.stories.js', '../src/**/*.stories.tsx'],
5 | addons: ['@storybook/addon-essentials', '@storybook/addon-storysource', '@storybook/addon-a11y'],
6 | framework: {
7 | name: '@storybook/react-webpack5',
8 | options: {},
9 | },
10 | docs: {
11 | autodocs: true,
12 | },
13 | staticDirs: ['./static'],
14 | };
15 |
16 | export default config;
17 |
--------------------------------------------------------------------------------
/.storybook/preview.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { loadFontsForStorybook } from '../src/utils/index';
3 | import { GlobalStyle } from '../src/components/shared/global';
4 |
5 | import type { Preview } from '@storybook/react';
6 |
7 | loadFontsForStorybook();
8 |
9 | const withGlobalStyle = (storyFn) => (
10 | <>
11 |
12 | {storyFn()}
13 | >
14 | );
15 |
16 | const preview: Preview = {
17 | parameters: {
18 | // automatically create action args for all props that start with "on"
19 | actions: { argTypesRegex: '^on.*' },
20 | dependencies: {
21 | // display only dependencies/dependents that have a story in storybook
22 | // by default this is false
23 | withStoriesOnly: true,
24 |
25 | // completely hide a dependency/dependents block if it has no elements
26 | // by default this is false
27 | hideEmpty: true,
28 | },
29 | },
30 | decorators: [withGlobalStyle],
31 | }
32 |
33 | export default preview;
34 |
--------------------------------------------------------------------------------
/.storybook/static/chromatic-logo-square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/storybookjs/design-system/0c4c043e8bf956ee9aad4664383829f807b4bfaf/.storybook/static/chromatic-logo-square.png
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 9
4 | - 8
5 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "deepscan.enable": true
3 | }
--------------------------------------------------------------------------------
/.yarnrc:
--------------------------------------------------------------------------------
1 | registry "https://registry.npmjs.org/"
2 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.cache(true);
3 |
4 | return {
5 | sourceMaps: false,
6 | presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'],
7 | plugins: [
8 | '@babel/plugin-proposal-object-rest-spread',
9 | '@babel/transform-runtime',
10 | [
11 | '@emotion',
12 | {
13 | sourceMap: false,
14 | importMap: {
15 | '@storybook/theming': {
16 | styled: { canonicalImport: ['@emotion/styled', 'default'] },
17 | css: { canonicalImport: ['@emotion/react', 'css'] },
18 | Global: { canonicalImport: ['@emotion/react', 'Global'] },
19 | },
20 | },
21 | },
22 | ],
23 | ],
24 | };
25 | };
26 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | const base = require('@storybook/linter-config/prettier.config');
2 |
3 | module.exports = {
4 | ...base,
5 | arrowParens: 'always',
6 | overrides: [
7 | {
8 | files: '*.html',
9 | options: { parser: 'babel' },
10 | },
11 | ],
12 | };
13 |
--------------------------------------------------------------------------------
/src/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "jest": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/src/Intro.mdx:
--------------------------------------------------------------------------------
1 | import { Meta } from '@storybook/blocks';
2 | import designSystem from './design-system.png';
3 |
4 |
5 |
6 |
7 |
8 | # Get started
9 |
10 | Storybook Design System is a reusable component library that helps Storybook contributors build UIs faster. The goal is to make building durable UIs more productive and satisfying.
11 |
12 | ## Install
13 |
14 | SDS components are written in React, and its stories are written in [Component Story Format](https://medium.com/storybookjs/component-story-format-66f4c32366df). It requires Storybook version 5.2-beta and up.
15 |
16 | Add SDS to your project.
17 |
18 | `npm install --save @storybook/design-system`
19 |
20 | ### **Use**
21 |
22 | Import components you want into your UI
23 |
24 | `import { Button, Badge } from '@storybook/design-system';`
25 |
26 | and use them like so
27 |
28 | ```
29 | const example = () => (
30 |
31 |
32 | Cool
33 |
34 | )
35 | ```
36 |
37 | ### **Browse SDS components in your own Storybook**
38 |
39 | Once you add the package, update your .storybook/config.js to import all files ending in .stories.js.
40 |
41 | ```
42 | import { configure } from '@storybook/react';
43 | configure(require.context('../src', true, /.stories.js$/), module);
44 | ```
45 |
46 | ### **Run and develop SDS locally**
47 |
48 | Clone the [SDS GitHub project](https://github.com/storybookjs/design-system) then start Storybook.
49 |
50 | `yarn && yarn run storybook`
51 |
52 | ## Used by
53 |
54 | - [Storybook homepage](https://storybook.js.org/)
55 | - [LearnStorybook.com](https://www.learnstorybook.com/)
56 | - [ChromaticQA.com](https://www.chromaticqa.com/)
57 |
58 | Note: this package is not used in Storybook's UI, but the visual design is identical.
59 |
60 | ### **Resources**
61 |
62 | - [Introducing Storybook Design System](https://medium.com/storybookjs/introducing-storybook-design-system-23fd9b1ac3c0)
63 | - [GitHub repository](https://github.com/storybookjs/design-system)
64 |
--------------------------------------------------------------------------------
/src/components/Avatar.stories.tsx:
--------------------------------------------------------------------------------
1 | import React, { ComponentProps, FunctionComponent } from 'react';
2 |
3 | import { Avatar, AvatarType } from './Avatar';
4 |
5 | export default {
6 | title: 'Avatar',
7 | component: Avatar,
8 | args: {
9 | type: 'user',
10 | },
11 | };
12 |
13 | const Base: FunctionComponent> = ({ src, ...props }) => (
14 |
23 | );
24 |
25 | export const Large = () => ;
26 |
27 | export const Medium = () => ;
28 |
29 | export const Small = () => ;
30 |
31 | export const Tiny = () => ;
32 |
33 | export const Organization = () => (
34 |
35 | );
36 |
--------------------------------------------------------------------------------
/src/components/AvatarList.stories.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { AvatarList } from './AvatarList';
3 | import { Avatar } from './Avatar';
4 |
5 | export const users = [
6 | {
7 | id: '1',
8 | name: 'Dominic Nguyen',
9 | avatarUrl: 'https://avatars2.githubusercontent.com/u/263385',
10 | },
11 | {
12 | id: '2',
13 | name: 'Tom Coleman',
14 | avatarUrl: 'https://avatars2.githubusercontent.com/u/132554',
15 | },
16 | {
17 | id: '3',
18 | name: 'Zoltan Olah',
19 | avatarUrl: 'https://avatars0.githubusercontent.com/u/81672',
20 | },
21 | {
22 | id: '4',
23 | name: 'Tim Hingston',
24 | avatarUrl: 'https://avatars3.githubusercontent.com/u/1831709',
25 | },
26 | ];
27 |
28 | export default {
29 | title: 'AvatarList',
30 | component: AvatarList,
31 | parameters: {
32 | subcomponents: { Avatar },
33 | },
34 | excludeStories: ['users'],
35 | };
36 |
37 | export const Basic = (args) => ;
38 | Basic.args = { users };
39 |
40 | export const Short = Basic.bind();
41 | Short.args = { users: users.slice(0, 2) };
42 |
43 | export const Ellipsized = Basic.bind();
44 | Ellipsized.args = { users };
45 |
46 | export const BigUserCount = Basic.bind();
47 | BigUserCount.args = { users, userCount: 100 };
48 |
49 | export const SmallSize = Basic.bind();
50 | SmallSize.args = { users, userCount: 100, size: 'small' };
51 |
52 | export const Loading = Basic.bind();
53 | Loading.args = { users: undefined, isLoading: true };
54 |
55 | export const Empty = Basic.bind();
56 | Empty.args = { users: [] };
57 |
--------------------------------------------------------------------------------
/src/components/Badge.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Badge } from './Badge';
3 | import { Icon } from './Icon';
4 |
5 | export default {
6 | title: 'Badge',
7 | component: Badge,
8 | };
9 |
10 | export const Basic = (args) => Badge;
11 |
12 | export const All = () => (
13 |
14 | Positive
15 | Negative
16 | Neutral
17 | Error
18 | Warning
19 | Selected
20 |
21 | );
22 |
23 | export const WithIcon = () => (
24 |
25 |
26 | with icon
27 |
28 | );
29 |
--------------------------------------------------------------------------------
/src/components/Badge.tsx:
--------------------------------------------------------------------------------
1 | import { styled, css } from '@storybook/theming';
2 | import { rgba } from 'polished';
3 | import { background, color, typography } from './shared/styles';
4 |
5 | export const Badge = styled.div<{
6 | status: 'positive' | 'negative' | 'neutral' | 'error' | 'warning' | 'selected';
7 | }>`
8 | display: inline-block;
9 | vertical-align: top;
10 | font-size: ${typography.size.s1}px;
11 | line-height: 12px;
12 | padding: 4px 12px;
13 | border-radius: 3em;
14 | font-weight: ${typography.weight.bold};
15 |
16 | svg {
17 | height: 12px;
18 | width: 12px;
19 | margin-right: 4px;
20 | margin-top: -2px;
21 | }
22 |
23 | ${(props) =>
24 | props.status === 'positive' &&
25 | css`
26 | color: ${color.positive};
27 | background: ${background.positive};
28 | box-shadow: ${rgba(color.positive, 0.1)} 0 0 0 1px inset;
29 | `};
30 |
31 | ${(props) =>
32 | props.status === 'negative' &&
33 | css`
34 | color: ${color.negative};
35 | background: ${background.negative};
36 | box-shadow: ${rgba(color.negative, 0.1)} 0 0 0 1px inset;
37 | `};
38 |
39 | ${(props) =>
40 | props.status === 'warning' &&
41 | css`
42 | color: ${color.warning};
43 | background: ${background.warning};
44 | box-shadow: ${rgba(color.warning, 0.1)} 0 0 0 1px inset;
45 | `};
46 |
47 | ${(props) =>
48 | props.status === 'error' &&
49 | css`
50 | color: ${color.lightest};
51 | background: ${color.red};
52 | `};
53 |
54 | ${(props) =>
55 | props.status === 'selected' &&
56 | css`
57 | color: ${color.selected};
58 | background: ${background.calmBlue};
59 | box-shadow: ${rgba(color.selected, 0.1)} 0 0 0 1px inset;
60 | `};
61 |
62 | ${(props) =>
63 | (props.status === 'neutral' || props.status === undefined) &&
64 | css`
65 | color: ${color.darker};
66 | background: ${color.mediumlight};
67 | box-shadow: ${rgba(color.darker, 0.1)} 0 0 0 1px inset;
68 | `};
69 | `;
70 |
--------------------------------------------------------------------------------
/src/components/ButtonAction.stories.tsx:
--------------------------------------------------------------------------------
1 | import type { Meta, StoryObj } from '@storybook/react';
2 |
3 | import { ButtonAction } from './ButtonAction';
4 |
5 | const meta: Meta = {
6 | title: 'ButtonAction',
7 | component: ButtonAction,
8 | tags: ['autodocs'],
9 | };
10 |
11 | export default meta;
12 | type Story = StoryObj;
13 |
14 | export const IconOnly: Story = {
15 | args: {
16 | children: '',
17 | icon: 'starhollow',
18 | isActive: false,
19 | },
20 | };
21 |
22 | export const IconOnlyActive: Story = {
23 | args: {
24 | children: '',
25 | icon: 'starhollow',
26 | isActive: true,
27 | },
28 | };
29 |
30 | export const WithLabel: Story = {
31 | args: {
32 | children: 'Hello World',
33 | icon: 'starhollow',
34 | isActive: false,
35 | },
36 | };
37 |
38 | export const WithLabelActive: Story = {
39 | args: {
40 | children: 'Hello World',
41 | icon: 'starhollow',
42 | isActive: true,
43 | },
44 | };
45 |
46 | export const IconOnlyIsSelect: Story = {
47 | args: {
48 | children: '',
49 | icon: 'starhollow',
50 | isActive: false,
51 | isSelect: true,
52 | },
53 | };
54 |
55 | export const WithLabelIsSelect: Story = {
56 | args: {
57 | children: 'Hello World',
58 | icon: 'starhollow',
59 | isActive: false,
60 | isSelect: true,
61 | },
62 | };
63 |
64 | export const IconOnlyWithTooltip: Story = {
65 | args: {
66 | icon: 'starhollow',
67 | isActive: false,
68 | tooltip: "I'm a tooltip",
69 | },
70 | };
71 |
72 | export const WithLabelWithTooltip: Story = {
73 | args: {
74 | children: 'Hello World',
75 | icon: 'starhollow',
76 | isActive: false,
77 | tooltip: "I'm a tooltip",
78 | },
79 | };
80 |
--------------------------------------------------------------------------------
/src/components/Checkbox.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { action } from '@storybook/addon-actions';
3 |
4 | import { Checkbox } from './Checkbox';
5 |
6 | const onChange = action('change');
7 |
8 | export default {
9 | title: 'forms/Checkbox',
10 | component: Checkbox,
11 | };
12 |
13 | export const Template = (args) => ;
14 | Template.args = { label: 'Basic', hideLabel: false };
15 | Template.storyName = 'Playground';
16 |
17 | export const All = () => (
18 |
37 | );
38 |
39 | export const Unchecked = Template.bind();
40 | Unchecked.args = { id: 'Unchecked', label: 'Cats', hideLabel: true };
41 |
42 | export const Checked = Template.bind();
43 | Checked.args = { id: 'Checked', label: 'Cats', hideLabel: true, checked: true };
44 |
--------------------------------------------------------------------------------
/src/components/CodeSnippets.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { CodeSnippets } from './CodeSnippets';
4 | import { javascriptCodeWithWrappers, typescriptCodeWithWrappers } from './Highlight.stories';
5 | import { color } from './shared/styles';
6 |
7 | // The wrapper allows you to see the shadow in Chromatic
8 | const Wrapper = styled.div`
9 | padding: 20px;
10 | `;
11 |
12 | /* eslint-disable react/no-danger */
13 | function JavaScriptSnippetContent() {
14 | return ;
15 | }
16 |
17 | function TypescriptSnippetContent() {
18 | return ;
19 | }
20 | /* eslint-enable react/no-danger */
21 |
22 | const snippets = [
23 | {
24 | Snippet: JavaScriptSnippetContent,
25 | id: '1',
26 | renderTabLabel: () => 'Label 1',
27 | },
28 | {
29 | Snippet: TypescriptSnippetContent,
30 | id: '2',
31 | renderTabLabel: () => 'Label 2',
32 | },
33 | ];
34 |
35 | export default {
36 | component: CodeSnippets,
37 | decorators: [(story) => {story()}],
38 | title: 'CodeSnippets',
39 | };
40 |
41 | const Story = (args) => ;
42 |
43 | export const Single = Story.bind({});
44 | Single.args = {
45 | snippets: [snippets[0]],
46 | };
47 |
48 | export const Multiple = Story.bind({});
49 | Multiple.args = {
50 | snippets,
51 | };
52 |
53 | const PreSnippetWrapper = styled.div`
54 | padding: 10px;
55 | border-bottom: 1px solid ${color.border};
56 | background: #fdf5d3;
57 | `;
58 |
59 | export const PreSnippet = Story.bind({});
60 | PreSnippet.args = {
61 | snippets: snippets.map((snippet) => ({
62 | ...snippet,
63 | PreSnippet: () => PreSnippet content,
64 | })),
65 | };
66 |
--------------------------------------------------------------------------------
/src/components/Color.mdx:
--------------------------------------------------------------------------------
1 | import { Meta, ColorPalette, ColorItem } from '@storybook/blocks';
2 |
3 | import { color } from './shared/styles';
4 |
5 |
6 |
7 | # Colors
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
39 |
40 |
--------------------------------------------------------------------------------
/src/components/Icon.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled, css } from '@storybook/theming';
3 |
4 | import { Icon } from './Icon';
5 | import { icons } from './shared/icons';
6 |
7 | const Meta = styled.div`
8 | color: #666;
9 | font-size: 12px;
10 | `;
11 |
12 | const Item = styled.li<{ minimal?: boolean }>`
13 | display: inline-flex;
14 | flex-direction: row;
15 | align-items: center;
16 | flex: 0 1 16%;
17 | min-width: 120px;
18 | margin: 16px;
19 |
20 | svg {
21 | margin-right: 6px;
22 | width: 14px;
23 | height: 14px;
24 | }
25 |
26 | ${(props) =>
27 | props.minimal &&
28 | css`
29 | flex: none;
30 | min-width: auto;
31 | padding: 0;
32 | background: #fff;
33 | margin: 16px;
34 |
35 | svg {
36 | display: block;
37 | margin-right: 0;
38 | width: 14px;
39 | height: 14px;
40 | }
41 | `};
42 | `;
43 |
44 | const List = styled.ul`
45 | display: flex;
46 | flex-flow: row wrap;
47 | list-style: none;
48 | padding: 0;
49 | margin: 0;
50 | `;
51 |
52 | const Header = styled.h2`
53 | font-size: 16px;
54 | margin: 16px;
55 | `;
56 |
57 | export default {
58 | title: 'Icon',
59 | component: Icon,
60 | };
61 |
62 | export const Basic = (args) => ;
63 | Basic.args = { icon: 'watch' };
64 |
65 | export const Labels = () => (
66 | <>
67 | {Object.keys(icons).length} icons
68 |
69 | {Object.keys(icons).map((key) => (
70 | -
71 |
72 | {key}
73 |
74 | ))}
75 |
76 | >
77 | );
78 |
79 | export const NoLabels = () => (
80 | <>
81 | {Object.keys(icons).length} icons
82 |
83 | {Object.keys(icons).map((key) => (
84 | -
85 |
86 |
87 | ))}
88 |
89 | >
90 | );
91 |
--------------------------------------------------------------------------------
/src/components/Icon.tsx:
--------------------------------------------------------------------------------
1 | import React, { FunctionComponent } from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { icons } from './shared/icons';
4 |
5 | const Svg = styled.svg`
6 | display: inline-block;
7 | shape-rendering: inherit;
8 | transform: translate3d(0, 0, 0);
9 | vertical-align: middle;
10 |
11 | path {
12 | fill: currentColor;
13 | }
14 | `;
15 |
16 | /**
17 | * An Icon is a piece of visual element, but we must ensure its accessibility while using it.
18 | * It can have 2 purposes:
19 | *
20 | * - *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: ``)
21 | * - *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: ``)
22 | */
23 | export const Icon: FunctionComponent = ({ icon, ...props }: IconProps) => {
24 | return (
25 |
28 | );
29 | };
30 |
31 | export type IconType = keyof typeof icons;
32 |
33 | export interface IconProps {
34 | icon: IconType;
35 | }
36 |
--------------------------------------------------------------------------------
/src/components/Link.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { action } from '@storybook/addon-actions';
4 |
5 | import { Icon } from './Icon';
6 | import { Link } from './Link';
7 | // @ts-ignore
8 | import { StoryLinkWrapper } from './StoryLinkWrapper';
9 |
10 | const CustomLink = styled(Link)`
11 | && {
12 | color: red;
13 | }
14 | `;
15 |
16 | const onLinkClick = action('onLinkClick');
17 |
18 | export default {
19 | title: 'Link',
20 | component: Link,
21 | };
22 |
23 | export const Basic: React.FunctionComponent> = () => (
24 |
25 | link text
26 |
27 | );
28 |
29 | export const All = () => (
30 | <>
31 | default{' '}
32 |
33 | secondary
34 | {' '}
35 |
36 | tertiary
37 | {' '}
38 |
39 | nochrome
40 | {' '}
41 |
42 |
43 | inverse
44 |
45 |
46 | >
47 | );
48 |
49 | export const WithArrow = () => (
50 |
51 | withArrow shows an arrow behind the link
52 |
53 | );
54 |
55 | export const ContainsIcon = () => (
56 |
57 |
58 |
59 | );
60 |
61 | export const WithIcon = () => (
62 |
63 |
64 | Link with an icon in front
65 |
66 | );
67 |
68 | export const IsButton = () => (
69 | /* eslint-disable-next-line */
70 |
71 | is actually a button
72 |
73 | );
74 |
75 | export const HasLinkWrapper = () => (
76 | <>
77 |
78 | has a LinkWrapper like GatsbyLink or NextLink
79 |
80 |
81 |
82 | has a LinkWrapper like GatsbyLink or NextLink with custom styling
83 |
84 | >
85 | );
86 |
--------------------------------------------------------------------------------
/src/components/LinkTabs.stories.tsx:
--------------------------------------------------------------------------------
1 | import { action } from '@storybook/addon-actions';
2 | import React from 'react';
3 |
4 | import { LinkTabs } from './LinkTabs';
5 |
6 | const items = [
7 | { key: '1', label: 'Activity', title: 'View activity', href: '/activity' },
8 | { key: '2', label: 'Components', title: 'View components', href: '/components', isActive: true },
9 | { key: '3', label: 'Changeset', title: 'View UI changes', href: '/changes' },
10 | ];
11 |
12 | export default {
13 | title: 'LinkTabs',
14 | };
15 |
16 | export const Default = () => ;
17 | Default.storyName = 'default';
18 |
--------------------------------------------------------------------------------
/src/components/LinkTabs.tsx:
--------------------------------------------------------------------------------
1 | import React, { ComponentProps } from 'react';
2 | import { styled, css } from '@storybook/theming';
3 | import type { StyledComponent } from '@storybook/theming';
4 |
5 | import { Link } from './Link';
6 | import { color, typography } from './shared/styles';
7 | import { inlineGlow } from './shared/animation';
8 |
9 | const Wrapper = styled.ul`
10 | display: flex;
11 | list-style: none;
12 | margin: 0;
13 | padding: 0;
14 | overflow-x: auto;
15 | overflow-y: hidden;
16 |
17 | li {
18 | list-style: none;
19 | }
20 | `;
21 |
22 | interface TabProps {
23 | isLoading?: boolean;
24 | isActive?: boolean;
25 | }
26 |
27 | const Tab: StyledComponent = styled(Link)`
28 | padding: 10px 15px;
29 | line-height: 20px;
30 | font-size: ${typography.size.s2}px;
31 | font-weight: ${typography.weight.bold};
32 | color: ${color.mediumdark};
33 | white-space: nowrap;
34 |
35 | &:hover {
36 | color: ${color.secondary};
37 | }
38 |
39 | ${(props) =>
40 | props.isLoading &&
41 | css`
42 | cursor: progress !important;
43 | > * {
44 | ${inlineGlow};
45 | }
46 | `}
47 |
48 | ${(props) =>
49 | props.isActive &&
50 | !props.isLoading &&
51 | css`
52 | color: ${color.secondary};
53 | box-shadow: ${color.secondary} 0 -3px 0 0 inset;
54 | `};
55 | `;
56 |
57 | type ItemProps = {
58 | key: string;
59 | label: string;
60 | } & ComponentProps;
61 |
62 | interface LinkTabsProps {
63 | isLoading?: boolean;
64 | items: ItemProps[];
65 | }
66 |
67 | export const LinkTabs = ({
68 | isLoading = false,
69 | items = [],
70 | ...props
71 | }: LinkTabsProps & ComponentProps) => (
72 |
73 | {items.map(({ key, label, ...item }) => (
74 |
75 |
76 | {label}
77 |
78 |
79 | ))}
80 |
81 | );
82 |
--------------------------------------------------------------------------------
/src/components/OutlineCTA.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { Badge } from './Badge';
4 | import { Button } from './Button';
5 | import { Link } from './Link';
6 | import { OutlineCTA } from './OutlineCTA';
7 |
8 | // The wrapper allows you to see the shadow in Chromatic
9 | const Wrapper = styled.div`
10 | padding: 20px;
11 | `;
12 |
13 | const InlineWrapper = styled.div`
14 | display: flex;
15 | justify-content: center;
16 | `;
17 |
18 | export default {
19 | component: OutlineCTA,
20 | title: 'OutlineCTA',
21 | argTypes: {
22 | action: { control: false },
23 | badge: { control: false },
24 | },
25 | decorators: [(story) => {story()}],
26 | };
27 |
28 | const Story = (args) => ;
29 |
30 | export const Default = Story.bind({});
31 | Default.args = {
32 | action: (
33 | // eslint-disable-next-line jsx-a11y/anchor-is-valid
34 |
35 | Go to latest docs
36 |
37 | ),
38 | badge: New,
39 | children: 'These docs are for version 6.0. Newer docs are available for version 6.4.',
40 | };
41 | Default.parameters = {
42 | chromatic: { viewports: [320, 1200] },
43 | };
44 |
45 | export const NoBadge = Story.bind({});
46 | NoBadge.args = {
47 | action: Default.args.action,
48 | children: Default.args.children,
49 | };
50 |
51 | export const Inline = Story.bind({});
52 | Inline.args = {
53 | ...Default.args,
54 | action: (
55 | // eslint-disable-next-line jsx-a11y/anchor-is-valid
56 |
57 | Read more
58 |
59 | ),
60 | badge: Default.args.badge,
61 | children: 'Learn how to automate UI tests with Github Actions.',
62 | };
63 | Inline.decorators = [(story) => {story()}];
64 |
--------------------------------------------------------------------------------
/src/components/OutlineCTA.tsx:
--------------------------------------------------------------------------------
1 | import React, { ReactNode } from 'react';
2 | import { styled } from '@storybook/theming';
3 |
4 | import { breakpoint, color, spacing, typography } from './shared/styles';
5 |
6 | const OutlineCTAWrapper = styled.div`
7 | border-radius: ${spacing.borderRadius.small}px;
8 | box-shadow: ${color.border} 0 0 0 1px inset;
9 | padding: ${spacing.padding.small}px ${spacing.padding.small}px;
10 |
11 | font-size: ${typography.size.s2}px;
12 | line-height: 20px;
13 |
14 | @media (min-width: ${breakpoint}px) {
15 | flex-wrap: nowrap;
16 | justify-content: flex-start;
17 | padding: ${spacing.padding.small}px ${spacing.padding.medium}px;
18 | }
19 | `;
20 |
21 | const MessageText = styled.span`
22 | margin-left: 2px;
23 | margin-right: 2px;
24 | `;
25 |
26 | const ActionWrapper = styled.span`
27 | font-weight: ${typography.weight.bold};
28 | white-space: nowrap;
29 | `;
30 |
31 | interface Props {
32 | /** Displays after `children`; typically a [Link](/?path=/docs/link--basic) */
33 | action: ReactNode;
34 | /** Displays before `children`; should be a [Badge](/?path=/docs/badge--basic) */
35 | badge?: ReactNode;
36 | children: string;
37 | }
38 |
39 | export const OutlineCTA = ({ action, badge, children, ...rest }: Props) => (
40 |
41 | {badge} {children} {action}
42 |
43 | );
44 |
45 | OutlineCTA.defaultProps = {
46 | badge: null,
47 | };
48 |
--------------------------------------------------------------------------------
/src/components/ProgressDots.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { ProgressDots } from './ProgressDots';
3 |
4 | export default {
5 | title: 'ProgressDots',
6 | component: ProgressDots,
7 | argTypes: { steps: { control: { type: 'range', max: 10 } } },
8 | };
9 |
10 | export const Basic = (args) => ;
11 |
12 | export const Loading = Basic.bind();
13 | Loading.args = { isLoading: true };
14 |
15 | export const Starting = Basic.bind();
16 | Starting.args = { steps: 4, progress: 1 };
17 |
18 | export const Halfway = Basic.bind();
19 | Halfway.args = { steps: 4, progress: 2 };
20 |
21 | export const Complete = Basic.bind();
22 | Complete.args = { steps: 4, progress: 4 };
23 |
24 | export const LargeComplete = Basic.bind();
25 | LargeComplete.args = { steps: 4, progress: 4, size: 'large' };
26 |
--------------------------------------------------------------------------------
/src/components/ProgressDots.tsx:
--------------------------------------------------------------------------------
1 | import React, { ComponentProps, FunctionComponent } from 'react';
2 | import { styled, css } from '@storybook/theming';
3 | import { color } from './shared/styles';
4 | import { glow } from './shared/animation';
5 |
6 | const ProgressWrapper = styled.div<{ size?: 'small' | 'large' }>`
7 | display: inline-block;
8 | height: ${(props) => (props.size === 'small' ? 4 : 5)}px;
9 | `;
10 |
11 | interface DotProps {
12 | size: 'small' | 'large';
13 | active: boolean;
14 | isLoading: boolean;
15 | }
16 |
17 | const Dot = styled.div`
18 | background: ${color.medium};
19 | display: inline-block;
20 | vertical-align: top;
21 | width: ${(props) => (props.size === 'small' ? 4 : 5)}px;
22 | height: ${(props) => (props.size === 'small' ? 4 : 5)}px;
23 | border-radius: 3em;
24 | margin: 0 ${(props) => (props.size === 'small' ? 2 : 3)}px;
25 |
26 | ${(props) =>
27 | props.active &&
28 | css`
29 | background: ${color.mediumdark};
30 | `};
31 |
32 | ${(props) =>
33 | props.isLoading &&
34 | css`
35 | animation: ${glow} 1.5s ease-in-out infinite;
36 | &:nth-child(1) {
37 | animation-delay: 0s;
38 | }
39 | &:nth-child(2) {
40 | animation-delay: 0.3s;
41 | }
42 | &:nth-child(3) {
43 | animation-delay: 0.6s;
44 | }
45 | &:nth-child(4) {
46 | animation-delay: 0.9s;
47 | }
48 | `};
49 | `;
50 |
51 | interface ProgressDotsProps {
52 | isLoading?: boolean;
53 | steps?: number;
54 | progress?: number;
55 | size?: 'small' | 'large';
56 | }
57 |
58 | export const ProgressDots: FunctionComponent<
59 | ProgressDotsProps & ComponentProps
60 | > = ({ isLoading = false, steps = 4, progress = 0, size = 'small', ...rest }) => {
61 | const dots = [];
62 | for (let i = 0; i < steps; i += 1) {
63 | dots.push();
64 | }
65 | return (
66 |
73 | {dots}
74 |
75 | );
76 | };
77 |
--------------------------------------------------------------------------------
/src/components/Radio.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { action } from '@storybook/addon-actions';
3 |
4 | import { Radio } from './Radio';
5 |
6 | const onChange = action('change');
7 |
8 | export default {
9 | title: 'forms/Radio',
10 | component: Radio,
11 | };
12 |
13 | export const Template = (args) => ;
14 | Template.args = { label: 'label', hideLabel: false };
15 | Template.storyName = 'Playground';
16 |
17 | export const All = () => (
18 |
26 | );
27 |
28 | export const Unchecked = Template.bind();
29 | Unchecked.args = { id: 'Mice', label: 'Mice', hideLabel: true, value: 'mice' };
30 |
31 | export const Checked = Template.bind();
32 | Checked.args = {
33 | id: 'Dogs',
34 | label: 'Dogs',
35 | hideLabel: true,
36 | value: 'dogs',
37 | checked: true,
38 | };
39 |
--------------------------------------------------------------------------------
/src/components/ShadowBoxCTA.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { Button } from './Button';
4 | import { ShadowBoxCTA } from './ShadowBoxCTA';
5 |
6 | // The wrapper allows you to see the shadow in Chromatic
7 | const Wrapper = styled.div`
8 | padding: 20px;
9 | `;
10 |
11 | const ctaAction = ;
12 |
13 | export default {
14 | component: ShadowBoxCTA,
15 | decorators: [(story) => {story()}],
16 | title: 'ShadowBoxCTA',
17 | };
18 |
19 | const Story = (args) => ;
20 | export const Default = Story.bind({});
21 | Default.args = {
22 | action: ctaAction,
23 | headingText: 'Composite component',
24 | messageText: 'Assemble a composite component out of simpler components',
25 | };
26 |
27 | export const WithoutMessageText = Story.bind({});
28 | WithoutMessageText.args = {
29 | action: ctaAction,
30 | headingText: 'Composite component',
31 | };
32 |
--------------------------------------------------------------------------------
/src/components/ShadowBoxCTA.tsx:
--------------------------------------------------------------------------------
1 | import React, { ComponentProps, ReactNode } from 'react';
2 | import { styled } from '@storybook/theming';
3 |
4 | import { breakpoint, spacing, typography } from './shared/styles';
5 |
6 | const ShadowBox = styled.div`
7 | background: #ffffff;
8 | box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 5px 15px 0 rgba(0, 0, 0, 0.05);
9 | border-radius: ${spacing.borderRadius.small}px;
10 | `;
11 |
12 | const ShadowBoxCTAWrapper = styled(ShadowBox)`
13 | padding: ${spacing.padding.large}px;
14 | display: flex;
15 | flex-wrap: wrap;
16 | align-items: center;
17 | text-align: center;
18 |
19 | @media (min-width: ${breakpoint}px) {
20 | text-align: left;
21 | }
22 | `;
23 |
24 | const TextWrapper = styled.div`
25 | line-height: 20px;
26 | flex: 0 1 100%;
27 |
28 | @media (min-width: ${breakpoint}px) {
29 | flex: 1;
30 | }
31 | `;
32 |
33 | const HeadingText = styled.div`
34 | font-size: ${typography.size.s3}px;
35 | font-weight: ${typography.weight.bold};
36 | `;
37 |
38 | const MessageText = styled.div`
39 | font-size: ${typography.size.s2}px;
40 | margin-top: 4px;
41 | `;
42 |
43 | const Action = styled.div`
44 | flex: 0 0 100%;
45 | margin-top: 1.5rem;
46 |
47 | button {
48 | padding: 13px 28px;
49 | }
50 |
51 | @media (min-width: ${breakpoint}px) {
52 | flex: 0 0 auto;
53 | margin-top: 0;
54 | padding-left: 60px;
55 | }
56 | `;
57 |
58 | interface ShadowBoxCTAProps {
59 | headingText: ReactNode;
60 | messageText?: ReactNode;
61 | action: ReactNode;
62 | }
63 |
64 | export const ShadowBoxCTA = ({
65 | action,
66 | headingText,
67 | messageText,
68 | ...rest
69 | }: ShadowBoxCTAProps & ComponentProps) => (
70 |
71 |
72 | {headingText}
73 | {messageText && {messageText}}
74 |
75 |
76 | {action}
77 |
78 | );
79 |
--------------------------------------------------------------------------------
/src/components/SharedStyles.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { pageMargins, hoverEffect } from './shared/styles';
4 |
5 | export default {
6 | title: 'SharedStyles',
7 | };
8 |
9 | const BlockWithMargin = styled.div`
10 | ${pageMargins};
11 | height: 300px;
12 | background-color: #333;
13 | `;
14 |
15 | export const PageMargins = () => (
16 |
17 |
18 | The box below has pageMargins
styles applied to it which controls the horizontal
19 | padding and margin
20 |
21 |
22 |
23 | );
24 |
25 | const BlockWithHoverEffect = styled.div`
26 | ${hoverEffect};
27 | display: block;
28 | height: 300px;
29 | `;
30 |
31 | export const HoverEffectRest = () => ;
32 |
33 | export const HoverEffectHover = () => ;
34 |
35 | export const HoverEffectActive = () => ;
36 |
--------------------------------------------------------------------------------
/src/components/Spinner.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Spinner } from './Spinner';
3 |
4 | export default {
5 | title: 'Spinner',
6 | component: Spinner,
7 | };
8 |
9 | export const Default = () => (
10 |
11 |
12 |
13 | );
14 |
15 | export const Inverse = () => (
16 |
17 |
18 |
19 | );
20 |
21 | export const InForm = () => (
22 |
23 |
24 |
25 | );
26 |
27 | export const Inline = () => (
28 |
29 |
30 |
31 | );
32 |
33 | export const InlinePositive = () => (
34 |
35 |
36 |
37 | );
38 |
39 | export const InlineNegative = () => (
40 |
41 |
42 |
43 | );
44 |
45 | export const InlineNeutral = () => (
46 |
47 |
48 |
49 | );
50 |
51 | export const InlineInverse = () => (
52 |
53 |
54 |
55 | );
56 |
--------------------------------------------------------------------------------
/src/components/StoryLinkWrapper.tsx:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line import/no-extraneous-dependencies
2 | import { action } from '@storybook/addon-actions';
3 | import React, { ComponentProps } from 'react';
4 |
5 | // This is allows us to test whether the link works via the actions addon
6 | const fireClickAction = action('onLinkClick');
7 |
8 | interface StoryLinkWrapperProps {
9 | to: string;
10 | }
11 |
12 | export const StoryLinkWrapper = ({
13 | children,
14 | href,
15 | onClick,
16 | to,
17 | ...rest
18 | }: StoryLinkWrapperProps & ComponentProps<'a'>) => {
19 | const modifiedOnClick: React.DOMAttributes['onClick'] = (event) => {
20 | event.preventDefault();
21 | onClick(event);
22 | fireClickAction(href || to);
23 | };
24 |
25 | return (
26 |
27 | {children}
28 |
29 | );
30 | };
31 |
--------------------------------------------------------------------------------
/src/components/Subheading.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { Subheading } from './Subheading';
4 |
5 | export default {
6 | title: 'Subheading',
7 | component: Subheading,
8 | };
9 |
10 | export const Basic = () => Subheading;
11 |
12 | export const Muted = () => Subheading;
13 |
--------------------------------------------------------------------------------
/src/components/Subheading.tsx:
--------------------------------------------------------------------------------
1 | import React, { FunctionComponent } from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { typography, color } from './shared/styles';
4 |
5 | const StyledSubheading = styled('span', { shouldForwardProp: (prop) => !['muted'].includes(prop) })<
6 | Partial
7 | >`
8 | font-size: ${typography.size.s2 - 1}px;
9 | font-weight: ${typography.weight.extrabold};
10 | letter-spacing: 0.35em;
11 | text-transform: uppercase;
12 |
13 | ${(props) =>
14 | props.muted &&
15 | `
16 | color: ${color.dark};
17 | display: block;
18 | line-height: ${typography.size.m1}px;
19 | margin-bottom: 12px;
20 | `}
21 | `;
22 |
23 | export const Subheading: FunctionComponent = ({
24 | muted = false,
25 | ...props
26 | }: SubheadingProps) => ;
27 |
28 | export interface SubheadingProps {
29 | /** This prop lightens the Subheading color and increases the letter spacing */
30 | muted?: boolean;
31 | }
32 |
--------------------------------------------------------------------------------
/src/components/Textarea.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { action } from '@storybook/addon-actions';
3 |
4 | import { Textarea } from './Textarea';
5 |
6 | const onChange = action('change');
7 |
8 | export default {
9 | title: 'forms/Textarea',
10 | component: Textarea,
11 | };
12 |
13 | export const playground = (args) => ;
14 | playground.args = {
15 | id: 'Basic',
16 | label: 'label',
17 | value: 'value',
18 | orientation: 'horizontal',
19 | hideLabel: false,
20 | };
21 |
22 | export const Default = () => (
23 |
89 | );
90 |
--------------------------------------------------------------------------------
/src/components/Typography.mdx:
--------------------------------------------------------------------------------
1 | import { Meta, Typeset } from '@storybook/blocks';
2 | import { typography } from './shared/styles';
3 |
4 |
5 |
6 | # Base Typography
7 |
8 | **Font:** Nunito Sans
9 |
10 | **Weights:** 400(regular), 700(bold), 800(extrabold), 900(black)
11 |
12 |
26 |
--------------------------------------------------------------------------------
/src/components/TypographyStyles.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { text, subheading, headers, code } from './shared/styles';
4 |
5 | export default {
6 | title: 'Typography/Styles',
7 | };
8 |
9 | const HeaderBase = styled.p<{ variant: keyof typeof headers }>(
10 | { marginBottom: 20 },
11 | (props) => headers[props.variant]
12 | );
13 | export const Header = () => (
14 | <>
15 | Headers/Hero1
16 | Headers/Hero2
17 | Headers/H1
18 | Headers/H2
19 | Headers/H3
20 | Headers/H4
21 | Headers/H5
22 | Headers/H6
23 | >
24 | );
25 |
26 | const SubheadingBase = styled.p<{ variant: keyof typeof subheading }>(
27 | { marginBottom: 20 },
28 | (props) => subheading[props.variant]
29 | );
30 | export const Subheading = () => (
31 | <>
32 | Subheading
33 | Subheading small
34 | >
35 | );
36 |
37 | const TextBase = styled.p<{ variant: keyof typeof text }>(
38 | { marginBottom: 20 },
39 | (props) => text[props.variant]
40 | );
41 | export const Text = () => (
42 | <>
43 | Text/Large
44 | Text/LargeBold
45 | Text/Regular
46 | Text/RegularBold
47 | Text/StorybookMedium
48 | Text/StorybookMediumBold
49 | Text/Small
50 | Text/SmallBold
51 | >
52 | );
53 |
54 | const CodeBase = styled.p<{ variant: keyof typeof code }>(
55 | { marginBottom: 20 },
56 | (props) => code[props.variant]
57 | );
58 | export const Code = () => (
59 | <>
60 | Code/Regular
61 | Code/Small
62 | >
63 | );
64 |
--------------------------------------------------------------------------------
/src/components/clipboard/Clipboard.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { action } from '@storybook/addon-actions';
3 | import { Clipboard } from './Clipboard';
4 | // @ts-ignore
5 | import { TooltipNote } from '../tooltip/TooltipNote';
6 |
7 | export default {
8 | title: 'Clipboard/Clipboard',
9 | decorators: [(storyFn: any) => {storyFn()}
],
10 | };
11 |
12 | export const Default = () => Click to copy;
13 |
14 | export const Callback = () => (
15 | Click to copy
16 | );
17 |
18 | export const Tooltips = () => (
19 | }
22 | renderUncopiedTooltip={() => }
23 | // @ts-ignore
24 | startOpen
25 | >
26 | Click to copy
27 |
28 | );
29 |
30 | export const WithFeedback = () => (
31 | {(copied) => (copied ? 'Copied' : 'Not yet copied')}
32 | );
33 |
--------------------------------------------------------------------------------
/src/components/clipboard/Clipboard.tsx:
--------------------------------------------------------------------------------
1 | import copyToClipboard from 'copy-to-clipboard';
2 | import React, { useEffect, useState } from 'react';
3 | import { styled } from '@storybook/theming';
4 | import { TooltipNote } from '../tooltip/TooltipNote';
5 | import WithTooltip from '../tooltip/WithTooltip';
6 |
7 | const Tooltip = styled(WithTooltip)`
8 | cursor: pointer;
9 | `;
10 |
11 | interface ClipboardProps {
12 | children: React.ReactNode | ((copied: boolean) => React.ReactNode);
13 | toCopy?: string;
14 | getCopyContent?: () => string;
15 | copyOptions?: any;
16 | renderCopiedTooltip?: () => React.ReactNode;
17 | renderUncopiedTooltip?: () => React.ReactNode;
18 | resetTimeout?: number;
19 | }
20 |
21 | export const Clipboard = ({
22 | children,
23 | toCopy,
24 | getCopyContent,
25 | copyOptions,
26 | resetTimeout,
27 | renderCopiedTooltip,
28 | renderUncopiedTooltip,
29 | ...props
30 | }: ClipboardProps) => {
31 | const [copied, setCopied] = useState(false);
32 |
33 | useEffect(() => {
34 | let timeoutId: ReturnType;
35 |
36 | if (copied && timeoutId) {
37 | clearTimeout(timeoutId);
38 | }
39 | if (copied && resetTimeout) {
40 | timeoutId = setTimeout(() => setCopied(false), resetTimeout);
41 | }
42 | return () => {
43 | clearTimeout(timeoutId);
44 | };
45 | }, [copied]);
46 |
47 | const copy = () => {
48 | if (copyToClipboard(toCopy || getCopyContent(), copyOptions)) {
49 | setCopied(true);
50 | }
51 | };
52 |
53 | return (
54 |
60 | {typeof children === 'function' ? children(copied) : children}
61 |
62 | );
63 | };
64 |
65 | Clipboard.defaultProps = {
66 | copyOptions: undefined,
67 | renderCopiedTooltip: () => ,
68 | renderUncopiedTooltip: () => ,
69 | resetTimeout: 3000,
70 | toCopy: undefined,
71 | getCopyContent: () => '',
72 | };
73 |
--------------------------------------------------------------------------------
/src/components/clipboard/ClipboardCode.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { ClipboardCode } from './ClipboardCode';
4 |
5 | export default {
6 | title: 'Clipboard/ClipboardCode',
7 | };
8 |
9 | export const Default = () => (
10 |
11 |
12 |
13 | );
14 |
15 | export const Wrapped = () => (
16 |
17 |
18 |
19 | );
20 |
--------------------------------------------------------------------------------
/src/components/clipboard/ClipboardCode.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 |
4 | import { ClipboardIcon } from './ClipboardIcon';
5 |
6 | const Container = styled.div`
7 | position: relative;
8 | `;
9 |
10 | const Code = styled.pre`
11 | width: 100%;
12 | display: block;
13 | margin: 0;
14 | padding-right: 32px;
15 | overflow: hidden;
16 | word-wrap: break-word;
17 | `;
18 |
19 | const StyledClipboardIcon = styled(ClipboardIcon)`
20 | position: absolute;
21 | top: 4px;
22 | right: 4px;
23 | `;
24 |
25 | interface ClipboardCodeProps {
26 | code: string;
27 | }
28 |
29 | export const ClipboardCode = ({ code, ...props }: ClipboardCodeProps) => (
30 |
31 |
32 | {code}
33 |
34 |
35 |
36 | );
37 |
--------------------------------------------------------------------------------
/src/components/clipboard/ClipboardIcon.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { ClipboardIcon } from './ClipboardIcon';
4 |
5 | export default {
6 | title: 'Clipboard/ClipboardIcon',
7 | };
8 |
9 | export const Default = () => (
10 |
11 |
12 |
13 | );
14 |
--------------------------------------------------------------------------------
/src/components/clipboard/ClipboardIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { color } from '../shared/styles';
4 | import { Icon } from '../Icon';
5 | import { Clipboard } from './Clipboard';
6 |
7 | const StyledClipboard = styled(Clipboard)`
8 | line-height: 10px;
9 | padding: 10px;
10 | color: ${color.mediumdark};
11 | &:hover {
12 | color: ${color.darker};
13 | }
14 | `;
15 |
16 | interface StyledIconProps {
17 | copied: boolean;
18 | }
19 |
20 | const StyledIcon = styled(Icon)`
21 | width: 12px;
22 | height: 12px;
23 | vertical-align: top;
24 | color: ${(props) => (props.copied ? color.positive : 'inherit')};
25 | `;
26 |
27 | type ClipboardIconProps = Omit, 'children'>;
28 |
29 | export const ClipboardIcon = (props: ClipboardIconProps) => (
30 |
31 | {(copied) => }
32 |
33 | );
34 |
--------------------------------------------------------------------------------
/src/components/clipboard/ClipboardInput.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { ClipboardInput } from './ClipboardInput';
4 |
5 | export default {
6 | title: 'Clipboard/ClipboardInput',
7 | };
8 |
9 | export const Default = () => (
10 |
11 |
12 |
13 | );
14 |
15 | export const Clipped = () => (
16 |
17 |
18 |
19 | );
20 |
--------------------------------------------------------------------------------
/src/components/clipboard/ClipboardInput.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { Input } from '../Input';
4 | import { ClipboardIcon } from './ClipboardIcon';
5 |
6 | const Container = styled.div`
7 | position: relative;
8 | `;
9 |
10 | const StyledInput = styled(Input as any)`
11 | width: 100%;
12 | display: block;
13 | && input {
14 | padding-right: 32px !important;
15 | }
16 | `;
17 |
18 | const StyledClipboardIcon = styled(ClipboardIcon)`
19 | position: absolute;
20 | top: 0px;
21 | right: 0px;
22 | `;
23 |
24 | type SubProps = React.ComponentPropsWithoutRef;
25 | interface ClipboardInputProps extends SubProps {
26 | value: string;
27 | }
28 |
29 | export const ClipboardInput = ({ value, ...props }: ClipboardInputProps) => (
30 |
31 |
40 |
41 |
42 | );
43 |
--------------------------------------------------------------------------------
/src/components/global.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'react-github-button';
2 |
--------------------------------------------------------------------------------
/src/components/header/HeaderContext.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 | import { breakpoint } from '../shared/styles';
3 |
4 | interface HeaderContextInterface {
5 | navBreakpoint: number;
6 | inverse: boolean;
7 | }
8 |
9 | export const defaultHeaderContext = {
10 | navBreakpoint: breakpoint,
11 | inverse: false,
12 | }
13 |
14 | export const HeaderContext = createContext(defaultHeaderContext);
15 |
--------------------------------------------------------------------------------
/src/components/header/Nav.tsx:
--------------------------------------------------------------------------------
1 | import { styled, css } from '@storybook/theming';
2 | import { pageMargins, breakpoint } from '../shared/styles';
3 | import { StyledNavItem } from './NavItem';
4 |
5 | export const Nav = styled.div`
6 | height: 3rem;
7 | position: relative;
8 | text-align: center;
9 | z-index: 3;
10 | `;
11 |
12 | export const NavWrapper = styled.nav`
13 | ${pageMargins}
14 |
15 | padding-top: 12px;
16 |
17 | @media (min-width: ${breakpoint}px) {
18 | padding-top: 36px;
19 | }
20 | `;
21 |
22 | type NavGroupProps = {
23 | withRightAlignment?: boolean;
24 | };
25 |
26 | export const NavGroup = styled.div`
27 | position: absolute;
28 | top: 0;
29 | left: 0;
30 | z-index: 1;
31 | display: flex;
32 |
33 | ${(props) =>
34 | props.withRightAlignment &&
35 | css`
36 | left: auto;
37 | right: 0;
38 | `}
39 |
40 | @media (min-width: ${(props) => props.navBreakpoint}px) {
41 | ${StyledNavItem} + ${StyledNavItem} {
42 | margin-left: 25px;
43 | }
44 | }
45 | `;
46 |
47 | NavGroup.defaultProps = {
48 | withRightAlignment: false,
49 | };
50 |
--------------------------------------------------------------------------------
/src/components/header/NavItem.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef, useContext } from 'react';
2 | import { styled, css } from '@storybook/theming';
3 | import { HeaderContext } from './HeaderContext';
4 |
5 | type StyledNavItemProps = {
6 | showDesktop?: boolean;
7 | showMobile?: boolean;
8 | };
9 |
10 | export const StyledNavItem = styled.div`
11 | display: inline-flex;
12 | height: 3rem;
13 | line-height: 3rem;
14 | align-items: center;
15 |
16 | && svg {
17 | margin-right: 0;
18 | }
19 |
20 | ${(props) =>
21 | props.showDesktop &&
22 | css`
23 | display: none;
24 | @media (min-width: ${props.navBreakpoint}px) {
25 | display: inline-flex;
26 | }
27 | `}
28 |
29 | ${(props) =>
30 | props.showMobile &&
31 | css`
32 | @media (min-width: ${props.navBreakpoint}px) {
33 | display: none;
34 | }
35 | `}
36 | `;
37 |
38 | type NavItemProps = React.ComponentPropsWithoutRef<'div'> & StyledNavItemProps;
39 |
40 | export const NavItem = forwardRef((props, ref) => {
41 | const { navBreakpoint } = useContext(HeaderContext);
42 | return ;
43 | });
44 |
--------------------------------------------------------------------------------
/src/components/header/NavLink.tsx:
--------------------------------------------------------------------------------
1 | import React, { ComponentProps, forwardRef, useContext } from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { Link } from '../Link';
4 | import { typography } from '../shared/styles';
5 | import { HeaderContext } from './HeaderContext';
6 |
7 | const StyledNavLink = styled(Link)`
8 | font-size: ${typography.size.s2}px;
9 | font-weight: ${typography.weight.bold};
10 | `;
11 |
12 | type NavLinkProps = ComponentProps;
13 | type NavLinkRef = ((props: NavLinkProps) => JSX.Element) & { displayName?: string };
14 |
15 | export const NavLink: NavLinkRef = forwardRef(
16 | (props, ref) => {
17 | const { inverse } = useContext(HeaderContext);
18 | return ;
19 | }
20 | );
21 |
22 | NavLink.displayName = 'NavLink';
23 |
--------------------------------------------------------------------------------
/src/components/index.tsx:
--------------------------------------------------------------------------------
1 | import * as styles from './shared/styles';
2 | import * as global from './shared/global';
3 | import * as animation from './shared/animation';
4 | import * as icons from './shared/icons';
5 |
6 | export { styles, global, animation, icons };
7 |
8 | export * from './Avatar';
9 | export * from './AvatarList';
10 | export * from './Badge';
11 | export * from './Button';
12 | export * from './ButtonAction';
13 | export * from './ButtonToggle';
14 | export * from './Highlight';
15 | export * from './Icon';
16 | export * from './Link';
17 | export * from './Subheading';
18 | export * from './ProgressDots';
19 | export * from './Spinner';
20 | export * from './Cardinal';
21 |
22 | export * from './FormErrorState';
23 | export * from './Input';
24 | export * from './Textarea';
25 | export * from './Checkbox';
26 | export * from './Radio';
27 | export * from './Select';
28 |
29 | export * from './tooltip/ListItem';
30 | export * from './tooltip/TooltipMessage';
31 | export * from './tooltip/TooltipNote';
32 | export * from './tooltip/TooltipLinkList';
33 | export * from './tooltip/Tooltip';
34 | export { default as WithTooltip } from './tooltip/WithTooltip';
35 |
36 | export * from './modal/Modal';
37 | export { default as WithModal } from './modal/WithModal';
38 |
39 | export * from './table-of-contents/TableOfContents';
40 | export * from './OutlineCTA';
41 | export * from './ShadowBoxCTA';
42 |
43 | export * from './clipboard/Clipboard';
44 | export * from './clipboard/ClipboardIcon';
45 | export * from './clipboard/ClipboardCode';
46 | export * from './clipboard/ClipboardInput';
47 |
48 | export * from './LinkTabs';
49 | export * from './CodeSnippets';
50 |
51 | export * from './header/Header';
52 | export * from './header/NavLink';
53 | export { NavItem } from './header/NavItem';
54 |
55 | export * from './tag/TagItem';
56 | export * from './tag/TagLink';
57 | export * from './tag/TagList';
58 |
--------------------------------------------------------------------------------
/src/components/modal/WithModal.tsx:
--------------------------------------------------------------------------------
1 | import React, { Children, ComponentProps, ReactNode, useState } from 'react';
2 |
3 | import { Modal } from './Modal';
4 |
5 | const PureWithModal = ({
6 | isOpen,
7 | onOpen,
8 | onClose,
9 | modal,
10 | children,
11 | ...rest
12 | }: Props & Omit, 'children'>) => {
13 | return (
14 | <>
15 | {Children.only(children({ isOpen, onOpen, onClose }))}
16 |
17 | {modal}
18 |
19 | >
20 | );
21 | };
22 |
23 | type AnyFn = (...args: any[]) => void;
24 |
25 | interface Props {
26 | isOpen: boolean;
27 | onOpen: AnyFn;
28 | onClose: AnyFn;
29 | modal: ComponentProps['children'];
30 | children: (o: { isOpen?: boolean; onClose?: AnyFn; onOpen?: AnyFn }) => ReactNode;
31 | }
32 |
33 | export default function WithModal({
34 | startOpen = false,
35 | onOpen,
36 | onClose,
37 | ...rest
38 | }: Omit, 'onOpen' | 'onClose' | 'isOpen'> & {
39 | startOpen?: boolean;
40 | onOpen?: AnyFn;
41 | onClose?: AnyFn;
42 | }) {
43 | const [isOpen, onSetIsOpen] = useState(startOpen);
44 | const handleOpen = () => {
45 | onSetIsOpen(true);
46 | if (onOpen) {
47 | onOpen();
48 | }
49 | };
50 | const handleClose = () => {
51 | onSetIsOpen(false);
52 | if (onClose) {
53 | onClose();
54 | }
55 | };
56 | return ;
57 | }
58 |
--------------------------------------------------------------------------------
/src/components/shared/animation.ts:
--------------------------------------------------------------------------------
1 | // Handy CSS animations for micro-interactions
2 | import { css, keyframes } from '@storybook/theming';
3 | import { color } from './styles';
4 |
5 | export const easing = {
6 | rubber: 'cubic-bezier(0.175, 0.885, 0.335, 1.05)',
7 | };
8 |
9 | export const rotate360 = keyframes`
10 | from {
11 | transform: rotate(0deg);
12 | }
13 | to {
14 | transform: rotate(360deg);
15 | }
16 | `;
17 |
18 | export const glow = keyframes`
19 | 0%, 100% { opacity: 1; }
20 | 50% { opacity: .4; }
21 | `;
22 |
23 | export const float = keyframes`
24 | 0% { transform: translateY(1px); }
25 | 25% { transform: translateY(0px); }
26 | 50% { transform: translateY(-3px); }
27 | 100% { transform: translateY(1px); }
28 | `;
29 |
30 | export const jiggle = keyframes`
31 | 0%, 100% { transform:translate3d(0,0,0); }
32 | 12.5%, 62.5% { transform:translate3d(-4px,0,0); }
33 | 37.5%, 87.5% { transform: translate3d(4px,0,0); }
34 | `;
35 |
36 | export const shake = keyframes`
37 | 0% { transform:rotate(-3deg) }
38 | 1.68421% { transform:rotate(3deg) }
39 | 2.10526% { transform:rotate(6deg) }
40 | 3.78947% { transform:rotate(-6deg) }
41 | 4.21053% { transform:rotate(-6deg) }
42 | 5.89474% { transform:rotate(6deg) }
43 | 6.31579% { transform:rotate(6deg) }
44 | 8% { transform:rotate(-6deg) }
45 | 8.42105% { transform:rotate(-6deg) }
46 | 10.10526% { transform:rotate(6deg) }
47 | 10.52632% { transform:rotate(6deg) }
48 | 12.21053% { transform:rotate(-6deg) }
49 | 12.63158% { transform:rotate(-6deg) }
50 | 14.31579% { transform:rotate(6deg) }
51 | 15.78947% { transform:rotate(0deg) }
52 | 100% { transform:rotate(0deg) }
53 | `;
54 |
55 | export const inlineGlow = css`
56 | animation: ${glow} 1.5s ease-in-out infinite;
57 | background: ${color.tr5};
58 | color: transparent;
59 | cursor: progress;
60 | `;
61 |
--------------------------------------------------------------------------------
/src/components/table-of-contents/BulletLink.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { BulletLink } from './BulletLink';
3 |
4 | export default {
5 | title: 'TableOfContents/BulletLink',
6 | component: BulletLink,
7 | parameters: { chromatic: { disable: true } },
8 | };
9 |
10 | const currentPath = '/path-1';
11 | // Bullet links should always be used in a series
12 | export const Series = () => (
13 |
17 | );
18 |
--------------------------------------------------------------------------------
/src/components/table-of-contents/ItemLink.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { ItemLink } from './ItemLink';
3 |
4 | export default {
5 | title: 'TableOfContents/ItemLink',
6 | component: ItemLink,
7 | parameters: { chromatic: { disable: true } },
8 | };
9 |
10 | export const Base = () => (
11 |
12 | );
13 |
14 | export const Active = () => (
15 |
16 | );
17 |
--------------------------------------------------------------------------------
/src/components/table-of-contents/ItemLink.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { MenuLink } from './MenuLink';
4 | import { LinkProps } from '../Link';
5 |
6 | const ItemLinkWrapper = styled.li`
7 | list-style-type: none;
8 |
9 | &:last-of-type ${MenuLink} {
10 | margin-bottom: 0;
11 | }
12 | `;
13 |
14 | export interface LinkItem extends Pick {
15 | path: string;
16 | title: string;
17 | }
18 |
19 | interface ItemLinkProps {
20 | currentPath: string;
21 | item: LinkItem;
22 | }
23 |
24 | export function ItemLink({ currentPath, item }: ItemLinkProps) {
25 | return (
26 |
27 |
33 | {item.title}
34 |
35 |
36 | );
37 | }
38 |
--------------------------------------------------------------------------------
/src/components/table-of-contents/MenuLink.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { MenuLink } from './MenuLink';
3 |
4 | export default {
5 | title: 'TableOfContents/MenuLink',
6 | component: MenuLink,
7 | parameters: { chromatic: { disable: true } },
8 | };
9 |
10 | export const Base = () => Menu link;
11 |
--------------------------------------------------------------------------------
/src/components/table-of-contents/MenuLink.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import type { StyledComponent } from '@storybook/theming';
4 | import { typography } from '../shared/styles';
5 | import { Link } from '../Link';
6 |
7 | type MenuLinkProps = React.ComponentProps & {
8 | isActive?: boolean;
9 | };
10 |
11 | export const MenuLink: StyledComponent = styled(
12 | ({ isActive, ...rest }: MenuLinkProps) =>
13 | )`
14 | outline: none;
15 | font-weight: ${(props) => (props.isActive ? typography.weight.bold : typography.weight.regular)};
16 | line-height: 24px;
17 | text-align: left;
18 | `;
19 |
--------------------------------------------------------------------------------
/src/components/tag/TagItem.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | // @ts-ignore
3 | import seedrandom from 'seedrandom';
4 | import { TagItem } from './TagItem';
5 |
6 | seedrandom('chromatic testing', { global: true });
7 |
8 | export default {
9 | component: TagItem,
10 | title: 'Tag/TagItem',
11 | };
12 |
13 | export const Default = () => ⚛️ React;
14 |
15 | export const Loading = () => ;
16 |
--------------------------------------------------------------------------------
/src/components/tag/TagItem.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled, css } from '@storybook/theming';
3 | import { color, typography, spacing } from '../shared/styles';
4 | import { inlineGlow } from '../shared/animation';
5 |
6 | export type TagItemProps = {
7 | children?: React.ReactNode;
8 | isLoading?: boolean;
9 | };
10 |
11 | function randomString(min: number, max: number) {
12 | const length = Math.random() * (max - min) + min;
13 | return Math.round(36 ** length + 1 - Math.random() * 36 ** length)
14 | .toString(36)
15 | .slice(1);
16 | }
17 | export const TagItem = styled(
18 | ({ isLoading, children, ...rest }: TagItemProps) => (
19 |
20 | {isLoading ? randomString(5, 12) : children}
21 |
22 | ),
23 | {
24 | shouldForwardProp: (prop) => prop !== 'theme' && prop !== 'as',
25 | }
26 | )`
27 | background: ${color.bluelighter};
28 | border-color: transparent;
29 | border-radius: ${spacing.borderRadius.small}px;
30 | border-style: solid;
31 | border-width: 1px;
32 | color: ${color.darkest};
33 | display: inline-block;
34 | font-size: ${typography.size.s2}px;
35 | line-height: ${typography.size.m1}px;
36 | padding: 6px 10px 4px 10px;
37 | position: relative;
38 | white-space: nowrap;
39 |
40 | ${(props) =>
41 | props.isLoading &&
42 | css`
43 | cursor: progress !important;
44 | ${inlineGlow};
45 | &:hover {
46 | color: transparent;
47 | }
48 | `}
49 | `;
50 |
51 | TagItem.defaultProps = {
52 | isLoading: false,
53 | };
54 |
--------------------------------------------------------------------------------
/src/components/tag/TagLink.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | // @ts-ignore
3 | import seedrandom from 'seedrandom';
4 | import { TagLink } from './TagLink';
5 | // @ts-ignore
6 | import { StoryLinkWrapper } from '../StoryLinkWrapper';
7 |
8 | seedrandom('chromatic testing', { global: true });
9 |
10 | export default {
11 | component: TagLink,
12 | title: 'Tag/TagLink',
13 | };
14 |
15 | export const Default = () => ⚛️ React;
16 |
17 | export const WithLinkWrapper = () => (
18 | }>
19 | ⚛️ React
20 |
21 | );
22 |
23 | export const Loading = () => ;
24 |
--------------------------------------------------------------------------------
/src/components/tag/TagLink.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled, css } from '@storybook/theming';
3 | import { rgba } from 'polished';
4 | import { color } from '../shared/styles';
5 | import { Link } from '../Link';
6 | import { TagItem } from './TagItem';
7 |
8 | export interface TagLinkProps extends React.ComponentProps {
9 | isLoading?: boolean;
10 | }
11 |
12 | export const TagLink = styled((props: TagLinkProps) => {
13 | return (
14 | // @ts-expect-error FIXME what's wrong here?
15 |
16 | {props.isLoading ? 'Loading tag' : props.children}
17 |
18 | );
19 | // TODO: check if this explicit type param is needed
20 | })`
21 | &:after {
22 | content: '';
23 | position: absolute;
24 | z-index: -1;
25 | top: 0;
26 | left: 0;
27 | width: 100%;
28 | height: 100%;
29 | box-shadow: rgba(0, 0, 0, 0.08) 0 3px 10px 0;
30 | opacity: 0;
31 | transition: opacity 0.3s ease-in-out;
32 | }
33 |
34 | ${(props) =>
35 | !props.isLoading &&
36 | css`
37 | &:hover {
38 | border-color: ${rgba(color.secondary, 0.5)};
39 |
40 | &:after {
41 | opacity: 1;
42 | }
43 | }
44 | `}
45 | `;
46 |
47 | TagLink.defaultProps = {
48 | isLoading: false,
49 | };
50 |
--------------------------------------------------------------------------------
/src/components/tag/TagList.tsx:
--------------------------------------------------------------------------------
1 | import React, { ComponentProps, useState, forwardRef } from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { color, typography } from '../shared/styles';
4 | import { Link } from '../Link';
5 | import { TagItem } from './TagItem';
6 |
7 | const TagListWrapper = styled.div`
8 | display: flex;
9 | flex-wrap: wrap;
10 |
11 | > * {
12 | margin-right: 10px;
13 | margin-bottom: 10px;
14 | }
15 |
16 | margin-bottom: -10px;
17 | `;
18 |
19 | const MoreTagsButton = styled(Link) & { appearance: any }>`
20 | color: ${color.mediumdark};
21 | font-size: ${typography.size.s2}px;
22 | font-weight: ${typography.weight.bold};
23 | padding-left: 5px;
24 | padding-right: 5px;
25 |
26 | &:focus {
27 | outline: auto;
28 | }
29 | `;
30 |
31 | export type TagListProps = {
32 | tags: React.ReactNode[];
33 | isLoading?: boolean;
34 | limit?: number;
35 | };
36 |
37 | export const TagList = forwardRef(
38 | ({ tags = [], limit = 4, isLoading = false, ...props }: TagListProps, ref) => {
39 | const primaryTags = tags.slice(0, limit);
40 | const moreTags = tags.slice(limit);
41 |
42 | const [moreTagsVisible, setMoreTagsVisible] = useState(false);
43 |
44 | const tagContent = (
45 | <>
46 | {primaryTags}
47 | {moreTagsVisible && moreTags}
48 | {moreTags.length > 0 && !moreTagsVisible && (
49 | setMoreTagsVisible(true)}>
50 | {`+ ${moreTags.length} more`}
51 |
52 | )}
53 | >
54 | );
55 |
56 | return (
57 |
58 | {isLoading ? (
59 | <>
60 |
61 |
62 |
63 |
64 | >
65 | ) : (
66 | tagContent
67 | )}
68 |
69 | );
70 | }
71 | );
72 |
--------------------------------------------------------------------------------
/src/components/tooltip/Tooltip.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { Tooltip } from './Tooltip';
4 |
5 | // Popper would position the tooltip absolutely. We just need to make sure we are pos:rel
6 | const mockPopperProps = { style: { position: 'relative', top: '0px', left: '0px' } };
7 |
8 | const Content = styled.div`
9 | width: 100px;
10 | height: 100px;
11 | font-size: 16px;
12 | text-align: center;
13 | line-height: 100px;
14 | outline: 1px dotted red;
15 | `;
16 |
17 | export default {
18 | title: 'tooltip/Tooltip',
19 | component: Tooltip,
20 | decorators: [
21 | (storyFn) => (
22 | {storyFn()}
23 | ),
24 | ],
25 | };
26 |
27 | export const basicDefault = () => (
28 |
29 | Text
30 |
31 | );
32 |
33 | basicDefault.storyName = 'basic, default';
34 |
35 | export const basicDefaultBottom = () => (
36 |
37 | Text
38 |
39 | );
40 |
41 | basicDefaultBottom.storyName = 'basic, default, bottom';
42 |
43 | export const basicDefaultLeft = () => (
44 |
45 | Text
46 |
47 | );
48 |
49 | basicDefaultLeft.storyName = 'basic, default, left';
50 |
51 | export const basicDefaultRight = () => (
52 |
53 | Text
54 |
55 | );
56 |
57 | basicDefaultRight.storyName = 'basic, default, right';
58 |
59 | export const noChrome = () => (
60 |
61 | Text
62 |
63 | );
64 |
65 | noChrome.storyName = 'no chrome';
66 |
--------------------------------------------------------------------------------
/src/components/tooltip/TooltipLinkList.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { action } from '@storybook/addon-actions';
3 | import WithTooltip from './WithTooltip';
4 |
5 | import { TooltipLinkList } from './TooltipLinkList';
6 | import { StoryLinkWrapper } from '../StoryLinkWrapper';
7 |
8 | export const links = [
9 | { title: 'Link', href: 'https://learnstorybook.com' },
10 | { title: 'Link', href: 'https://learnstorybook.com' },
11 | { title: 'callback', onClick: action('onClick') },
12 | ];
13 |
14 | export default {
15 | title: 'tooltip/TooltipLinkList',
16 | component: TooltipLinkList,
17 | decorators: [
18 | (storyFn) => (
19 |
20 |
21 | Tooltip
22 |
23 |
24 | ),
25 | ],
26 | excludeStories: ['links'],
27 | };
28 |
29 | export const Links = () => ;
30 |
31 | export const LinksAndCallback = () => (
32 |
33 | );
34 |
--------------------------------------------------------------------------------
/src/components/tooltip/TooltipLinkList.tsx:
--------------------------------------------------------------------------------
1 | import React, { ComponentProps } from 'react';
2 | import { styled } from '@storybook/theming';
3 | import { ListItem } from './ListItem';
4 | import { spacing } from '../shared/styles';
5 |
6 | const List = styled.ul`
7 | min-width: 180px;
8 | border-radius: ${spacing.borderRadius.small}px;
9 | overflow: hidden;
10 | margin: 0;
11 | padding: 0;
12 | list-style: none;
13 | `;
14 |
15 | type AnyProps = Record;
16 | type LinkWrapperType = (props: AnyProps) => React.ReactElement;
17 |
18 | interface TooltipLinkListProps {
19 | links: Omit, 'LinkWrapper'>[];
20 | LinkWrapper?: LinkWrapperType;
21 | }
22 |
23 | export const TooltipLinkList = ({ links, LinkWrapper, ...rest }: TooltipLinkListProps) => {
24 | return (
25 |
26 | {links.map((data, index) => (
27 |
33 | ))}
34 |
35 | );
36 | };
37 |
--------------------------------------------------------------------------------
/src/components/tooltip/TooltipMessage.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 | import WithTooltip from './WithTooltip';
4 | import { TooltipMessage } from './TooltipMessage';
5 |
6 | export default {
7 | title: 'tooltip/TooltipMessage',
8 |
9 | decorators: [
10 | (storyFn) => (
11 |
12 |
13 | Tooltip
14 |
15 |
16 | ),
17 | ],
18 | component: TooltipMessage,
19 | };
20 |
21 | export const defaultStory = () => (
22 |
26 | );
27 |
28 | defaultStory.storyName = 'default';
29 |
30 | export const withLink = () => (
31 |
36 | );
37 |
38 | withLink.storyName = 'with link';
39 |
40 | export const withLinks = () => (
41 |
49 | );
50 |
51 | withLinks.storyName = 'with links';
52 |
53 | export const minimalMessage = () => (
54 |
55 | );
56 |
57 | minimalMessage.storyName = 'minimal message';
58 |
59 | export const withCustomClass = () => {
60 | const CustomWrapper = styled(TooltipMessage)`
61 | background: black;
62 | & * {
63 | color: white;
64 | }
65 | `;
66 | return ;
67 | };
68 |
69 | withCustomClass.storyName = 'with custom className';
70 |
71 | export const BreakWord = {
72 | render: () => (
73 |
74 | ),
75 | };
76 |
--------------------------------------------------------------------------------
/src/components/tooltip/TooltipMessage.tsx:
--------------------------------------------------------------------------------
1 | import React, { ComponentProps, ReactNode } from 'react';
2 | import { styled } from '@storybook/theming';
3 |
4 | import { color, typography } from '../shared/styles';
5 | import { Link } from '../Link';
6 |
7 | const Title = styled.div`
8 | font-weight: ${typography.weight.bold};
9 | `;
10 |
11 | const Desc = styled.span``;
12 |
13 | const Links = styled.div`
14 | margin-top: 8px;
15 | text-align: center;
16 |
17 | > * {
18 | margin: 0 8px;
19 | font-weight: ${typography.weight.bold};
20 | }
21 | `;
22 |
23 | const Message = styled.div`
24 | color: ${color.darker};
25 | line-height: 18px;
26 | `;
27 |
28 | const MessageWrapper = styled.div`
29 | padding: 15px;
30 | width: 280px;
31 | box-sizing: border-box;
32 | word-break: break-word;
33 | `;
34 |
35 | export function TooltipMessage({
36 | title,
37 | desc,
38 | links,
39 | ...rest
40 | }: Props & ComponentProps) {
41 | return (
42 |
43 |
44 | {title && {title}}
45 | {desc && {desc}}
46 |
47 | {links && links.length > 0 && (
48 |
49 | {links.map(({ title: linkTitle, ...other }) => (
50 |
51 | {linkTitle}
52 |
53 | ))}
54 |
55 | )}
56 |
57 | );
58 | }
59 |
60 | interface Props {
61 | title?: ReactNode;
62 | desc?: ReactNode;
63 | links?: Omit, 'children'>[];
64 | }
65 |
--------------------------------------------------------------------------------
/src/components/tooltip/TooltipNote.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import WithTooltip from './WithTooltip';
3 |
4 | import { TooltipNote } from './TooltipNote';
5 |
6 | export default {
7 | title: 'tooltip/TooltipNote',
8 |
9 | decorators: [
10 | (storyFn) => (
11 |
12 |
19 | Tooltip
20 |
21 |
22 | ),
23 | ],
24 | component: TooltipNote,
25 | };
26 |
27 | export const Default = () => ;
28 |
--------------------------------------------------------------------------------
/src/components/tooltip/TooltipNote.tsx:
--------------------------------------------------------------------------------
1 | import React, { ComponentProps } from 'react';
2 | import { styled } from '@storybook/theming';
3 |
4 | import { color, typography, spacing } from '../shared/styles';
5 |
6 | const Note = styled.div`
7 | padding: 2px 6px;
8 | line-height: 16px;
9 | font-size: 10px;
10 | font-weight: ${typography.weight.bold};
11 | color: ${color.lightest};
12 | box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.3);
13 | border-radius: ${spacing.borderRadius.small}px;
14 | white-space: nowrap;
15 | pointer-events: none;
16 | z-index: -1;
17 | background: rgba(0, 0, 0, 0.6);
18 | margin: 6px;
19 | `;
20 |
21 | interface TooltipNoteProps {
22 | note: string;
23 | }
24 |
25 | export const TooltipNote = ({ note, ...rest }: TooltipNoteProps & ComponentProps) => {
26 | return {note};
27 | };
28 |
--------------------------------------------------------------------------------
/src/design-system.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/storybookjs/design-system/0c4c043e8bf956ee9aad4664383829f807b4bfaf/src/design-system.png
--------------------------------------------------------------------------------
/src/images/Chrome.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgChrome = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
83 | );
84 |
85 | export default SvgChrome;
86 |
--------------------------------------------------------------------------------
/src/images/Ie.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgIe = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
24 | );
25 |
26 | export default SvgIe;
27 |
--------------------------------------------------------------------------------
/src/images/Illustrations.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { styled } from '@storybook/theming';
3 |
4 | import * as coloredIcons from './colored-icons';
5 |
6 | export default {
7 | title: 'Images',
8 | };
9 |
10 | const Grid = styled.div`
11 | display: flex;
12 | flex-wrap: wrap;
13 | margin: 3rem;
14 | `;
15 |
16 | const Item = styled.div`
17 | display: inline-flex;
18 | align-items: center;
19 | flex: 0 0 20%;
20 | margin-right: 5%;
21 | margin-bottom: 20px;
22 |
23 | svg {
24 | width: 32px;
25 | height: 32px;
26 | margin-right: 10px;
27 | }
28 | `;
29 |
30 | export const ColoredIcons = () => (
31 |
32 | {Object.entries(coloredIcons).map(([name, Icon]) => (
33 | -
34 | {name}
35 |
36 | ))}
37 |
38 | );
39 |
--------------------------------------------------------------------------------
/src/images/chrome.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Accessibility.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgAccessibility = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
27 | );
28 |
29 | export default SvgAccessibility;
30 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Assign.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgAssign = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
37 | );
38 |
39 | export default SvgAssign;
40 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Bell.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgBell = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
26 | );
27 |
28 | export default SvgBell;
29 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Branch.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgBranch = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
30 | );
31 |
32 | export default SvgBranch;
33 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Bug.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgBug = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
24 | );
25 |
26 | export default SvgBug;
27 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Catalog.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgCatalog = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
31 | );
32 |
33 | export default SvgCatalog;
34 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Check.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgCheck = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
26 | );
27 |
28 | export default SvgCheck;
29 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Code.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgCode = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
25 | );
26 |
27 | export default SvgCode;
28 |
--------------------------------------------------------------------------------
/src/images/colored-icons/CodeBrackets.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgCodeBrackets = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
34 | );
35 |
36 | export default SvgCodeBrackets;
37 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Comments.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgComments = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
33 | );
34 |
35 | export default SvgComments;
36 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Components.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgComponents = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
31 | );
32 |
33 | export default SvgComponents;
34 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Delete.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgDelete = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
26 | );
27 |
28 | export default SvgDelete;
29 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Detect.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgDetect = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
42 | );
43 |
44 | export default SvgDetect;
45 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Direction.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgDirection = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
29 | );
30 |
31 | export default SvgDirection;
32 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Document.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgDocument = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
32 | );
33 |
34 | export default SvgDocument;
35 |
--------------------------------------------------------------------------------
/src/images/colored-icons/DocumentAlt.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgDocumentAlt = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
32 | );
33 |
34 | export default SvgDocumentAlt;
35 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Email.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgEmail = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
36 | );
37 |
38 | export default SvgEmail;
39 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Error.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgError = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
24 | );
25 |
26 | export default SvgError;
27 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Eye.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgEye = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
31 | );
32 |
33 | export default SvgEye;
34 |
--------------------------------------------------------------------------------
/src/images/colored-icons/FastForward.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/images/colored-icons/FastForward.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgRedo = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
32 | );
33 |
34 | export default SvgRedo;
35 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Flow.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgFlow = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
27 | );
28 |
29 | export default SvgFlow;
30 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Group.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgGroup = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
31 | );
32 |
33 | export default SvgGroup;
34 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Ignore.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgIgnore = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
38 | );
39 |
40 | export default SvgIgnore;
41 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Interact.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgInteract = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
29 | );
30 |
31 | export default SvgInteract;
32 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Interface.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgInterface = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
25 | );
26 |
27 | export default SvgInterface;
28 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Key.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgKey = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
33 | );
34 |
35 | export default SvgKey;
36 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Knob.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgKnob = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
30 | );
31 |
32 | export default SvgKnob;
33 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Lightning.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgLightning = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
29 | );
30 |
31 | export default SvgLightning;
32 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Link.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgLink = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
29 | );
30 |
31 | export default SvgLink;
32 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Overlap.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgOverlap = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
24 | );
25 |
26 | export default SvgOverlap;
27 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Pixel.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgPixel = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
25 | );
26 |
27 | export default SvgPixel;
28 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Plugin.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgPlugin = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
29 | );
30 |
31 | export default SvgPlugin;
32 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Plus.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgPlus = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
23 | );
24 |
25 | export default SvgPlus;
26 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Projects.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgProjects = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
30 | );
31 |
32 | export default SvgProjects;
33 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Redo.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Redo.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgRedo = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
32 | );
33 |
34 | export default SvgRedo;
35 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Repo.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgRepo = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
34 | );
35 |
36 | export default SvgRepo;
37 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Review.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgReview = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
41 | );
42 |
43 | export default SvgReview;
44 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Rewind.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgRewind = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
26 | );
27 |
28 | export default SvgRewind;
29 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Runtest.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgRuntest = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
27 | );
28 |
29 | export default SvgRuntest;
30 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Scale.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgScale = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
24 | );
25 |
26 | export default SvgScale;
27 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Search.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgSearch = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
34 | );
35 |
36 | export default SvgSearch;
37 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Shield.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgShield = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
30 | );
31 |
32 | export default SvgShield;
33 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Stack.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgStack = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
33 | );
34 |
35 | export default SvgStack;
36 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Stoplight.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgStoplight = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
31 | );
32 |
33 | export default SvgStoplight;
34 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Testflake.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgTestflake = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
49 | );
50 |
51 | export default SvgTestflake;
52 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Testpyramid.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgTestpyramid = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
27 | );
28 |
29 | export default SvgTestpyramid;
30 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Undo.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgUndo = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
26 | );
27 |
28 | export default SvgUndo;
29 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Unignore.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgUnignore = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
44 | );
45 |
46 | export default SvgUnignore;
47 |
--------------------------------------------------------------------------------
/src/images/colored-icons/Update.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 |
4 | interface SVGRProps {
5 | title?: string;
6 | titleId?: string;
7 | }
8 |
9 | const SvgUpdate = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
10 |
26 | );
27 |
28 | export default SvgUpdate;
29 |
--------------------------------------------------------------------------------
/src/images/colored-icons/accessibility.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/images/colored-icons/bell.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/boxmodel.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/images/colored-icons/branch.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/src/images/colored-icons/bug.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/images/colored-icons/catalog.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/src/images/colored-icons/check.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/code-brackets.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/code.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/src/images/colored-icons/comments.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/images/colored-icons/components.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/src/images/colored-icons/delete.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/detect.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/images/colored-icons/direction.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/document-alt.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/images/colored-icons/document.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/images/colored-icons/email.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/images/colored-icons/error.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/colored-icons/flow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/colored-icons/group.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
--------------------------------------------------------------------------------
/src/images/colored-icons/ignore.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/images/colored-icons/interact.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/images/colored-icons/interface.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/src/images/colored-icons/key.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/images/colored-icons/knob.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/images/colored-icons/lightning.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/link.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/colored-icons/overlap.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/images/colored-icons/pixel.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/src/images/colored-icons/plugin.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/plus.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/projects.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/colored-icons/repo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/images/colored-icons/review.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/images/colored-icons/rewind.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/runtest.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/images/colored-icons/scale.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/images/colored-icons/search.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/shield.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/soc2.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/stack.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/colored-icons/stoplight.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/images/colored-icons/testflake.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/src/images/colored-icons/testpyramid.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/colored-icons/turbo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/images/colored-icons/undo.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/colored-icons/unignore.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/images/colored-icons/update.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/images/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Chrome } from './Chrome';
2 | export { default as Firefox } from './Firefox';
3 | export { default as Ie } from './Ie';
4 | export { default as Safari } from './Safari';
5 | export * as Logos from './logos';
6 | export * as ColoredIcons from './colored-icons';
7 |
--------------------------------------------------------------------------------
/src/images/logos/StorybookIcon.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { SVGProps } from 'react';
3 | interface SVGRProps {
4 | title?: string;
5 | titleId?: string;
6 | }
7 |
8 | const SvgStorybookIcon = ({ title, titleId, ...props }: SVGProps & SVGRProps) => (
9 |
29 | );
30 |
31 | export default SvgStorybookIcon;
32 |
--------------------------------------------------------------------------------
/src/images/logos/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as ChromaticInverted } from './ChromaticInverted';
2 | export { default as Chromatic } from './Chromatic';
3 | export { default as Circleci } from './Circleci';
4 | export { default as Netlify } from './Netlify';
5 | export { default as StorybookIcon } from './StorybookIcon';
6 | export { default as StorybookInverted } from './StorybookInverted';
7 | export { default as StorybookMonochromeInverse } from './StorybookMonochromeInverse';
8 | export { default as StorybookMonochrome } from './StorybookMonochrome';
9 | export { default as Storybook } from './Storybook';
10 |
--------------------------------------------------------------------------------
/src/images/logos/storybook-icon.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | export * from './components';
2 | export * from './utils';
3 | export * from './images';
4 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | /* add css styles here (optional) */
2 |
3 | .test {
4 | display: inline-block;
5 | margin: 2em auto;
6 | border: 2px solid #000;
7 | font-size: 2em;
8 | }
9 |
--------------------------------------------------------------------------------
/src/test.js:
--------------------------------------------------------------------------------
1 | describe('sanity', () => {
2 | it('is truthy', () => {
3 | expect(true).toBeTruthy();
4 | });
5 | });
6 |
--------------------------------------------------------------------------------
/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loadFontsForStorybook';
2 |
--------------------------------------------------------------------------------
/src/utils/loadFontsForStorybook.ts:
--------------------------------------------------------------------------------
1 | /* eslint-env browser */
2 | import { fontUrl } from '../components/shared/global';
3 |
4 | // Load the font and avoid re-loading it when components change
5 | const fontLinkId = 'storybook-font-link-tag';
6 |
7 | export const loadFontsForStorybook = () => {
8 | if (!document.getElementById(fontLinkId)) {
9 | const fontLink = document.createElement('link');
10 |
11 | fontLink.id = fontLinkId;
12 | fontLink.href = fontUrl;
13 | fontLink.rel = 'stylesheet';
14 |
15 | document.head.appendChild(fontLink);
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/svgr.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | ignoreExisting: true,
3 | svgoConfig: {
4 | plugins: [
5 | {
6 | name: 'preset-default',
7 | params: {
8 | overrides: {
9 | removeViewBox: false,
10 | },
11 | },
12 | },
13 | 'prefixIds',
14 | 'removeDimensions',
15 | ],
16 | },
17 | svgProps: {
18 | role: 'img',
19 | },
20 | titleProp: true,
21 | typescript: 'true',
22 | };
23 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "checkJs": false,
6 | "baseUrl": ".",
7 | "incremental": false,
8 | "noImplicitAny": true,
9 | "experimentalDecorators": true,
10 | "emitDecoratorMetadata": true,
11 | "jsx": "react",
12 | "module": "commonjs",
13 | "skipDefaultLibCheck": true,
14 | "skipLibCheck": true,
15 | "allowSyntheticDefaultImports": true,
16 | "esModuleInterop": true,
17 | "target": "es5",
18 | "types": [],
19 | "lib": ["es2017", "dom"]
20 | },
21 | "include": ["src"],
22 | "exclude": [
23 | "**/dist",
24 | "**/test.*",
25 | "node_modules",
26 | "**/node_modules",
27 | "**/*.spec.ts",
28 | "**/__tests__",
29 | "**/*.test.ts",
30 | "**/*.stories.*"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------