From 6af31bf7f33107c94613ed272c615571f8c119ad Mon Sep 17 00:00:00 2001 From: Kyle Gach Date: Tue, 2 Apr 2024 09:21:58 -0600 Subject: [PATCH] Merge pull request #26544 from storybookjs/update-docs-multiple-components Docs: Update multiple components guidance (cherry picked from commit 6b773a6157d7b071147e7346f82f0cfbdb406ecf) --- .../angular/list-story-reuse-data.ts.mdx | 5 --- .../html/list-story-reuse-data.js.mdx | 9 ---- .../html/list-story-reuse-data.ts.mdx | 9 ---- .../react/list-story-reuse-data.js.mdx | 6 --- .../react/list-story-reuse-data.ts-4-9.mdx | 5 --- .../react/list-story-reuse-data.ts.mdx | 5 --- .../solid/list-story-reuse-data.js.mdx | 6 --- .../solid/list-story-reuse-data.ts-4-9.mdx | 5 --- .../solid/list-story-reuse-data.ts.mdx | 5 --- .../vue/list-story-reuse-data.3.js.mdx | 5 --- .../vue/list-story-reuse-data.3.ts-4-9.mdx | 5 --- .../vue/list-story-reuse-data.3.ts.mdx | 5 --- docs/writing-stories/index.md | 4 +- .../stories-for-multiple-components.md | 44 ++++++++++++------- 14 files changed, 30 insertions(+), 88 deletions(-) diff --git a/docs/snippets/angular/list-story-reuse-data.ts.mdx b/docs/snippets/angular/list-story-reuse-data.ts.mdx index 3ff20f0d824a..7f531c257527 100644 --- a/docs/snippets/angular/list-story-reuse-data.ts.mdx +++ b/docs/snippets/angular/list-story-reuse-data.ts.mdx @@ -26,11 +26,6 @@ const meta: Meta = { export default meta; type Story = StoryObj; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const ManyItems: Story = { args: { Selected: Selected.args.isSelected, diff --git a/docs/snippets/html/list-story-reuse-data.js.mdx b/docs/snippets/html/list-story-reuse-data.js.mdx index 76a6f8820a3b..fe46d1a44f71 100644 --- a/docs/snippets/html/list-story-reuse-data.js.mdx +++ b/docs/snippets/html/list-story-reuse-data.js.mdx @@ -8,18 +8,9 @@ import { createListItem } from './ListItem'; import { Selected, Unselected } from './ListItem.stories'; export default { - /* ๐Ÿ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/configure/#configure-story-loading - * to learn how to generate automatic titles - */ title: 'List', }; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const ManyItems = { render: (args) => { const list = createList(args); diff --git a/docs/snippets/html/list-story-reuse-data.ts.mdx b/docs/snippets/html/list-story-reuse-data.ts.mdx index 999a38a65c25..50f984c0bb85 100644 --- a/docs/snippets/html/list-story-reuse-data.ts.mdx +++ b/docs/snippets/html/list-story-reuse-data.ts.mdx @@ -10,21 +10,12 @@ import { createListItem } from './ListItem'; import { Selected, Unselected } from './ListItem.stories'; const meta: Meta = { - /* ๐Ÿ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/configure/#configure-story-loading - * to learn how to generate automatic titles - */ title: 'List', }; export default meta; type Story = StoryObj; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const ManyItems: Story = { render: (args) => { const list = createList(args); diff --git a/docs/snippets/react/list-story-reuse-data.js.mdx b/docs/snippets/react/list-story-reuse-data.js.mdx index 2e35ca9c2dab..6f99fad942ef 100644 --- a/docs/snippets/react/list-story-reuse-data.js.mdx +++ b/docs/snippets/react/list-story-reuse-data.js.mdx @@ -13,12 +13,6 @@ export default { component: List, }; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ - export const ManyItems = { render: (args) => ( diff --git a/docs/snippets/react/list-story-reuse-data.ts-4-9.mdx b/docs/snippets/react/list-story-reuse-data.ts-4-9.mdx index 07767df39468..6fbee90aa76a 100644 --- a/docs/snippets/react/list-story-reuse-data.ts-4-9.mdx +++ b/docs/snippets/react/list-story-reuse-data.ts-4-9.mdx @@ -16,11 +16,6 @@ const meta = { export default meta; type Story = StoryObj; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const ManyItems: Story = { render: (args) => ( diff --git a/docs/snippets/react/list-story-reuse-data.ts.mdx b/docs/snippets/react/list-story-reuse-data.ts.mdx index 006e28639c99..5e8382162d6a 100644 --- a/docs/snippets/react/list-story-reuse-data.ts.mdx +++ b/docs/snippets/react/list-story-reuse-data.ts.mdx @@ -16,11 +16,6 @@ const meta: Meta = { export default meta; type Story = StoryObj; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const ManyItems: Story = { render: (args) => ( diff --git a/docs/snippets/solid/list-story-reuse-data.js.mdx b/docs/snippets/solid/list-story-reuse-data.js.mdx index 812843a505e6..e893f403e914 100644 --- a/docs/snippets/solid/list-story-reuse-data.js.mdx +++ b/docs/snippets/solid/list-story-reuse-data.js.mdx @@ -11,12 +11,6 @@ export default { component: List, }; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ - export const ManyItems = { render: (args) => ( diff --git a/docs/snippets/solid/list-story-reuse-data.ts-4-9.mdx b/docs/snippets/solid/list-story-reuse-data.ts-4-9.mdx index 5d4e5aae4e28..78e8b4d089fb 100644 --- a/docs/snippets/solid/list-story-reuse-data.ts-4-9.mdx +++ b/docs/snippets/solid/list-story-reuse-data.ts-4-9.mdx @@ -16,11 +16,6 @@ const meta = { export default meta; type Story = StoryObj; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const ManyItems: Story = { render: (args) => ( diff --git a/docs/snippets/solid/list-story-reuse-data.ts.mdx b/docs/snippets/solid/list-story-reuse-data.ts.mdx index 636f66d6b020..cccd2b421cc8 100644 --- a/docs/snippets/solid/list-story-reuse-data.ts.mdx +++ b/docs/snippets/solid/list-story-reuse-data.ts.mdx @@ -16,11 +16,6 @@ const meta: Meta = { export default meta; type Story = StoryObj; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const ManyItems: Story = { render: (args) => ( diff --git a/docs/snippets/vue/list-story-reuse-data.3.js.mdx b/docs/snippets/vue/list-story-reuse-data.3.js.mdx index d9384dd001d2..ab3b3f042072 100644 --- a/docs/snippets/vue/list-story-reuse-data.3.js.mdx +++ b/docs/snippets/vue/list-story-reuse-data.3.js.mdx @@ -11,11 +11,6 @@ export default { component: List, }; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const ManyItems = { render: (args) => ({ components: { List, ListItem }, diff --git a/docs/snippets/vue/list-story-reuse-data.3.ts-4-9.mdx b/docs/snippets/vue/list-story-reuse-data.3.ts-4-9.mdx index 37c83e2a7edc..bfcc9be89175 100644 --- a/docs/snippets/vue/list-story-reuse-data.3.ts-4-9.mdx +++ b/docs/snippets/vue/list-story-reuse-data.3.ts-4-9.mdx @@ -16,11 +16,6 @@ const meta = { export default meta; type Story = StoryObj; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const ManyItems: Story = { render: (args) => ({ components: { List, ListItem }, diff --git a/docs/snippets/vue/list-story-reuse-data.3.ts.mdx b/docs/snippets/vue/list-story-reuse-data.3.ts.mdx index 99c0bde71faa..93bf88a25d67 100644 --- a/docs/snippets/vue/list-story-reuse-data.3.ts.mdx +++ b/docs/snippets/vue/list-story-reuse-data.3.ts.mdx @@ -16,11 +16,6 @@ const meta: Meta = { export default meta; type Story = StoryObj; -/* - *๐Ÿ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const ManyItems: Story = { render: (args) => ({ components: { List, ListItem }, diff --git a/docs/writing-stories/index.md b/docs/writing-stories/index.md index abc6632d90f8..ec51a7dc1d39 100644 --- a/docs/writing-stories/index.md +++ b/docs/writing-stories/index.md @@ -357,7 +357,7 @@ Decorators [can be more complex](./decorators.md#context-for-mocking) and are of ## Stories for two or more components -When building design systems or component libraries, you may have two or more components created to work together. For instance, if you have a parent `List` component, it may require child `ListItem` components. +Sometimes you may have two or more components created to work together. For instance, if you have a parent `List` component, it may require child `ListItem` components. @@ -405,7 +405,7 @@ In such cases, it makes sense to render a different function for each story: -You can also reuse stories from the child `ListItem` in your `List` component. Thatโ€™s easier to maintain because you donโ€™t have to keep the identical story definitions updated in multiple places. +You can also reuse _story data_ from the child `ListItem` in your `List` component. Thatโ€™s easier to maintain because you donโ€™t have to update it in multiple places. diff --git a/docs/writing-stories/stories-for-multiple-components.md b/docs/writing-stories/stories-for-multiple-components.md index 708ccce28787..a51a58867445 100644 --- a/docs/writing-stories/stories-for-multiple-components.md +++ b/docs/writing-stories/stories-for-multiple-components.md @@ -2,7 +2,13 @@ title: 'Stories for multiple components' --- -It's useful to write stories that [render two or more components](../writing-stories/index.md#stories-for-two-or-more-components) at once if those components are designed to work together. For example, `ButtonGroups`, `Lists`, and `Page` components. Here's an example with `List` and `ListItem` components: +It's useful to write stories that [render two or more components](./index.md#stories-for-two-or-more-components) at once if those components are designed to work together. For example, `ButtonGroup`, `List`, and `Page` components. + +## Subcomponents + +When the components you're documenting have a parent-child relationship, you can use the `subcomponents` property to document them together. This is especially useful when the child component is not meant to be used on its own, but only as part of the parent component. + +Here's an example with `List` and `ListItem` components: @@ -33,32 +39,36 @@ Subcomponents are only intended for documentation purposes and have some limitat Let's talk about some techniques you can use to mitigate the above, which are especially useful in more complicated situations. -## Reusing subcomponent stories +## Reusing story definitions -The simplest change we can make to the above is to reuse the stories of the `ListItem` in the `List`: +We can also reduce repetition in our stories by reusing story definitions. Here, we can reuse the `ListItem` stories' args in the story for `List`: By rendering the `Unchecked` story with its args, we are able to reuse the input data from the `ListItem` stories in the `List`. + + However, we still arenโ€™t using args to control the `ListItem` stories, which means we cannot change them with controls and we cannot reuse them in other, more complex component stories. ## Using children as an arg @@ -82,19 +92,21 @@ Now that `children` is an arg, we can potentially reuse it in another story. However, there are some caveats when using this approach that you should be aware of. -The `children` `args` as any other arg needs to be JSON serializable. It means that you should: +The `children` arg, just like all args, needs to be JSON serializable. To avoid errors with your Storybook, you should: - Avoid using empty values +- Use [mapping](../essentials/controls.md#dealing-with-complex-values) if you want to adjust the value with [controls](../essentials/controls.md) - Use caution with components that include third party libraries -As they could lead into errors with your Storybook. - We're currently working on improving the overall experience for the children arg and allow you to edit children arg in a control and allow you to use other types of components in the near future. But for now you need to factor in this caveat when you're implementing your stories. + + + ## Creating a Template Component Another option that is more โ€œdataโ€-based is to create a special โ€œstory-generatingโ€ template component: