Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore: (Docs) Minor polish to the decorators docs #14907

Merged
merged 1 commit into from
May 13, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 25 additions & 12 deletions docs/writing-stories/decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
title: 'Decorators'
---

A decorator is a way to wrap a story in extra “rendering” functionality. Many addons define decorators in order to augment your stories with extra rendering or gather details about how your story is rendered.
A decorator is a way to wrap a story in extra “rendering” functionality. Many addons define decorators to augment your stories with extra rendering or gather details about how your story is rendered.

When writing stories, decorators are typically used to wrap stories with extra markup or context mocking.

## Wrap stories with extra markup

Some components require a “harness” to render in a useful way. For instance if a component runs right up to its edges, you might want to space it inside Storybook. Use a decorator to add spacing for all stories of the component.
Some components require a “harness” to render in a useful way. For instance, if a component runs right up to its edges, you might want to space it inside Storybook. Use a decorator to add spacing for all stories of the component.

![Story without padding](./decorators-no-padding.png)

Expand All @@ -17,7 +17,9 @@ Some components require a “harness” to render in a useful way. For instance
<CodeSnippets
paths={[
'react/your-component-with-decorator.js.mdx',
'react/your-component-with-decorator.story-function-js.js.mdx',
'react/your-component-with-decorator.ts.mdx',
'react/your-component-with-decorator.story-function-ts.ts.mdx',
'vue/your-component-with-decorator.js.mdx',
'angular/your-component-with-decorator.ts.mdx',
'svelte/your-component-with-decorator.js.mdx',
Expand All @@ -32,29 +34,37 @@ Some components require a “harness” to render in a useful way. For instance

## “Context” for mocking

Some libraries require components higher up in the component hierarchy to render properly. For example in Styled Components, a `ThemeProvider` is required if your components make use of themes. Add a single global decorator that adds this context to all stories in [`.storybook/preview.js`](../configure/overview.md#configure-story-rendering):
Some libraries require components higher up in the component hierarchy to render correctly. For example, in Styled Components, a `ThemeProvider` is necessary if your components use themes. Add a single global decorator that adds this context to all stories in [`.storybook/preview.js`](../configure/overview.md#configure-story-rendering):

<!-- prettier-ignore-start -->

<CodeSnippets
paths={[
'react/storybook-preview-with-styled-components-decorator.js.mdx',
'react/storybook-preview-with-styled-components-decorator.story-function.js.mdx',
]}
/>

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

In the example above, the theme is hardcoded to a mock value of `default` but you may want to vary that value, either on a per-story basis (if it is data you are mocking that is relevant to the other args of the story) or in a user controlled way (for instance to provide a theme switcher).
In the example above, the theme is hardcoded to a mock value of `default`. Still, you may want to vary that value, either on a per-story basis (if it is data you are mocking that is relevant to the other args of the story) or in a user-controlled way (for instance, to provide a theme switcher).

The second argument to a decorator function is the **story context** which in particular contains the keys:

- `args` - the story arguments. You can use some args in your decorators and drop them in the story implementation itself.
- `args` - the story arguments. You can use some [`args`](./args.md) in your decorators and drop them in the story implementation itself.
- `argTypes`- Storybook's [argTypes](../api/argtypes.md) allow you to customize and fine-tune your stories [`args`](./args.md).
- `globals` - Storybook-wide [globals](../essentials/toolbars-and-globals.md#globals). In particular you can use the [toolbars feature](../essentials/toolbars-and-globals.md#global-types-toolbar-annotations) to allow you to change these values using Storybook’s UI.
- `hooks` - Storybook's API hooks (e.g., useArgs).
- `parameters`- the story's static metadata, most commonly used to control Storybook's behavior of features and addons.
- `viewMode`- Storybook's current active window (e.g., canvas, docs).

- `globals` - the Storybook-wide [globals](../essentials/toolbars-and-globals.md#globals). In particular you can use the [toolbars feature](../essentials/toolbars-and-globals.md#global-types-toolbar-annotations) to allow you to change these values using Storybook’s UI.
<div class="aside">
💡 <strong>Note:</strong> This pattern can also be applied to your own stories. Some of Storybook's supported frameworks already use it (e.g., vue 2).
</div>

### Using decorators to provide data

If your components are “connected” and require side-loaded data to render, you can use decorators to provide that data in a mocked way, without having to refactor your components to take that data as an arg. There are several techniques to achieve this, depending on exactly how you are loading that data -- read more in the [building pages in Storybook](../workflows/build-pages-with-storybook.md) section.
If your components are “connected” and require side-loaded data to render, you can use decorators to provide that data in a mocked way without having to refactor your components to take that data as an arg. There are several techniques to achieve this. Depending on exactly how you are loading that data -- read more in the [building pages in Storybook](../workflows/build-pages-with-storybook.md) section.

## Story decorators

Expand All @@ -65,7 +75,7 @@ To define a decorator for a single story, use the `decorators` key on a named ex
<CodeSnippets
paths={[
'react/button-story-decorator.js.mdx',
'react/button-story-decorator.ts.mdx',
'react/button-story-decorator.story-function.js.mdx',
'vue/button-story-decorator.js.mdx',
'angular/button-story-decorator.ts.mdx',
'svelte/button-story-decorator.js.mdx',
Expand All @@ -75,7 +85,7 @@ To define a decorator for a single story, use the `decorators` key on a named ex

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

This is useful to ensure that the story remains a “pure” rendering of the component under test and any extra HTML or components you need to add don’t pollute that. In particular the [Source](../writing-docs/doc-blocks.md#source) docblock works best when you do this.
It is useful to ensure that the story remains a “pure” rendering of the component under test, and any extra HTML or components you need to add don’t pollute that. In particular the [Source](../writing-docs/doc-blocks.md#source) docblock works best when you do this.

## Component decorators

Expand All @@ -86,7 +96,9 @@ To define a decorator for all stories of a component, use the `decorators` key o
<CodeSnippets
paths={[
'react/button-story-component-decorator.js.mdx',
'react/button-story-component-decorator.story-function-js.js.mdx',
'react/button-story-component-decorator.ts.mdx',
'react/button-story-component-decorator.story-function-ts.ts.mdx',
'vue/button-story-component-decorator.js.mdx',
'angular/button-story-component-decorator.ts.mdx',
'svelte/button-story-component-decorator.js.mdx',
Expand All @@ -106,6 +118,7 @@ We can also set a decorator for **all stories** via the `decorators` export of y
<CodeSnippets
paths={[
'react/storybook-preview-global-decorator.js.mdx',
'react/storybook-preview-global-decorator.story-function.js.mdx',
'vue/storybook-preview-global-decorator.js.mdx',
'angular/storybook-preview-global-decorator.ts.mdx',
'svelte/storybook-preview-global-decorator.js.mdx',
Expand All @@ -117,10 +130,10 @@ We can also set a decorator for **all stories** via the `decorators` export of y

## Decorator inheritance

Like parameters, decorators can be defined globally, at the component level and for a single story (as we’ve seen).
Like parameters, decorators can be defined globally, at the component level, and for a single story (as we’ve seen).

All decorators, defined at all levels that apply to a story will run whenever that story is rendered, in the order:
All decorators, defined at all levels that apply to a story, will run whenever that story is rendered, in the order:

- Global decorators, in the order they are defined
- Component decorators, in the order they are defined
- Story decorators, in the order they are defined.
- Story decorators, in the order they are defined.