Skip to content

Commit b4663f4

Browse files
authored
chore(demo): refactor storybook (#1265)
1 parent 87dc881 commit b4663f4

File tree

435 files changed

+9557
-12461
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

435 files changed

+9557
-12461
lines changed

.eslintrc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
},
2727
{
2828
"files": ["packages/**/*.{js,ts,tsx}"],
29-
"excludedFiles": ["*.spec.*", "packages/**/stories/**/*"],
29+
"excludedFiles": ["*.spec.*", "packages/*/demo/**/*"],
3030
"plugins": ["garden-local"],
3131
"rules": {
3232
"garden-local/require-default-theme": "error"

.github/CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ on your system. After you clone this repo, run `yarn` to install
4848
dependencies needed for development. After installation, the following
4949
commands are available:
5050

51-
- `yarn start` to launch Styleguidist with live reload.
51+
- `yarn start` to launch Storybook with live reload.
5252
- `yarn test` to run Jest testing.
5353
- `yarn lint` to enforce consistent JavaScript, CSS, and
5454
markdown code conventions across all component packages. Note this is

.lintstagedrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"jest --config=utils/test/jest.config.js --bail --findRelatedTests",
66
"prettier --write"
77
],
8-
"!(*CHANGELOG).md": [
8+
"!(*CHANGELOG).{md,mdx}": [
99
"markdownlint",
1010
"prettier --write"
1111
],

.markdownlintrc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
"default": true,
33
"first-line-h1": false,
44
"first-header-h1": false,
5-
"MD013": {
5+
"line-length": {
66
"line_length": 100,
77
"tables": false
8-
}
8+
},
9+
"no-inline-html": false
910
}

.storybook/babel.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88
const path = require('path');
99
const { readdirSync } = require('fs');
10-
const babel = require('@storybook/core-common/dist/cjs/utils/babel');
10+
const { getStorybookBabelConfig } = require('@storybook/core-common');
1111

12-
const config = babel.getStorybookBabelConfig();
12+
const config = getStorybookBabelConfig();
1313

1414
const PACKAGE_NAMES = readdirSync(path.resolve(__dirname, '../packages')).filter(
1515
name => name !== '.template'

.storybook/main.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,18 @@
66
*/
77

88
const webpack = require('webpack');
9-
const externalConfig = require('../.svgo.config.js');
9+
const svgoConfig = require('../.svgo.config.js');
1010
const ESLintPlugin = require('eslint-webpack-plugin');
1111
const docs = process.env.BROWSER ? process.env.BROWSER.toUpperCase() !== 'IE11' : true;
1212

1313
module.exports = {
14-
stories: ['../packages/*/stories/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
15-
addons: [{ name: '@storybook/addon-essentials', options: { docs } }, '@storybook/addon-a11y'],
14+
stories: ['../packages/*/demo/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
15+
staticDirs: ['./static'],
16+
addons: [
17+
{ name: '@storybook/addon-essentials', options: { docs } },
18+
'@storybook/addon-a11y',
19+
'storybook-addon-designs'
20+
],
1621
core: {
1722
builder: 'webpack5'
1823
},
@@ -26,9 +31,7 @@ module.exports = {
2631
use: [
2732
{
2833
loader: '@svgr/webpack',
29-
options: {
30-
externalConfig
31-
}
34+
options: { svgoConfig }
3235
}
3336
]
3437
});

.storybook/manager.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { addons } from '@storybook/addons';
1010
import { DEFAULT_THEME } from '../packages/theming/src';
1111

1212
addons.setConfig({
13+
panelPosition: 'right',
1314
theme: create({
1415
brandTitle: 'Zendesk Garden React Components',
1516
brandUrl: 'https://github.com/zendeskgarden/react-components',

.storybook/preview.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ export const parameters = {
1717
grid: { disable: true }
1818
},
1919
controls: {
20-
hideNoControlsWarning: true
20+
hideNoControlsWarning: true,
21+
sort: 'alpha'
2122
},
2223
docs: {
2324
theme: create({
@@ -29,6 +30,8 @@ export const parameters = {
2930
const GlobalPreviewStyling = createGlobalStyle`
3031
body {
3132
background-color: ${p => p.theme.colors.background};
33+
/* stylelint-disable-next-line declaration-no-important */
34+
padding: 0 !important;
3235
font-family: ${p => p.theme.fonts.system};
3336
}
3437
`;
58 KB
Loading

.svgo.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module.exports = {
88
focusable: false
99
},
1010
{
11-
role: 'presentation'
11+
'aria-hidden': true
1212
}
1313
]
1414
}

docs/demo.md

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
# Garden demos
2+
3+
Garden leverages [Storybook](https://storybook.js.org/) for generating component
4+
demos with story controls. Run `yarn start` to build and serve package demos in
5+
development mode (with hot reloading).
6+
7+
The development goal for demos is to render components in isolation with the
8+
least amount of structural scaffolding together with the greatest amount of
9+
control for content and flexibility. Along with global toolbar items (preview
10+
size, locale direction, CSS Bedrock, etc), controls should stress every aspect
11+
of a component's layout and behavior.
12+
13+
## Best practice
14+
15+
The following list of dos and don'ts outline demo code expectations.
16+
17+
### Do this
18+
19+
- Expose controls for all essentials – inherent props, conditional subcomponent
20+
renders, child content
21+
- Allow natural component layout – full width for block, partial width for inline
22+
- Use the Garden `Grid` to manage layout for components that respond to
23+
placement values (start, end, top, bottom, etc)
24+
- Rely on `useArgs` from Storybook's client API in order to keep component state
25+
connected with it's associated Storybook control
26+
27+
### Not this
28+
29+
- Avoid `styled-components`. The addition of demo CSS is an indicator that the
30+
underlying component may not offer comprehensive styling.
31+
- Refrain from adding component documentation. The Storybook demos are not a
32+
substitute for the [garden.zendesk.com](https://garden.zendesk.com/) website.
33+
The website is the source of truth for component documenation.
34+
- Avoid `useState`; prefer Storybook `useArgs` instead
35+
- Do not write "Default" vs "Advanced" stories. A well-written component story
36+
will render as expected with defaults and offer controls to push into advanced
37+
component capabilities. See the [patterns](#patterns) section below for cases
38+
that extend beyond the consideration of an isolated component.
39+
- Do not use numeric file naming. By following the [naming](#naming) conventions
40+
listed below, component stories will be naturally sorted alphabetically.
41+
42+
## Conventions
43+
44+
Stick to the following conventions for authoring demo stories that are
45+
consistent with the existing codebase. You may find that running `yarn new` is
46+
helpful for auto-generating component demo scaffolding.
47+
48+
### Structure
49+
50+
- Place MDX stories under the package `demo` directory.
51+
- All `Story` TSX files are placed under a `demo/stories` directory.
52+
- Move all boilerplate data constants (i.e. control data for a component's
53+
`children`) into `demo/stories/data.ts`
54+
- Capture all types and interfaces specific to story data under
55+
`demo/stories/types.ts`
56+
- If a package has patterns (see [section](#patterns) below), tuck all pattern
57+
demo code under a `demo/~patterns` directory – repeating the directory structure
58+
as needed for `Story` TSX, `data.ts`, and `types.ts` files noted above. Prefix
59+
with a tilde to ensure these stories are ordered last.
60+
61+
### Meta
62+
63+
Story meta appears in the MDX file with the following structure:
64+
65+
```mdx
66+
<Meta
67+
title="Packages/Package/Component"
68+
component={Component}
69+
subcomponents={{...}} />
70+
```
71+
72+
- The `Component` is the element-level component that this story is focused on
73+
- Use the optional `subcomponents` object whenever subcomponents exist in
74+
support of the main element component. Keep this list in alphabetical order.
75+
76+
### ArgsTable
77+
78+
The next simple section of MDX generates prop tables for the component and
79+
subcomponents identied by the story meta. These tables can be viewed under the
80+
Storybook "Docs" tab.
81+
82+
```mdx
83+
# API
84+
85+
<ArgsTable />
86+
```
87+
88+
### Canvas story (or stories)
89+
90+
The canvas story specifies a name, args, argTypes, parameters, and the rendered
91+
story itself. In its most basic form:
92+
93+
```mdx
94+
# Demo
95+
96+
<Canvas>
97+
<Story name="Component">{args => <Component {...args} />}</Story>
98+
</Canvas>
99+
```
100+
101+
Often a single story is enough to fulfill the development goal for an isolated
102+
and flexible component demo. But sometimes, in the case of uncontrolled vs.
103+
controlled, there is a need to render multiple stories. In this case, the basic
104+
MDX form is modified to be:
105+
106+
```mdx
107+
# Demo
108+
109+
## Uncontrolled
110+
111+
<Canvas>
112+
<Story name="Uncontrolled">{args => <ComponentStory {...args} />}</Story>
113+
</Canvas>
114+
115+
## Controlled
116+
117+
<Canvas>
118+
<Story name="Controlled">
119+
{args => {
120+
const updateArgs = useArgs()[1];
121+
const handleEvent = argName => updateArgs({ argName });
122+
return <ComponentStory {...args} onEvent={handleEvent} />;
123+
}}
124+
</Story>
125+
</Canvas>
126+
```
127+
128+
Note how the `ComponentStory` is reused for both canvas stories. See
129+
[Story](#story) below for additional details. Be sure to move common `args`,
130+
`argTypes`, and `parameters` under the MDX `<Meta>` rather than repeating these
131+
under each story.
132+
133+
#### Story `args`
134+
135+
- Storybook automatically provides main component props as `args`. Usually there
136+
is no need to specify these values (double-check for missing prop controls). One
137+
notable exception is for Garden boolean prop values that default to `true`. In
138+
this case, the `args` should be specified to match.
139+
- Select smart defaults for the remaining subcomponent or "Story" `args`.
140+
Sometimes the best choice is to leave an arg undefined.
141+
142+
#### Story `argTypes`
143+
144+
Standard convention for `argTypes` exists across dozens of existing stories.
145+
Study demo code for details. Most importantly, main component props that are
146+
_not_ auto-generated must be properly categorized. The two acceptable story
147+
categories are:
148+
149+
- Subcomponent. All subcomponent props (including `children`) are specified
150+
under the associated subcomponent name.
151+
- "Story". This category includes all ancillary controls that are needed to
152+
stress the full flexibility of the rendered component(s).
153+
154+
#### Story `parameters`
155+
156+
Currently, story `parameters` are used to link to the Figma page(s) or frame(s)
157+
that best exhibits associated component designs. Note that the parameter URLs
158+
are internal-only and point to designs that exist in the main Garden Figma
159+
branch. Therefore, `parameters` may need to be added as a follow-on for new
160+
components.
161+
162+
### Story
163+
164+
A `Story` type component is the best way to develop demo code for non-trivial
165+
Garden components. Doing so removes complexity of coding in MDX, placing
166+
component rendering and application of story args into TypeScript where code can
167+
be properly maintained. In its basic form, a `Story` looks like this:
168+
169+
```tsx
170+
import React from 'react';
171+
import { Story } from '@storybook/react';
172+
import { Component, IComponentProps } from '@zendeskgarden/react-package';
173+
174+
interface IArgs extends IComponentProps {
175+
/* Subcomponent and "Story" arg definitions go here */
176+
}
177+
178+
export const ComponentStory: Story<IArgs> = args => <Component {...args} />;
179+
```
180+
181+
Take time to ensure Story `args` and `argTypes` are defined well. Often you will
182+
find that the majority of demo development time is spent on `args` and
183+
`argTypes` and the `Story` itself essentially falls out of the goal to
184+
demonstrate component flexibility in isolation.
185+
186+
## Naming
187+
188+
- Follow the existing Storybook naming hierarcy:
189+
`Packages/{{PackageName}}/{{ComponentName}}`
190+
- The first story in every package demo should be a `#readme.stories.mdx` file
191+
that renders the package's README.md. Prefix with a hashtag to ensure this story
192+
is ordered first.
193+
- Subsequent component story files are named `componentName.stories.mdx`
194+
(camelCase)
195+
- Use Garden's standard prop naming for story args (i.e. isXxx/hasXxx for
196+
boolean args), but use `argTypes` to rename with subcomponent notation. For
197+
example:
198+
199+
```js
200+
args={{
201+
hasHint: true
202+
}}
203+
argTypes={{
204+
hasHint: { name: Hint, table: { category: 'Story' } }
205+
}}
206+
```
207+
208+
## Patterns
209+
210+
A pattern is a demo story that highlights a component's ability to work together
211+
with other Garden components or in conjunction with external libraries.
212+
Oftentimes, a pattern ends up violating the best practice of duplicating example
213+
documentation that belongs on the website. However, due to component development
214+
sequencing or a need to persist a visual test, a pattern can be a helpful tool
215+
for (temporarily) demonstrating component layout or behavior that supercedes the
216+
isolation of the component itself.
217+
218+
Follow [structure](#structure) conventions to keep patterns collected in a
219+
(potentially) short-lived location. It is the component developer's
220+
responsibility to track example pattern movement to the website and subsequently
221+
remove the pattern from Storybook – keeping the website as the focal source of
222+
truth.

docs/development.md

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Garden Development
1+
# Garden development
22

33
You're here because you want to get into the codebase. That's great. This
44
guide will help you dig in. If you haven't already, please see the
@@ -25,7 +25,7 @@ All packages follow this basic structure (.e.g. under `/packages/test`):
2525

2626
<!-- markdownlint-disable -->
2727

28-
- `├── examples/` – visual component examples and generated documentation
28+
- `├── demo/` – visual component demos
2929
- `├── src/` – component source code and spec tests<br>
3030
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`├── elements/` – high abstraction components that wrap interaction behavior and visual styling<br>
3131
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`├── styled/` – view-level [styled-components](https://styled-components.com/) that contain theme based CSS<br>
@@ -40,23 +40,12 @@ The Garden React codebase is statically type-checked using
4040
documentation for in-depth treatment of Garden's Container-View-Element
4141
architecture, along with rules that apply to each component type.
4242

43-
## Package examples
43+
## Package demos
4444

45-
Package example documentation is generated via [React
46-
Styleguidist](https://react-styleguidist.js.org/). Run `yarn start` to build
47-
and serve package documentation in development mode (with hot reloading). The
48-
[global configuration](/utils/styleguide/styleguide.base.config.js) is
49-
extended by a package-local `styleguide.config.js` which determines section
50-
structure and content for each package page.
51-
52-
In general, an example page includes:
53-
54-
- the package README
55-
- a "knobs" style example that toggles various visual component states
56-
- API prop sheets for all public element exports
57-
58-
Include additional example files to demonstrate complex component behaviors
59-
or common interactions with other Garden components.
45+
Package demo code is generated via [Storybook](https://storybook.js.org/). Run
46+
`yarn start` to build and serve package documentation in development mode (with
47+
hot reloading). See [demo documentation](/docs/demo.md) for development
48+
information.
6049

6150
## Package testing
6251

0 commit comments

Comments
 (0)