Skip to content

Commit

Permalink
Merge pull request #11877 from storybookjs/chore_add_api_section_snip…
Browse files Browse the repository at this point in the history
…pets

Chore: add snippets for api section
  • Loading branch information
shilman authored Aug 11, 2020
2 parents e9ec609 + fe3b3e0 commit 30d685c
Show file tree
Hide file tree
Showing 67 changed files with 1,260 additions and 665 deletions.
279 changes: 131 additions & 148 deletions docs/api/addons-api.md

Large diffs are not rendered by default.

151 changes: 58 additions & 93 deletions docs/api/addons.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,69 +35,47 @@ Let’s write a simple addon for Storybook which:

Let’s start by writing a story for our addon that exposes a custom parameter. The idea is that our addon will show this parameter in the addon panel.

```js
// Button.story.js

import React from 'react';
import Button from './Button';
export default {
title: 'Button',
parameters: {
myAddon: {
data: 'this data is passed to the addon',
},
},
};
export const Basic = () => <Button>hello</Button>;
```
<!-- prettier-ignore-start -->

<CodeSnippets
paths={[
'react/button-story-with-addon-example.js.mdx',
]}
/>

<!-- prettier-ignore-end -->

Because we added the story at the component level, the `myAddon` parameter is associated with all stories defined in the file.

### Add a panel

Now let’s add a panel to Storybook in a file called `register.js`, which is the entry point for addons to register themselves.

```js
// .storybook/register.js

import React from 'react';
import { addons, types } from '@storybook/addons';
import { AddonPanel } from '@storybook/components';

const ADDON_ID = 'myaddon';
const PANEL_ID = `${ADDON_ID}/panel`;

const MyPanel = () => <div>MyAddon</div>;
addons.register(ADDON_ID, (api) => {
addons.add(PANEL_ID, {
type: types.PANEL,
title: 'My Addon',
render: ({ active, key }) => (
<AddonPanel active={active} key={key}>
<MyPanel />
</AddonPanel>
),
});
});
```
<!-- prettier-ignore-start -->

<CodeSnippets
paths={[
'common/storybook-addon-panel-initial.js.mdx',
]}
/>

<!-- prettier-ignore-end -->

This is boilerplate code for any addon that adds a panel to Storybook, and there’s really not much going on here. In this case, we’re just adding a static div that renders when the panel is selected in Storybook’s UI.

### Display story parameter

Next, let’s replace the `MyPanel` component from above to show the parameter.

```js
// .storybook/register.js
<!-- prettier-ignore-start -->

import { useParameter } from '@storybook/api';
const PARAM_KEY = 'myAddon';
const MyPanel = () => {
const value = useParameter(PARAM_KEY, null);
const item = value ? value.data : '';
return <div>{item}</div>;
};
```
<CodeSnippets
paths={[
'common/storybook-addon-change-panel.js.mdx',
]}
/>

<!-- prettier-ignore-end -->

The new version is made smarter by `useParameter`, which is a [React hook](https://reactjs.org/docs/hooks-intro.html) that updates the parameter value and re-renders the panel every time the story changes.

Expand All @@ -109,13 +87,15 @@ Finally, let’s hook it all up. Addons are typically published as standalone pa

Update your [`.storybook/main.js`](../configure/overview.md#configure-story-rendering):

```js
// .storybook/main.js
<!-- prettier-ignore-start -->

module.exports = {
addons: ['path/to/register.js'],
};
```
<CodeSnippets
paths={[
'common/storybook-main-register-addon.js.mdx',
]}
/>

<!-- prettier-ignore-end -->

The path can be an absolute location on your file system, or a path relative to your `.storybook` directory (e.g. `./my-addon/register.js` if you defined the addon inside your `.storybook` folder).

Expand Down Expand Up @@ -158,32 +138,27 @@ It’s possible to disable the addon panel for a particular story.

To make that possible, you need to pass the `paramKey` element when you register the panel:

```js
// .storybook/register.js

addons.register(ADDON_ID, () => {
addons.add(PANEL_ID, {
type: types.PANEL,
title: 'My Addon',
render: () => <div>Addon tab content</div>,
paramKey: 'myAddon', // this element
});
});
```
<!-- prettier-ignore-start -->

<CodeSnippets
paths={[
'common/storybook-addon-disable-addon.js.mdx',
]}
/>

<!-- prettier-ignore-end -->

Then when adding a story, you can then pass a disabled parameter.

```js
// Button.story.js
<!-- prettier-ignore-start -->

import React from 'react';
export default {
title: 'Button',
parameters: {
myAddon: { disable: true },
},
};
```
<CodeSnippets
paths={[
'react/button-story-disable-addon.js.mdx',
]}
/>

<!-- prettier-ignore-end -->

### Styling your addon

Expand Down Expand Up @@ -241,25 +216,15 @@ Common uses for presets include:

Here’s an example of typical preset file:

```js
//preset.js
export function config(entry = []) {
return [...entry, require.resolve('./defaultParameters')];
}
<!-- prettier-ignore-start -->

export function managerEntries(entries) {
return [...entries, require.resolve('./register')];
}
<CodeSnippets
paths={[
'common/storybook-addon-preset-example.js.mdx',
]}
/>

export const parameters = {
backgrounds: {
values: [
{ name: 'light', value: '#F8F8F8' },
{ name: 'dark', value: '#333333' },
],
},
};
```
<!-- prettier-ignore-end -->

For more information on presets, see the [presets docs](./presets.md).

Expand Down
91 changes: 35 additions & 56 deletions docs/api/argtypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,15 @@ To do so, Storybook uses various static analysis tools depending on your framewo

The format of the generated argType will look something like:

```js
const argTypes = {
label: {
name: 'label',
type: { name: 'string', required: false },
defaultValue: 'Hello',
description: 'demo description',
table: {
type: { summary: 'string' },
defaultValue: { summary: 'Hello' },
}
control: {
type: 'text'
}
}
}
```
<!-- prettier-ignore-start -->

<CodeSnippets
paths={[
'common/storybook-generated-argtypes.js.mdx',
]}
/>

<!-- prettier-ignore-end -->

In this ArgTypes data structure, name, type, defaultValue, and description are standard fields in all ArgTypes (analogous to PropTypes in React). The table and control fields are addon-specific annotations. So, for example, the table annotation provides extra information to customize how label gets rendered, and the control annotation provides extra information for the control for editing the property.

Expand All @@ -69,53 +61,40 @@ In this ArgTypes data structure, name, type, defaultValue, and description are s

If you want more control over the props table or any other aspect of using argTypes, you can overwrite the generated argTypes for you component on a per-arg basis. For instance, with the above inferred argTypes and the following default export:

```js
export default {
title: 'Button',
component: Button,
argTypes: {
label: {
description: 'overwritten description',
table: {
type: { summary: 'something short', detail: 'something really really long' },
},
control: {
type: null,
},
},
},
};
```
<!-- prettier-ignore-start -->

<CodeSnippets
paths={[
'common/storybook-customize-argtypes.js.mdx',
]}
/>

<!-- prettier-ignore-end -->

These values--description, table.type, and controls.type--get merged over the defaults that are extracted by Storybook. The final merged values would be:

```js
const argTypes = {
label: {
name: 'label',
type: { name: 'string', required: false },
defaultValue: 'Hello',
description: 'overwritten description',
table: {
type: { summary: 'something short', detail: 'something really really long' },
defaultValue: { summary: 'Hello' },
}
control: {
type: null
}
}
}
```
<!-- prettier-ignore-start -->

<CodeSnippets
paths={[
'common/storybook-merged-argtypes.js.mdx',
]}
/>

<!-- prettier-ignore-end -->

In particular, this would render a row with a modified description, a type display with a dropdown that shows the detail, and no control.

#### Using argTypes in addons

If you want to access the argTypes of the current component inside an addon, you can use the `useArgTypes` hook from the `@storybook/api` package:

```js
import { useArgTypes } from '@storybook/api';
<!-- prettier-ignore-start -->

<CodeSnippets
paths={[
'common/storybook-argtypes-with-addon.js.mdx',
]}
/>

// inside your panel
const { argTypes } = useArgTypes();
```
<!-- prettier-ignore-end -->
Loading

0 comments on commit 30d685c

Please sign in to comment.