From 4caffee258781d6cc874b625913bc70391af98e4 Mon Sep 17 00:00:00 2001 From: jonniebigodes Date: Tue, 23 Jan 2024 11:36:20 +0000 Subject: [PATCH 01/20] initial changes --- docs/api/main-config-typescript.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/api/main-config-typescript.md b/docs/api/main-config-typescript.md index ae25c4fb308a..5ccf2ac0e020 100644 --- a/docs/api/main-config-typescript.md +++ b/docs/api/main-config-typescript.md @@ -6,15 +6,32 @@ Parent: [main.js|ts configuration](./main-config.md) Type: + + ```ts { check?: boolean; checkOptions?: CheckOptions; reactDocgen?: 'react-docgen' | 'react-docgen-typescript' | false; reactDocgenTypescriptOptions?: ReactDocgenTypescriptOptions; + skipCompiler?: boolean; } ``` + + + + +```ts +{ + check?: boolean; + checkOptions?: CheckOptions; + skipCompiler?: boolean; +} +``` + + + Configures how Storybook handles [TypeScript files](../configure/typescript.md). ## `check` @@ -49,6 +66,8 @@ Options to pass to `fork-ts-checker-webpack-plugin`, if [enabled](#check). See [ + + ## `reactDocgen` Type: `'react-docgen' | 'react-docgen-typescript' | false` @@ -74,7 +93,7 @@ Only available for React Storybook projects. Configure which library, if any, St Type: `ReactDocgenTypescriptOptions` -Only available for React Storybook projects. Options to pass to react-docgen-typescript-plugin if react-docgen-typescript is enabled. See [docs for available options](https://github.com/hipstersmoothie/react-docgen-typescript-plugin). +Only available for React Storybook projects. Options to pass to `react-docgen-typescript-plugin` if `react-docgen-typescript` is enabled. See [docs for available options](https://github.com/hipstersmoothie/react-docgen-typescript-plugin). @@ -86,6 +105,8 @@ Only available for React Storybook projects. Options to pass to react-docgen-typ + + ## `skipCompiler` Type: `boolean` From 661c7e76cc650900877c82f395c5d30ffd4c1348 Mon Sep 17 00:00:00 2001 From: jonniebigodes Date: Wed, 24 Jan 2024 14:35:09 +0000 Subject: [PATCH 02/20] initial changes --- docs/configure/typescript.md | 8 ++++++++ docs/essentials/controls.md | 6 ------ .../common/main-config-typescript-react-docgen.ts.mdx | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/configure/typescript.md b/docs/configure/typescript.md index eb789ed833e7..fc6b285a93fb 100644 --- a/docs/configure/typescript.md +++ b/docs/configure/typescript.md @@ -95,3 +95,11 @@ Out of the box, Storybook supports the `satisfies` operator for almost every fra ### The TypeScript auto-completion is not working on my editor If you're using Vue single file components and TypeScript, you can add both [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) and the [TypeScript Vue Plugin](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) for editor support, additional type safety and auto-completion. Nevertheless, if you're working with Svelte, you can add the [Svelte for VSCode extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) for similar benefits. + + + +### + +via `react-docgen`, you may run into a situation where specific properties may not work as expected + + diff --git a/docs/essentials/controls.md b/docs/essentials/controls.md index fcd5ea7f6333..46917698fe85 100644 --- a/docs/essentials/controls.md +++ b/docs/essentials/controls.md @@ -654,12 +654,6 @@ Type: `boolean` Show the full documentation, including description and default value, for each property in the Controls addon panel. See [usage example](#show-full-documentation-for-each-property), above. -#### `hideNoControlsWarning` - -Type: `boolean` - -Hide the warning that appears when no controls are defined for a story. See [usage example](#hide-nocontrols-warning), above. - #### `include` Type: `string[] | RegExp` diff --git a/docs/snippets/common/main-config-typescript-react-docgen.ts.mdx b/docs/snippets/common/main-config-typescript-react-docgen.ts.mdx index 6b908ac4000f..b882a3b835e4 100644 --- a/docs/snippets/common/main-config-typescript-react-docgen.ts.mdx +++ b/docs/snippets/common/main-config-typescript-react-docgen.ts.mdx @@ -8,7 +8,7 @@ const config: StorybookConfig = { framework: '@storybook/your-framework', stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], typescript: { - reactDocgen: 'react-docgen-typescript', + reactDocgen: 'react-docgen', }, }; From 56ad82da3c527d3dbe2e1c746017b1468aa71faa Mon Sep 17 00:00:00 2001 From: jonniebigodes Date: Sat, 27 Jan 2024 18:56:55 +0000 Subject: [PATCH 03/20] additional changes --- code/builders/builder-vite/README.md | 22 +- docs/api/arg-types.md | 14 +- docs/api/main-config-typescript.md | 8 +- docs/builders/vite.md | 2 +- docs/configure/typescript.md | 69 ++++- docs/essentials/controls.md | 256 ++++++++++-------- .../angular/compodoc-install.pnpm.js.mdx | 2 +- ...ain-config-typescript-check-options.ts.mdx | 2 +- .../main-config-typescript-check.ts.mdx | 2 +- .../storybook-main-extend-ts-config.ts.mdx | 11 +- ...storybook-vite-builder-react-docgen.js.mdx | 4 +- ...ipt-react-docgen-typescript-options.ts.mdx | 2 +- ...main-config-typescript-react-docgen.ts.mdx | 2 +- .../storybook-main-extend-ts-config.ts.mdx | 20 ++ .../react/storybook-main-prop-filter.ts.mdx | 23 ++ ...rybook-main-react-docgen-typescript.ts.mdx | 19 ++ 16 files changed, 297 insertions(+), 161 deletions(-) rename docs/snippets/{common => react}/main-config-typescript-react-docgen-typescript-options.ts.mdx (95%) rename docs/snippets/{common => react}/main-config-typescript-react-docgen.ts.mdx (92%) create mode 100644 docs/snippets/react/storybook-main-extend-ts-config.ts.mdx create mode 100644 docs/snippets/react/storybook-main-prop-filter.ts.mdx create mode 100644 docs/snippets/react/storybook-main-react-docgen-typescript.ts.mdx diff --git a/code/builders/builder-vite/README.md b/code/builders/builder-vite/README.md index 1e5026e36443..724cb5acee66 100644 --- a/code/builders/builder-vite/README.md +++ b/code/builders/builder-vite/README.md @@ -27,7 +27,7 @@ When installing Storybook, use the `--builder=vite` flag if you do not have a `v The builder supports both development mode in Storybook and building a static production version. -Your `vite.config` file will be used by Storybook. If you need to customize the vite config for Storybook, you have two choices: +Your `vite.config` file will be used by Storybook. If you need to customize the Vite config for Storybook, you have two choices: 1. Set values in your `vite.config` conditionally, based on an environment variable, for example. 2. Add a `viteFinal` config to your `.storybook/main.js` file. See [Customize Vite config](#customize-vite-config) for details. @@ -44,12 +44,12 @@ npx storybook@latest init --builder vite && npm run storybook ### Migration from webpack / CRA 1. Install `vite` and `@storybook/builder-vite` -2. Remove any explicit project dependencies on `webpack`, `react-scripts`, and any other webpack plugins or loaders. +2. Remove any explicit project dependencies on `webpack`, `react-scripts`, and any other Webpack plugins or loaders. 3. If you were previously using `@storybook/manager-webpack5`, you can remove it. Also remove `@storybook/builder-webpack5` or `@storybook/builder-webpack4` if they are installed. -4. Choose a vite-based Storybook "framework" to set in the `framework` option of your `.storybook/main.js` file. -5. Remove storybook webpack cache (`rm -rf node_modules/.cache`) -6. Update your `/public/index.html` file for vite (be sure there are no `%PUBLIC_URL%` inside it, which is a CRA variable) -7. Be sure that any files containing JSX syntax use a `.jsx` or `.tsx` file extension, which [vite requires](https://vitejs.dev/guide/features.html#jsx). This includes `.storybook/preview.jsx` if it contains JSX syntax. +4. Choose a Vite-based Storybook "framework" to set in the `framework` option of your `.storybook/main.js` file. +5. Remove Storybook Webpack cache (`rm -rf node_modules/.cache`) +6. Update your `/public/index.html` file for Vite (be sure there are no `%PUBLIC_URL%` inside it, which is a CRA variable) +7. Be sure that any files containing JSX syntax use a `.jsx` or `.tsx` file extension, which [Vite requires](https://vitejs.dev/guide/features.html#jsx). This includes `.storybook/preview.jsx` if it contains JSX syntax. 8. If you are using `@storybook/addon-interactions`, for now you'll need to add a [workaround](https://github.com/storybookjs/storybook/issues/18399) for jest-mock relying on the node `global` variable by creating a `.storybook/preview-head.html` file containing the following: ```html @@ -58,9 +58,9 @@ npx storybook@latest init --builder vite && npm run storybook ``` -9. Start up your storybook using the same `yarn storybook` or `npm run storybook` commands you are used to. +9. Start up your Storybook using the same `yarn storybook` or `npm run storybook` commands you are used to. -For other details about the differences between vite and webpack projects, be sure to read through the [vite documentation](https://vitejs.dev/). +For other details about the differences between Vite and Webpack projects, be sure to read through the [Vite documentation](https://vitejs.dev/). ### Customize Vite config @@ -105,7 +105,7 @@ const config = { export default config; ``` -The `viteFinal` function will give you `config` which is the combination of your project's vite config and the builder's own Vite config. +The `viteFinal` function will give you `config` which is the combination of your project's Vite config and the builder's own Vite config. You can tweak this as you want, for example to set up aliases, add new plugins etc. The `configType` variable will be either `"DEVELOPMENT"` or `"PRODUCTION"`. @@ -149,7 +149,7 @@ If you're using TypeScript, we encourage you to experiment and see which option The builder will by default enable Vite's [server.fs.strict](https://vitejs.dev/config/#server-fs-strict) option, for increased security. The default project `root` is set to the parent directory of the -storybook configuration directory. This can be overridden in viteFinal. +Storybook configuration directory. This can be overridden in [viteFinal](https://storybook.js.org/docs/api/main-config-vite-final). ## Known issues @@ -158,7 +158,7 @@ storybook configuration directory. This can be overridden in viteFinal. ## Contributing The Vite builder cannot build itself. -Are you willing to contribute? We are especially looking for Vue and Svelte experts, as the current maintainers are react users. +Are you willing to contribute? We are especially looking for Vue and Svelte experts, as the current maintainers are React users. Have a look at the GitHub issues with the `vite` label for known bugs. If you find any new bugs, feel free to create an issue or send a pull request! diff --git a/docs/api/arg-types.md b/docs/api/arg-types.md index 555462c1354f..ed9f66b4cdd0 100644 --- a/docs/api/arg-types.md +++ b/docs/api/arg-types.md @@ -16,13 +16,13 @@ If you are using the Storybook [docs](../writing-docs/index.md) addon (installed To do so, Storybook uses various static analysis tools depending on your framework. -| Framework | Static analysis tool | -| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -| React | [react-docgen](https://github.com/reactjs/react-docgen) or [react-docgen-typescript](https://github.com/styleguidist/react-docgen-typescript) | -| Vue | [vue-docgen-api](https://github.com/vue-styleguidist/vue-styleguidist/tree/dev/packages/vue-docgen-api) | -| Angular | [compodoc](https://compodoc.app/) | -| WebComponents | [custom-element.json](https://github.com/webcomponents/custom-elements-json) | -| Ember | [YUI doc](https://github.com/ember-learn/ember-cli-addon-docs-yuidoc#documenting-components) | +| Framework | Static analysis tool | +| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| React | [react-docgen](https://github.com/reactjs/react-docgen) (default) or [react-docgen-typescript](https://github.com/styleguidist/react-docgen-typescript) | +| Vue | [vue-docgen-api](https://github.com/vue-styleguidist/vue-styleguidist/tree/dev/packages/vue-docgen-api) | +| Angular | [compodoc](https://compodoc.app/) | +| WebComponents | [custom-element.json](https://github.com/webcomponents/custom-elements-json) | +| Ember | [YUI doc](https://github.com/ember-learn/ember-cli-addon-docs-yuidoc#documenting-components) | The data structure of `argTypes` is designed to match the output of the these tools. Properties specified manually will override what is inferred. diff --git a/docs/api/main-config-typescript.md b/docs/api/main-config-typescript.md index 5ccf2ac0e020..9af77907c54c 100644 --- a/docs/api/main-config-typescript.md +++ b/docs/api/main-config-typescript.md @@ -77,13 +77,13 @@ Default: - `false`: if `@storybook/react` is not installed - `'react-docgen'`: if `@storybook/react` is installed -Only available for React Storybook projects. Configure which library, if any, Storybook uses to parse React components, [react-docgen](https://github.com/reactjs/react-docgen) or [react-docgen-typescript](https://github.com/styleguidist/react-docgen-typescript). Set to `false` to disable parsing React components. `react-docgen-typescript` invokes the TypeScript compiler, which makes it slow but generally accurate. `react-docgen` performs its own analysis, which is much faster but incomplete. +Configures which library, if any, Storybook uses to parse React components, [react-docgen](https://github.com/reactjs/react-docgen) or [react-docgen-typescript](https://github.com/styleguidist/react-docgen-typescript). Set to `false` to disable parsing React components. `react-docgen-typescript` invokes the TypeScript compiler, which makes it slow but generally accurate. `react-docgen` performs its own analysis, which is much faster but incomplete. @@ -93,13 +93,13 @@ Only available for React Storybook projects. Configure which library, if any, St Type: `ReactDocgenTypescriptOptions` -Only available for React Storybook projects. Options to pass to `react-docgen-typescript-plugin` if `react-docgen-typescript` is enabled. See [docs for available options](https://github.com/hipstersmoothie/react-docgen-typescript-plugin). +Configures the options to pass to `react-docgen-typescript-plugin` if `react-docgen-typescript` is enabled. See [docs for available options](https://github.com/hipstersmoothie/react-docgen-typescript-plugin). diff --git a/docs/builders/vite.md b/docs/builders/vite.md index e8d722777e7d..a254e7b5f7a0 100644 --- a/docs/builders/vite.md +++ b/docs/builders/vite.md @@ -114,7 +114,7 @@ If you need to override it, you can use the `viteFinal` function and adjust it. ### ArgTypes are not generated automatically -Currently, [automatic argType inference](../api/arg-types.md#automatic-argtype-inference) is only available for React, Vue3 and Svelte (JSDocs only). With React, the Vite builder defaults to `react-docgen-typescript` if TypeScript is listed as a dependency. If you run into any issues, you can revert to `react-docgen` by updating your Storybook configuration file as follows: +Currently, [automatic argType inference](../api/arg-types.md#automatic-argtype-inference) is only available for React, Vue 3, and Svelte (JSDocs only). With React, the Vite builder defaults to `react-docgen`, a faster alternative to `react-docgen-typescript` for parsing React components. If you run into any issues, you can revert to `react-docgen-typescript` by updating your Storybook configuration file as follows: diff --git a/docs/configure/typescript.md b/docs/configure/typescript.md index fc6b285a93fb..61bc30d7eeb3 100644 --- a/docs/configure/typescript.md +++ b/docs/configure/typescript.md @@ -28,20 +28,50 @@ See the Vite builder [TypeScript documentation](https://github.com/storybookjs/b ### Extending the default configuration -Out of the box, Storybook is built to work with a wide range of third-party libraries, enabling you to safely access and document metadata (e.g., props, inputs) from your components without any additional configuration. Since Storybook supports multiple frameworks, it also includes a set of third-party packages to support each framework (e.g., `ts-loader` and `ngx-template-loader` for Angular, `react-docgen-typescript-plugin` for React). If you need to customize the default configuration for a specific use case scenario, refer to the [`config.typescript` API reference](../api/main-config-typescript.md). + -The above example extends the baseline configuration to remove existing props from third-party libraries. Useful if you want to document only your components. However, if you need to include them, you can do so by adjusting your configuration as follows: +Out of the box, Storybook is built to work with a wide range of third-party libraries, enabling you to safely access and document metadata (e.g., props, inputs) from your components without any additional configuration. Since Storybook supports multiple frameworks, it also includes a set of third-party packages to support each framework (e.g., `ts-loader`, `vue-docgen-api` for Vue). If you need to customize the default configuration for a specific use case scenario, you can adjust your Storybook configuration file and provide the required options. Listed below are the available options and examples of how to use them. + +| Option | Description | +| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `check` | Available for Webpack-based projects.
Enables type checking within Storybook
`typescript: { check: true },` | +| `checkOptions` | Requires the `check` option to be enabled.
Configures the [`fork-ts-checker-webpack-plugin`](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin) plugin
`typescript: { checkOptions:{},},` | +| `skipCompiler` | Disables parsing Typescript files through the compiler
`typescript: { skipCompiler:false,},` | + +
+ + + +Out of the box, Storybook is built to work with a wide range of third-party libraries, enabling you to safely access and document metadata (e.g., props) for your components without any additional configuration. It relies on [`react-docgen`](https://github.com/reactjs/react-docgen), a fast and highly customizable parser to process TypeScript files to infer the component's metadata and generate types automatically for improved performance and type safety. If you need to customize the default configuration for a specific use case scenario, you can adjust your Storybook configuration file and provide the required options. Listed below are the available options and examples of how to use them. + +| Option | Description | +| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `check` | Available for Webpack-based projects.
Enables type checking within Storybook
`typescript: { check: true },` | +| `checkOptions` | Requires the `check` option to be enabled.
Configures the [`fork-ts-checker-webpack-plugin`](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin) plugin
`typescript: { checkOptions: {},},` | +| `reactDocgen` | Configures the TypeScript parser used by Storybook.
Available options: `react-docgen` (default), `react-docgen-typescript`,` false`
`typescript: { reactDocgen: 'react-docgen'},` | +| `reactDocgenTypescriptOptions` | Requires the `reactDocgen`option to be `react-docgen-typescript`.
Configures the `react-docgen-typescript-plugin` plugin per builder
`typescript: { reactDocgen: 'react-docgen-typescript', reactDocgenTypescriptOptions: {},},` | +| `skipCompiler` | Disables parsing Typescript files through the compiler
`typescript: { skipCompiler:false,},` | + +
+ + + +Additional options are available for the `typescript` configuration option. See the [`config.typescript` API reference](../api/main-config-typescript.md) for more information. + + + ## Write stories with TypeScript Storybook provides zero-config TypeScript support, allowing you to write stories using this language without additional configuration. You can use this format for improved type safety and code completion. For example, if you're testing a `Button` component, you could do the following in your story file: @@ -92,14 +122,45 @@ Now, when you define a story or update an existing one, you'll automatically get Out of the box, Storybook supports the `satisfies` operator for almost every framework already using TypeScript version 4.9 or higher. However, due to the constraints of the Angular and Web Components framework, you might run into issues when applying this operator for additional type safety. This is primarily due to how both frameworks are currently implemented, making it almost impossible for Storybook to determine if the component property is required. If you encounter this issue, please open up a support request on [GitHub Discussions](https://github.com/storybookjs/storybook/discussions/new?category=help). + + ### The TypeScript auto-completion is not working on my editor If you're using Vue single file components and TypeScript, you can add both [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) and the [TypeScript Vue Plugin](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) for editor support, additional type safety and auto-completion. Nevertheless, if you're working with Svelte, you can add the [Svelte for VSCode extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) for similar benefits. + + -### +### Storybook doesn't create the required types for external packages + +If you're working with a project relying on a third-party library and you're running into an issue where you notice that the required types are not being generated, preventing you from accurately documenting your components, you can adjust the `reactDocgen` configuration option in your Storybook configuration file to use `react-docgen-typescript` instead and include the required options. For example: + + + + + + + + +### The types are not being generated for my component + +If you're working with a React project, type inference is automatically enabled for your components using the `react-docgen` library for improved build times and type safety. However, you may run into a situation where some options may not work as expected (e.g., [`Enums`](https://www.typescriptlang.org/docs/handbook/enums.html), React's [`forwardRef`](https://react.dev/reference/react/forwardRef)). This is primarily due to how the `react-docgen` package is implemented, making it difficult for Storybook to infer the component's metadata and generate types automatically. To solve this, you can update the `typescript` configuration option in your Storybook configuration file to use `react-docgen-typescript` instead. For example: + + + + + + -via `react-docgen`, you may run into a situation where specific properties may not work as expected +If you're still encountering issues, we recommend reaching out to the community using the default communication channels (e.g., [GitHub discussions](https://github.com/storybookjs/storybook/discussions/new?category=help)). diff --git a/docs/essentials/controls.md b/docs/essentials/controls.md index 46917698fe85..143e02c8246e 100644 --- a/docs/essentials/controls.md +++ b/docs/essentials/controls.md @@ -31,7 +31,49 @@ If you have stories in the older pre-Storybook 6 style, check the [args & contro -By default, Storybook will choose a control for each arg based on its initial value. This will work well with specific arg types (e.g., `boolean` or `string`). To enable them, add the `component` annotation to the default export of your story file, and it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component using [Compodoc](https://compodoc.app/) if you opt-in to use it, including first-class support for Angular's `inputs`, `outputs`, `properties`, `methods` and `view/content child/children`. +By default, Storybook will try to infer the required argTypes and associated controls for your stories based on the component's definition and initial value of the args using [Compodoc](https://compodoc.app/), a documentation generator for Angular applications that can extract the metadata of your components, including first-class support for Angular's `inputs`, `outputs`, `properties`, `methods`, and `view/content child/children`. If you opt-in to use it, you must take additional steps to set it up properly. + +Run the following command to install the tooling. + + + + + + + +Update your `angular.json` file to include the following configuration to include it in the Storybook's inbuilt builder configuration. + + + + + + + + +Finally, update your `.storybook/preview.ts` file to include the following configuration to import the metadata generated by Compodoc and use it to generate the controls and argTypes for your stories. + + + + + + + + +When you set the `component` annotation to the default export of your story file, it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component. @@ -45,9 +87,57 @@ By default, Storybook will choose a control for each arg based on its initial va + + +By default, Storybook will try to infer the required argTypes and associated controls for your stories based on the metadata provided by the [`@storybook/ember-cli-storybook`](https://github.com/storybookjs/ember-cli-storybook) addon. You'll need to take some additional steps to set it up properly. + +Update your `ember-cli-build.js` configuration file to include the addon. + + + + + + + +Restart your application to generate the metadata file (i.e., `storybook-docgen/index.json`) and update your `.storybook/preview.js` file to include it, which will be used to create the controls and argTypes for your stories. + + + + + + + + + +Enabling this feature will generate a `storybook-docgen/index.json` automatically with each build. For more information on how the metadata is generated, refer to [documentation](https://github.com/storybookjs/storybook/tree/next/code/frameworks/ember) for the Ember framework. + + + +When you set the `component` annotation to the default export of your story file, it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component. + + + + + + + + + -By default, Storybook will choose a control for each arg based on its initial value. This will work well with specific arg types (e.g., `boolean` or `string`). To enable them, add the `component` annotation to the default export of your story file and it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component using [`react-docgen`](https://github.com/reactjs/react-docgen) or [`react-docgen-typescript`](https://github.com/styleguidist/react-docgen-typescript) for TypeScript. +By default, Storybook will choose a control for each arg based on its initial value. This will work well with specific arg types (e.g., `boolean` or `string`). To enable them, add the `component` annotation to the default export of your story file, and it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component using [`react-docgen`](https://github.com/reactjs/react-docgen), a documentation generator for React components that also includes first-class support for TypeScript. @@ -79,7 +169,38 @@ By default, Storybook will choose a control for each arg based on its initial va - + + +By default, Storybook will try to infer the required argTypes and associated controls for your stories based on the component's definition and the initial value of the args. You'll need to take some additional steps to set it up properly. You can opt to generate a [`custom-elements.json`](https://github.com/webcomponents/custom-elements-json) file with [`@custom-elements-manifest/analyzer`](https://github.com/open-wc/custom-elements-manifest) if you're using the `pre-v1.0.0` version of the elements file or [`@custom-elements-manifest/analyzer`](https://github.com/open-wc/custom-elements-manifest) for newer versions and configure it in your Storybook UI configuration file (i.e., `.storybook/preview.js|ts`) to enable it. + + + + + + + + +When you set the `component` annotation to the default export of your story file, it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component. + + + + + + + + + + By default, Storybook will choose a control for each arg based on its initial value. This will work well with specific arg types (e.g., `boolean` or `string`). To enable them, add the `component` annotation to the default export of your story file, and it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component provided by the framework you've chosen to use. @@ -87,17 +208,16 @@ By default, Storybook will choose a control for each arg based on its initial va + + If you're using a framework that doesn't support this feature, you'll need to define the `argTypes` for your component [manually](#fully-custom-args). @@ -163,10 +283,10 @@ This replaces the input with a radio group for a more intuitive experience. Controls can automatically be inferred from arg's name with [regex](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp), but currently only for the color picker and date picker controls. If you've used the Storybook CLI to setup your project, it should have automatically created the following defaults in `.storybook/preview.js`: -| Control | Default regex | Description | -| :-------: | :--------------------------------------: | :-------------------------------------------------------: | +| Control | Default regex | Description | +| --------- | ---------------------------------------- | --------------------------------------------------------- | | **color** | /(background|color)$/i | Will display a color picker UI for the args that match it | -| **date** | `/Date$/` | Will display a date picker UI for the args that match it | +| **date** | `/Date$/` | Will display a date picker UI for the args that match it | If you haven't used the CLI to set the configuration, or if you want to define your patterns, use the `matchers` property in the `controls` parameter: @@ -223,9 +343,9 @@ Using `argTypes`, you can change the display and behavior of each control. ### Dealing with complex values -When dealing with non-primitive values, you'll notice that you'll run into some limitations. The most obvious issue is that not every value can be represented as part of the `args` param in the URL, losing the ability to share and deeplink to such a state. Beyond that, complex values such as JSX cannot be synchronized between the manager (e.g., Controls addon) and the preview (your story). +When dealing with non-primitive values, you'll notice that you'll run into some limitations. The most obvious issue is that not every value can be represented as part of the `args` param in the URL, losing the ability to share and deep link to such a state. Beyond that, complex values such as JSX cannot be synchronized between the manager (e.g., Controls addon) and the preview (your story). -One way to deal with this is to use primitive values (e.g., strings) as arg values and add a custom `render` function to convert these values to their complex counterpart before rendering. It isn't the nicest way to do it (see below), but certainly the most flexible. +One way to deal with this is to use primitive values (e.g., strings) as arg values and add a custom `render` function to convert them to their complex counterpart before rendering. It isn't the nicest way to do it (see below), but certainly the most flexible. @@ -284,7 +404,7 @@ As shown above, you can configure individual controls with the β€œcontrol" annot | **number** | `number` | Provides a numeric input to include the range of all possible values.
`argTypes: { even: { control: { type: 'number', min:1, max:30, step: 2 } }}` | | | `range` | Provides a range slider component to include all possible values.
`argTypes: { odd: { control: { type: 'range', min: 1, max: 30, step: 3 } }}` | | **object** | `object` | Provides a JSON-based editor component to handle the object's values.
Also allows edition in raw mode.
`argTypes: { user: { control: 'object' }}` | -| **array** | `object` | Provides a JSON-based editor component to handle the values of the array.
Also allows edition in raw mode.
`argTypes: { odd: { control: 'object' }}` | +| **array** | `object` | Provides a JSON-based editor component to handle the array's values.
Also allows edition in raw mode.
`argTypes: { odd: { control: 'object' }}` | | | `file` | Provides a file input component that returns an array of URLs.
Can be further customized to accept specific file types.
`argTypes: { avatar: { control: { type: 'file', accept: '.png' } }}` | | **enum** | `radio` | Provides a set of radio buttons based on the available options.
`argTypes: { contact: { control: 'radio', options: ['email', 'phone', 'mail'] }}` | | | `inline-radio` | Provides a set of inlined radio buttons based on the available options.
`argTypes: { contact: { control: 'inline-radio', options: ['email', 'phone', 'mail'] }}` | @@ -514,117 +634,13 @@ It may also contain at most one of the following operators: If no operator is provided, that is equivalent to `{ truthy: true }`. - - -## Troubleshooting - -### Controls are not automatically generated for my component - -Out of the box, Storybook will try to infer the required argTypes and associated controls for your stories based on the component's definition and the initial value of the args. However, in some cases, this may not be enough, and you may need to provide additional information to Storybook. To solve this, you can opt-in to use [Compodoc](https://compodoc.app/), a documentation generator for Angular applications that can extract the metadata of your components and generate the required argTypes and controls for your stories. - -Run the following command to install the tooling. - - - - - - - -Update your `angular.json` file to include the following configuration to include it in the Storybook's inbuilt builder configuration. - - - - - - - - -Finally, update your `.storybook/preview.ts` file to include the following configuration to import the metadata generated by Compodoc and use it to generate the controls and argTypes for your stories. - - - - - - - - - - - - -## Troubleshooting - -### Controls are not automatically generated for my component - -Out of the box, Storybook will try to infer the required argTypes and associated controls for your stories based on the component's definition and the initial value of the args. However, in some cases, this may not be enough, and you may need to provide additional information to Storybook. To solve this, you can generate a [`custom-elements.json`](https://github.com/webcomponents/custom-elements-json) file with [`@custom-elements-manifest/analyzer`](https://github.com/open-wc/custom-elements-manifest) if you're using the `pre-v1.0.0` version of the elements file or [`@custom-elements-manifest/analyzer`](https://github.com/open-wc/custom-elements-manifest) for newer versions and configure it in your Storybook UI configuration file (i.e., `.storybook/preview.js|ts`) to enable it. - - - - - - - - - - - + ## Troubleshooting ### Controls are not automatically generated for my component -Out of the box, Storybook will try to infer the required argTypes and associated controls for your stories based on the metadata provided by the [`@storybook/ember-cli-storybook`](https://github.com/storybookjs/ember-cli-storybook) addon. However, in some cases, this may not be enough, and you may need to customize your project configuration to provide additional information to Storybook to generate the required argTypes and controls for your stories. - -Update your `ember-cli-build.js` configuration file to include the addon. - - - - - - - - -Restart your application to generate the metadata file (i.e., `storybook-docgen/index.json`) and update your `.storybook/preview.js` file to include it, which will be used to create the controls and argTypes for your stories. - - - - - - - - - - -Enabling this feature will generate a `storybook-docgen/index.json` automatically with each build. For more information on how the metadata is generated, refer to [documentation](https://github.com/storybookjs/storybook/tree/next/code/frameworks/ember) for the Ember framework. - - +If you're working with Angular, Ember, or Web Components, automatic argTypes and controls inference will not work out of the box and requires you to provide [additional configuration](#choosing-the-control-type) to allow Storybook to retrieve the necessary metadata and generate the needed argTypes and controls for your stories. However, if you need additional customization, you can always [define them manually](#fully-custom-args). @@ -652,7 +668,7 @@ Specifies which properties to exclude from the Controls addon panel. Any propert Type: `boolean` -Show the full documentation, including description and default value, for each property in the Controls addon panel. See [usage example](#show-full-documentation-for-each-property), above. +Show the full documentation for each property in the Controls addon panel, including the description and default value. See [usage example](#show-full-documentation-for-each-property), above. #### `include` @@ -664,7 +680,7 @@ Specifies which properties to include in the Controls addon panel. Any propertie Type: `(string | { color: string; title?: string })[]` -Specify preset color swatches for the color picker control. Color value many be any valid CSS color. See [usage example](#specify-initial-preset-color-swatches), above. +Specify preset color swatches for the color picker control. The color value may be any valid CSS color. See [usage example](#specify-initial-preset-color-swatches), above. #### `sort` diff --git a/docs/snippets/angular/compodoc-install.pnpm.js.mdx b/docs/snippets/angular/compodoc-install.pnpm.js.mdx index 116346afd228..37c0310aa158 100644 --- a/docs/snippets/angular/compodoc-install.pnpm.js.mdx +++ b/docs/snippets/angular/compodoc-install.pnpm.js.mdx @@ -1,3 +1,3 @@ ```shell -pnpm add --save-dev @compodoc/compodo +pnpm add --save-dev @compodoc/compodoc ``` diff --git a/docs/snippets/common/main-config-typescript-check-options.ts.mdx b/docs/snippets/common/main-config-typescript-check-options.ts.mdx index 0581f7ee5ebf..90f5e7beeaa9 100644 --- a/docs/snippets/common/main-config-typescript-check-options.ts.mdx +++ b/docs/snippets/common/main-config-typescript-check-options.ts.mdx @@ -1,7 +1,7 @@ ```ts // .storybook/main.ts -// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) +// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-webpack5) import type { StorybookConfig } from '@storybook/your-framework'; const config: StorybookConfig = { diff --git a/docs/snippets/common/main-config-typescript-check.ts.mdx b/docs/snippets/common/main-config-typescript-check.ts.mdx index 5f0149dfcb5e..7c687ffbef58 100644 --- a/docs/snippets/common/main-config-typescript-check.ts.mdx +++ b/docs/snippets/common/main-config-typescript-check.ts.mdx @@ -1,7 +1,7 @@ ```ts // .storybook/main.ts -// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) +// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-webpack5) import type { StorybookConfig } from '@storybook/your-framework'; const config: StorybookConfig = { diff --git a/docs/snippets/common/storybook-main-extend-ts-config.ts.mdx b/docs/snippets/common/storybook-main-extend-ts-config.ts.mdx index a7fa7fd28444..7884f8a4724a 100644 --- a/docs/snippets/common/storybook-main-extend-ts-config.ts.mdx +++ b/docs/snippets/common/storybook-main-extend-ts-config.ts.mdx @@ -8,14 +8,9 @@ const config: StorybookConfig = { framework: '@storybook/your-framework', stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], typescript: { - reactDocgen: 'react-docgen-typescript', - reactDocgenTypescriptOptions: { - compilerOptions: { - allowSyntheticDefaultImports: false, - esModuleInterop: false, - }, - propFilter: () => true, - }, + check: false, + checkOptions: {}, + skipCompiler: false, }, }; diff --git a/docs/snippets/common/storybook-vite-builder-react-docgen.js.mdx b/docs/snippets/common/storybook-vite-builder-react-docgen.js.mdx index 99ef2c6a0372..84d035998c63 100644 --- a/docs/snippets/common/storybook-vite-builder-react-docgen.js.mdx +++ b/docs/snippets/common/storybook-vite-builder-react-docgen.js.mdx @@ -8,7 +8,9 @@ export default { builder: '@storybook/builder-vite', }, typescript: { - reactDocgen: 'react-docgen', // πŸ‘ˆ react-docgen configured here. + // Enables the `react-docgen-typescript` parser. + // See https://storybook.js.org/docs/api/main-config-typescript for more information about this option. + reactDocgen: 'react-docgen-typescript', }, }; ``` diff --git a/docs/snippets/common/main-config-typescript-react-docgen-typescript-options.ts.mdx b/docs/snippets/react/main-config-typescript-react-docgen-typescript-options.ts.mdx similarity index 95% rename from docs/snippets/common/main-config-typescript-react-docgen-typescript-options.ts.mdx rename to docs/snippets/react/main-config-typescript-react-docgen-typescript-options.ts.mdx index fc36649054e1..77319b608505 100644 --- a/docs/snippets/common/main-config-typescript-react-docgen-typescript-options.ts.mdx +++ b/docs/snippets/react/main-config-typescript-react-docgen-typescript-options.ts.mdx @@ -1,7 +1,7 @@ ```ts // .storybook/main.ts -// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) +// Replace your-framework with the framework you are using (e.g., react-webpack5, react-vite) import type { StorybookConfig } from '@storybook/your-framework'; const config: StorybookConfig = { diff --git a/docs/snippets/common/main-config-typescript-react-docgen.ts.mdx b/docs/snippets/react/main-config-typescript-react-docgen.ts.mdx similarity index 92% rename from docs/snippets/common/main-config-typescript-react-docgen.ts.mdx rename to docs/snippets/react/main-config-typescript-react-docgen.ts.mdx index b882a3b835e4..c96821c5a7ce 100644 --- a/docs/snippets/common/main-config-typescript-react-docgen.ts.mdx +++ b/docs/snippets/react/main-config-typescript-react-docgen.ts.mdx @@ -1,7 +1,7 @@ ```ts // .storybook/main.ts -// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) +// Replace your-framework with the framework you are using (e.g., react-webpack5, react-vite) import type { StorybookConfig } from '@storybook/your-framework'; const config: StorybookConfig = { diff --git a/docs/snippets/react/storybook-main-extend-ts-config.ts.mdx b/docs/snippets/react/storybook-main-extend-ts-config.ts.mdx new file mode 100644 index 000000000000..abf80d6e62f2 --- /dev/null +++ b/docs/snippets/react/storybook-main-extend-ts-config.ts.mdx @@ -0,0 +1,20 @@ +```ts +// .storybook/main.ts + +// Replace your-framework with the framework you are using (e.g., react-webpack5, react-vite) +import type { StorybookConfig } from '@storybook/your-framework'; + +const config: StorybookConfig = { + framework: '@storybook/your-framework', + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + typescript: { + check: false, + checkOptions: {}, + reactDocgen: 'react-docgen', + reactDocgenTypescriptOptions: {}, // Available only when reactDocgen is set to 'react-docgen-typescript' + skipCompiler: true, + }, +}; + +export default config; +``` diff --git a/docs/snippets/react/storybook-main-prop-filter.ts.mdx b/docs/snippets/react/storybook-main-prop-filter.ts.mdx new file mode 100644 index 000000000000..7d4f2763ac7e --- /dev/null +++ b/docs/snippets/react/storybook-main-prop-filter.ts.mdx @@ -0,0 +1,23 @@ +```ts +// .storybook/main.ts + +// Replace your-framework with the framework you are using (e.g., react-webpack5, react-vite) +import type { StorybookConfig } from '@storybook/your-framework'; + +const config: StorybookConfig = { + framework: '@storybook/your-framework', + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + typescript: { + reactDocgen: 'react-docgen-typescript', + reactDocgenTypescriptOptions: { + compilerOptions: { + allowSyntheticDefaultImports: false, + esModuleInterop: false, + }, + propFilter: () => true, + }, + }, +}; + +export default config; +``` diff --git a/docs/snippets/react/storybook-main-react-docgen-typescript.ts.mdx b/docs/snippets/react/storybook-main-react-docgen-typescript.ts.mdx new file mode 100644 index 000000000000..8dc82534b82f --- /dev/null +++ b/docs/snippets/react/storybook-main-react-docgen-typescript.ts.mdx @@ -0,0 +1,19 @@ +```ts +// .storybook/main.ts + +// Replace your-framework with the framework you are using (e.g., react-webpack5, react-vite) +import type { StorybookConfig } from '@storybook/your-framework'; + +const config: StorybookConfig = { + framework: '@storybook/your-framework', + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + typescript: { + reactDocgen: 'react-docgen-typescript', + // Provide your own options if necessary. + // See https://storybook.js.org/docs/configure/typescript for more information. + reactDocgenTypescriptOptions: {}, + }, +}; + +export default config; +``` From 7987e76169d2340aa49330ac878a62a0c689fc99 Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Mon, 29 Jan 2024 15:57:16 +0100 Subject: [PATCH 04/20] Refactor isCorePackage function to use versions map --- code/lib/core-common/src/utils/cli.ts | 32 +-------------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/code/lib/core-common/src/utils/cli.ts b/code/lib/core-common/src/utils/cli.ts index be022eac4460..71081381be99 100644 --- a/code/lib/core-common/src/utils/cli.ts +++ b/code/lib/core-common/src/utils/cli.ts @@ -97,34 +97,4 @@ export const createLogStream = async ( }); }; -const PACKAGES_EXCLUDED_FROM_CORE = [ - '@storybook/addon-bench', - '@storybook/addon-console', - '@storybook/addon-onboarding', - '@storybook/addon-postcss', - '@storybook/addon-designs', - '@storybook/addon-styling', - '@storybook/addon-styling-webpack', - '@storybook/bench', - '@storybook/builder-vite', - '@storybook/csf', - '@storybook/design-system', - '@storybook/ember-cli-storybook', - '@storybook/eslint-config-storybook', - '@storybook/expect', - '@storybook/jest', - '@storybook/linter-config', - '@storybook/mdx1-csf', - '@storybook/mdx2-csf', - '@storybook/react-docgen-typescript-plugin', - '@storybook/storybook-deployer', - '@storybook/test-runner', - '@storybook/testing-library', - '@storybook/testing-react', - '@nrwl/storybook', - '@nx/storybook', -]; -export const isCorePackage = (pkg: string) => - pkg.startsWith('@storybook/') && - !pkg.startsWith('@storybook/preset-') && - !PACKAGES_EXCLUDED_FROM_CORE.includes(pkg); +export const isCorePackage = (pkg: string) => Object.keys(versions).includes(pkg); From 731531ebcfe32e9a5a348a7b1ed633ad97a95055 Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Mon, 29 Jan 2024 15:57:26 +0100 Subject: [PATCH 05/20] Update name of getStorybookVersion to getCoercedStorybookVersion --- code/lib/cli/src/add.ts | 5 +++-- code/lib/cli/src/automigrate/helpers/mainConfigFile.ts | 4 ++-- code/lib/cli/src/automigrate/index.ts | 4 ++-- code/lib/core-common/src/utils/cli.test.ts | 5 ++--- code/lib/core-common/src/utils/cli.ts | 3 ++- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/code/lib/cli/src/add.ts b/code/lib/cli/src/add.ts index acfd7e4e6eb7..0321ec966fd7 100644 --- a/code/lib/cli/src/add.ts +++ b/code/lib/cli/src/add.ts @@ -1,7 +1,7 @@ import { getStorybookInfo, serverRequire, - getStorybookVersion, + getCoercedStorybookVersion, isCorePackage, JsPackageManagerFactory, type PackageManagerName, @@ -107,8 +107,9 @@ export async function add( // add to package.json const isStorybookAddon = addonName.startsWith('@storybook/'); const isAddonFromCore = isCorePackage(addonName); - const storybookVersion = await getStorybookVersion(packageManager); + const storybookVersion = await getCoercedStorybookVersion(packageManager); const version = versionSpecifier || (isAddonFromCore ? storybookVersion : latestVersion); + const addonWithVersion = SemVer.valid(version) ? `${addonName}@^${version}` : `${addonName}@${version}`; diff --git a/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts b/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts index c816ee90c5ec..c721dae39a31 100644 --- a/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts +++ b/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts @@ -12,7 +12,7 @@ import chalk from 'chalk'; import dedent from 'ts-dedent'; import path from 'path'; import type { JsPackageManager } from '@storybook/core-common'; -import { getStorybookVersion } from '@storybook/core-common'; +import { getCoercedStorybookVersion } from '@storybook/core-common'; const logger = console; @@ -93,7 +93,7 @@ export const getStorybookData = async ({ configDir: configDirFromScript, previewConfig: previewConfigPath, } = getStorybookInfo(packageJson, userDefinedConfigDir); - const storybookVersion = await getStorybookVersion(packageManager); + const storybookVersion = await getCoercedStorybookVersion(packageManager); const configDir = userDefinedConfigDir || configDirFromScript || '.storybook'; diff --git a/code/lib/cli/src/automigrate/index.ts b/code/lib/cli/src/automigrate/index.ts index 604393de492c..3adeff5e0ead 100644 --- a/code/lib/cli/src/automigrate/index.ts +++ b/code/lib/cli/src/automigrate/index.ts @@ -10,7 +10,7 @@ import invariant from 'tiny-invariant'; import { getStorybookInfo, loadMainConfig, - getStorybookVersion, + getCoercedStorybookVersion, JsPackageManagerFactory, } from '@storybook/core-common'; import type { PackageManagerName } from '@storybook/core-common'; @@ -156,7 +156,7 @@ export async function runFixes({ userSpecifiedConfigDir ); - const storybookVersion = await getStorybookVersion(packageManager); + const storybookVersion = await getCoercedStorybookVersion(packageManager); if (!storybookVersion) { logger.info(dedent` diff --git a/code/lib/core-common/src/utils/cli.test.ts b/code/lib/core-common/src/utils/cli.test.ts index f2444debb22a..708a11ebbba8 100644 --- a/code/lib/core-common/src/utils/cli.test.ts +++ b/code/lib/core-common/src/utils/cli.test.ts @@ -5,13 +5,12 @@ describe('UTILS', () => { describe.each([ ['@storybook/react', true], ['@storybook/node-logger', true], - ['@storybook/addon-info', true], - ['@storybook/something-random', true], - ['@storybook/preset-create-react-app', false], ['@storybook/linter-config', false], ['@storybook/design-system', false], ['@storybook/addon-styling', false], ['@storybook/addon-styling-webpack', false], + ['@storybook/addon-webpack5-compiler-swc', false], + ['@storybook/addon-webpack5-compiler-babel', false], ['@nx/storybook', false], ['@nrwl/storybook', false], ])('isCorePackage', (input, output) => { diff --git a/code/lib/core-common/src/utils/cli.ts b/code/lib/core-common/src/utils/cli.ts index 71081381be99..0dd8eae5277d 100644 --- a/code/lib/core-common/src/utils/cli.ts +++ b/code/lib/core-common/src/utils/cli.ts @@ -4,6 +4,7 @@ import { join } from 'path'; import tempy from 'tempy'; import { rendererPackages } from './get-storybook-info'; import type { JsPackageManager } from '../js-package-manager'; +import versions from '../versions'; export function parseList(str: string): string[] { return str @@ -12,7 +13,7 @@ export function parseList(str: string): string[] { .filter((item) => item.length > 0); } -export async function getStorybookVersion(packageManager: JsPackageManager) { +export async function getCoercedStorybookVersion(packageManager: JsPackageManager) { const packages = ( await Promise.all( Object.keys(rendererPackages).map(async (pkg) => ({ From fea8bb5a25ddd5eceb40ca0939fee911dac586f9 Mon Sep 17 00:00:00 2001 From: Kyle Gach Date: Mon, 29 Jan 2024 14:03:30 -0700 Subject: [PATCH 06/20] Fix bad docs paths --- docs/api/index.md | 2 +- docs/api/parameters.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/index.md b/docs/api/index.md index 168f0d0456a4..60edd614c32c 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -82,7 +82,7 @@ An overview of all available API references for Storybook. Parameters - Parameters are static metadata used to configure your stories addons in Storybook. They are specified at the story, meta (component), project (global) levels. + Parameters are static metadata used to configure your stories addons in Storybook. They are specified at the story, meta (component), project (global) levels. diff --git a/docs/api/parameters.md b/docs/api/parameters.md index 53174e387492..70c555c61783 100644 --- a/docs/api/parameters.md +++ b/docs/api/parameters.md @@ -2,7 +2,7 @@ title: 'Parameters' --- -Parameters are static metadata used to configure your [stories](../get-started/whats-a-story.md) and [addons](../addons/introduction.md) in Storybook. They are specified at the story, meta (component), project (global) levels. +Parameters are static metadata used to configure your [stories](../get-started/whats-a-story.md) and [addons](../addons/index.md) in Storybook. They are specified at the story, meta (component), project (global) levels. ## Story parameters @@ -36,7 +36,7 @@ Parameters specified at the story level apply to that story only. They are defin -Parameter's specified in a [CSF](../writing-stories/introduction.md#component-story-format-csf) file's meta configuration apply to all stories in that file. They are defined in the `parameters` property of the `meta` (default export): +Parameter's specified in a [CSF](../writing-stories/index.md#component-story-format-csf) file's meta configuration apply to all stories in that file. They are defined in the `parameters` property of the `meta` (default export): From 8ab95188f9ce9a79c251dacd4675f4f8084d6e2c Mon Sep 17 00:00:00 2001 From: Kyle Gach Date: Mon, 29 Jan 2024 14:06:52 -0700 Subject: [PATCH 07/20] Re-document subcomponents - Largely reverted relevant portions of #20233 & #21742 --- .../list-story-with-subcomponents.ts.mdx | 50 ++++++++++++++++++ .../common/subcomponents-in-meta.js.mdx | 10 ++++ .../common/subcomponents-in-meta.ts-4-9.mdx | 15 ++++++ .../common/subcomponents-in-meta.ts.mdx | 15 ++++++ .../list-story-with-subcomponents.js.mdx | 28 ++++++++++ .../list-story-with-subcomponents.ts-4-9.mdx | 32 +++++++++++ .../list-story-with-subcomponents.ts.mdx | 31 +++++++++++ .../vue/list-story-with-sub-components.js.mdx | 35 ++++++++++++ .../list-story-with-sub-components.ts-4-9.mdx | 41 ++++++++++++++ .../vue/list-story-with-sub-components.ts.mdx | 41 ++++++++++++++ .../list-story-with-subcomponents.js.mdx | 21 ++++++++ .../list-story-with-subcomponents.ts.mdx | 26 +++++++++ docs/writing-docs/autodocs.md | 23 ++++++++ .../doc-block-arg-types-subcomponents.png | Bin 0 -> 10007 bytes ...block-arg-types-subcomponents-for-list.png | Bin 0 -> 16815 bytes .../stories-for-multiple-components.md | 33 +++++++++++- 16 files changed, 399 insertions(+), 2 deletions(-) create mode 100644 docs/snippets/angular/list-story-with-subcomponents.ts.mdx create mode 100644 docs/snippets/common/subcomponents-in-meta.js.mdx create mode 100644 docs/snippets/common/subcomponents-in-meta.ts-4-9.mdx create mode 100644 docs/snippets/common/subcomponents-in-meta.ts.mdx create mode 100644 docs/snippets/react/list-story-with-subcomponents.js.mdx create mode 100644 docs/snippets/react/list-story-with-subcomponents.ts-4-9.mdx create mode 100644 docs/snippets/react/list-story-with-subcomponents.ts.mdx create mode 100644 docs/snippets/vue/list-story-with-sub-components.js.mdx create mode 100644 docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx create mode 100644 docs/snippets/vue/list-story-with-sub-components.ts.mdx create mode 100644 docs/snippets/web-components/list-story-with-subcomponents.js.mdx create mode 100644 docs/snippets/web-components/list-story-with-subcomponents.ts.mdx create mode 100644 docs/writing-docs/doc-block-arg-types-subcomponents.png create mode 100644 docs/writing-stories/doc-block-arg-types-subcomponents-for-list.png diff --git a/docs/snippets/angular/list-story-with-subcomponents.ts.mdx b/docs/snippets/angular/list-story-with-subcomponents.ts.mdx new file mode 100644 index 000000000000..17e8ab2e60aa --- /dev/null +++ b/docs/snippets/angular/list-story-with-subcomponents.ts.mdx @@ -0,0 +1,50 @@ +```ts +// List.stories.ts + +import type { Meta, StoryObj } from '@storybook/angular'; + +import { moduleMetadata } from '@storybook/angular'; + +import { CommonModule } from '@angular/common'; + +import { List } from './list.component'; +import { ListItem } from './list-item.component'; + +const meta: Meta = { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/angular/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'List', + component: List, + subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent + decorators: [ + moduleMetadata({ + declarations: [List, ListItem], + imports: [CommonModule], + }), + ], +}; + +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/7.0/angular/api/csf + * to learn how to use render functions. + */ +export const Empty: Story = {}; + +export const OneItem: Story = { + args: {}, + render: (args) => ({ + props: args, + template: ` + + + + `, + }), +}; +``` diff --git a/docs/snippets/common/subcomponents-in-meta.js.mdx b/docs/snippets/common/subcomponents-in-meta.js.mdx new file mode 100644 index 000000000000..c925367d0b09 --- /dev/null +++ b/docs/snippets/common/subcomponents-in-meta.js.mdx @@ -0,0 +1,10 @@ +```js +// ButtonGroup.stories.js|jsx + +import { Button, ButtonGroup } from './ButtonGroup'; + +export default { + component: ButtonGroup, + subcomponents: { Button }, +}; +``` diff --git a/docs/snippets/common/subcomponents-in-meta.ts-4-9.mdx b/docs/snippets/common/subcomponents-in-meta.ts-4-9.mdx new file mode 100644 index 000000000000..49f5deefb5ca --- /dev/null +++ b/docs/snippets/common/subcomponents-in-meta.ts-4-9.mdx @@ -0,0 +1,15 @@ +```ts +// ButtonGroup.stories.ts|tsx + +// Replace your-framework with the name of your framework +import type { Meta, StoryObj } from '@storybook/your-framework'; + +import { Button, ButtonGroup } from './ButtonGroup'; + +const meta = { + component: ButtonGroup, + subcomponents: { Button }, +} satisfies Meta; + +export default meta; +``` \ No newline at end of file diff --git a/docs/snippets/common/subcomponents-in-meta.ts.mdx b/docs/snippets/common/subcomponents-in-meta.ts.mdx new file mode 100644 index 000000000000..8847609e9fac --- /dev/null +++ b/docs/snippets/common/subcomponents-in-meta.ts.mdx @@ -0,0 +1,15 @@ +```ts +// ButtonGroup.stories.ts|tsx + +// Replace your-framework with the name of your framework +import type { Meta } from '@storybook/your-framework'; + +import { Button, ButtonGroup } from './ButtonGroup'; + +const meta: Meta = { + component: ButtonGroup, + subcomponents: { Button }, +}; + +export default meta; +``` \ No newline at end of file diff --git a/docs/snippets/react/list-story-with-subcomponents.js.mdx b/docs/snippets/react/list-story-with-subcomponents.js.mdx new file mode 100644 index 000000000000..1bae39ac9a4e --- /dev/null +++ b/docs/snippets/react/list-story-with-subcomponents.js.mdx @@ -0,0 +1,28 @@ +```js +// List.stories.js|jsx + +import React from 'react'; + +import { List } from './List'; +import { ListItem } from './ListItem'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'List', + component: List, + subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent +}; + +export const Empty = {}; + +export const OneItem = { + render: (args) => ( + + + + ), +}; +``` diff --git a/docs/snippets/react/list-story-with-subcomponents.ts-4-9.mdx b/docs/snippets/react/list-story-with-subcomponents.ts-4-9.mdx new file mode 100644 index 000000000000..71abc96d3c2c --- /dev/null +++ b/docs/snippets/react/list-story-with-subcomponents.ts-4-9.mdx @@ -0,0 +1,32 @@ +```ts +// List.stories.ts|tsx + +import type { Meta, StoryObj } from '@storybook/react'; + +import { List } from './List'; +import { ListItem } from './ListItem'; + +const meta = { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'List', + component: List, + //πŸ‘ˆ Adds the ListItem component as a subcomponent + subcomponents: { ListItem }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Empty: Story = {}; + +export const OneItem: Story = { + render: (args) => ( + + + + ), +}; +``` diff --git a/docs/snippets/react/list-story-with-subcomponents.ts.mdx b/docs/snippets/react/list-story-with-subcomponents.ts.mdx new file mode 100644 index 000000000000..dcb959020f98 --- /dev/null +++ b/docs/snippets/react/list-story-with-subcomponents.ts.mdx @@ -0,0 +1,31 @@ +```tsx +// List.stories.ts|tsx + +import type { Meta, StoryObj } from '@storybook/react'; + +import { List } from './List'; +import { ListItem } from './ListItem'; + +const meta: Meta = { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'List', + component: List, + subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent +}; + +export default meta; +type Story = StoryObj; + +export const Empty: Story = {}; + +export const OneItem: Story = { + render: (args) => ( + + + + ), +}; +``` diff --git a/docs/snippets/vue/list-story-with-sub-components.js.mdx b/docs/snippets/vue/list-story-with-sub-components.js.mdx new file mode 100644 index 000000000000..9d674dbfebf4 --- /dev/null +++ b/docs/snippets/vue/list-story-with-sub-components.js.mdx @@ -0,0 +1,35 @@ +```js +// List.stories.js + +import List from './List.vue'; +import ListItem from './ListItem.vue'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'List', + component: List, + subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent +}; + +/* + *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/7.0/vue/api/csf + * to learn how to use render functions. + */ +export const Empty = { + render: () => ({ + components: { List }, + template: '', + }), +}; + +export const OneItem = { + render: () => ({ + components: { List, ListItem }, + template: '', + }), +}; +``` diff --git a/docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx b/docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx new file mode 100644 index 000000000000..b4d2023904bc --- /dev/null +++ b/docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx @@ -0,0 +1,41 @@ +```ts +// List.stories.ts + +// Replace vue3 with vue if you are using Storybook for Vue 2 +import type { Meta, StoryObj } from '@storybook/vue3'; + +import List from './List.vue'; +import ListItem from './ListItem.vue'; + +const meta = { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'List', + component: List, + subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent +} satisfies 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/7.0/vue/api/csf + * to learn how to use render functions. + */ +export const Empty = { + render: () => ({ + components: { List }, + template: '', + }), +}; + +export const OneItem: Story = { + render: (args) => ({ + components: { List, ListItem }, + template: '', + }), +}; +``` diff --git a/docs/snippets/vue/list-story-with-sub-components.ts.mdx b/docs/snippets/vue/list-story-with-sub-components.ts.mdx new file mode 100644 index 000000000000..e6e6a2a58942 --- /dev/null +++ b/docs/snippets/vue/list-story-with-sub-components.ts.mdx @@ -0,0 +1,41 @@ +```ts +// List.stories.ts + +// Replace vue3 with vue if you are using Storybook for Vue 2 +import type { Meta, StoryObj } from '@storybook/vue3'; + +import List from './List.vue'; +import ListItem from './ListItem.vue'; + +const meta: Meta = { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'List', + component: List, + subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent +}; + +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/7.0/vue/api/csf + * to learn how to use render functions. + */ +export const Empty: Story = { + render: () => ({ + components: { List }, + template: '', + }), +}; + +export const OneItem: Story = { + render: () => ({ + components: { List, ListItem }, + template: '', + }), +}; +``` diff --git a/docs/snippets/web-components/list-story-with-subcomponents.js.mdx b/docs/snippets/web-components/list-story-with-subcomponents.js.mdx new file mode 100644 index 000000000000..ced80cc450bf --- /dev/null +++ b/docs/snippets/web-components/list-story-with-subcomponents.js.mdx @@ -0,0 +1,21 @@ +```js +// List.stories.js + +import { html } from 'lit'; + +export default { + title: 'List', + component: 'demo-list', + subcomponents: { ListItem: 'demo-list-item' }, // πŸ‘ˆ Adds the ListItem component as a subcomponent +}; + +export const Empty = {}; + +export const OneItem = { + render: () => html` + + + + `, +}; +``` diff --git a/docs/snippets/web-components/list-story-with-subcomponents.ts.mdx b/docs/snippets/web-components/list-story-with-subcomponents.ts.mdx new file mode 100644 index 000000000000..511213a1030e --- /dev/null +++ b/docs/snippets/web-components/list-story-with-subcomponents.ts.mdx @@ -0,0 +1,26 @@ +```ts +// List.stories.ts + +import type { Meta, StoryObj } from '@storybook/web-components'; + +import { html } from 'lit'; + +const meta: Meta = { + title: 'List', + component: 'demo-list', + subcomponents: { ListItem: 'demo-list-item' }, // πŸ‘ˆ Adds the ListItem component as a subcomponent +}; +export default meta; + +type Story = StoryObj; + +export const Empty: Story = {}; + +export const OneItem: Story = { + render: () => html` + + + + `, +}; +``` diff --git a/docs/writing-docs/autodocs.md b/docs/writing-docs/autodocs.md index 4c1dcaea5fdb..20b459e03f09 100644 --- a/docs/writing-docs/autodocs.md +++ b/docs/writing-docs/autodocs.md @@ -183,6 +183,29 @@ Creating automated documentation with Storybook's Autodocs provides you with the ## Advanced configuration +### Documenting multiple components + +Sometimes it's helpful to document multiple components together. For example, a component library’s ButtonGroup and Button components might not make sense without one another. + +Autodocs allows you to document your "main" component, defined by the `component` property, as well as one or more `subcomponents` related to it. + + + + + + + +![Subcomponents in ArgTypes doc block](./doc-block-arg-types-subcomponents.png) + +The main component and its subcomponents will show up in a tabbed version of the [`ArgTypes` doc block](./doc-blocks.md#argtypes). The tab titles will correspond to the keys of the subcomponents object. + +If you want to organize your documentation differently for component groups, we recommend [using MDX](./mdx.md). It gives you complete control over how your components are displayed and supports any configuration. + ### Customize the Docs Container The Docs Container is the component that wraps up the documentation page. It's responsible for rendering the documentation page in Storybook's UI. You can customize it by creating your own component and updating your Storybook UI configuration file (i.e., `.storybook/preview.js`) to reference it. diff --git a/docs/writing-docs/doc-block-arg-types-subcomponents.png b/docs/writing-docs/doc-block-arg-types-subcomponents.png new file mode 100644 index 0000000000000000000000000000000000000000..bd883288f6f154c547b35ce94b3a972a4494ba5c GIT binary patch literal 10007 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 literal 0 HcmV?d00001 diff --git a/docs/writing-stories/doc-block-arg-types-subcomponents-for-list.png b/docs/writing-stories/doc-block-arg-types-subcomponents-for-list.png new file mode 100644 index 0000000000000000000000000000000000000000..b0d5469f0e3f441ce6413bab9ef1b5fa80719647 GIT binary patch literal 16815 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 + + + + + +Note that by adding a `subcomponents` property to the default export, we get an extra panel on the [ArgTypes](../writing-docs/doc-blocks.md#argtypes) and [Controls](../essentials/controls.md#) tables, listing the props of `ListItem`: + +![Subcomponents in ArgTypes doc block](./doc-block-arg-types-subcomponents-for-list.png) + +The downside of the approach used above, where each story creates its own combination of components, is that it does not take advantage of Storybook [Args](../writing-stories/args.md) meaning: + +1. You cannot change the stories via the controls panel +2. There is no [args reuse](../writing-stories/index.md#using-args) possible, which makes the stories harder to maintain. + +Let's talk about some techniques you can use to mitigate the above, which are especially useful in more complicated situations. ## Reusing subcomponent stories -The simplest approach we can take is to reuse the stories of the `ListItem` in the `List`: +The simplest change we can make to the above is to reuse the stories of the `ListItem` in the `List`: From f18392262c76070787dcb7e62158b96d6f2a3b38 Mon Sep 17 00:00:00 2001 From: Kyle Gach Date: Mon, 29 Jan 2024 17:09:41 -0700 Subject: [PATCH 08/20] Update docs/writing-docs/autodocs.md Co-authored-by: Jeppe Reinhold --- docs/writing-docs/autodocs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/writing-docs/autodocs.md b/docs/writing-docs/autodocs.md index 20b459e03f09..9ea752168c12 100644 --- a/docs/writing-docs/autodocs.md +++ b/docs/writing-docs/autodocs.md @@ -202,7 +202,7 @@ Autodocs allows you to document your "main" component, defined by the `component ![Subcomponents in ArgTypes doc block](./doc-block-arg-types-subcomponents.png) -The main component and its subcomponents will show up in a tabbed version of the [`ArgTypes` doc block](./doc-blocks.md#argtypes). The tab titles will correspond to the keys of the subcomponents object. +The main component and its subcomponents will show up in a tabbed version of the [`ArgTypes` doc block](./doc-blocks.md#argtypes). The tab titles will correspond to the keys of the `subcomponents` object. If you want to organize your documentation differently for component groups, we recommend [using MDX](./mdx.md). It gives you complete control over how your components are displayed and supports any configuration. From fd87a7f3e4d26df27f9ec557f541e1d975287dcd Mon Sep 17 00:00:00 2001 From: Kyle Gach Date: Mon, 29 Jan 2024 17:10:44 -0700 Subject: [PATCH 09/20] Address comments - Update un-reverted snippets for v8 --- .../list-story-with-subcomponents.ts.mdx | 13 +------------ .../react/list-story-with-subcomponents.js.mdx | 8 +------- .../list-story-with-subcomponents.ts-4-9.mdx | 14 ++++---------- .../react/list-story-with-subcomponents.ts.mdx | 9 ++------- .../vue/list-story-with-sub-components.js.mdx | 11 ----------- .../list-story-with-sub-components.ts-4-9.mdx | 18 +++--------------- .../vue/list-story-with-sub-components.ts.mdx | 16 ++-------------- .../list-story-with-subcomponents.js.mdx | 1 - .../list-story-with-subcomponents.ts.mdx | 1 - 9 files changed, 13 insertions(+), 78 deletions(-) diff --git a/docs/snippets/angular/list-story-with-subcomponents.ts.mdx b/docs/snippets/angular/list-story-with-subcomponents.ts.mdx index 17e8ab2e60aa..e79ac6301ded 100644 --- a/docs/snippets/angular/list-story-with-subcomponents.ts.mdx +++ b/docs/snippets/angular/list-story-with-subcomponents.ts.mdx @@ -1,6 +1,5 @@ ```ts // List.stories.ts - import type { Meta, StoryObj } from '@storybook/angular'; import { moduleMetadata } from '@storybook/angular'; @@ -11,11 +10,6 @@ import { List } from './list.component'; import { ListItem } from './list-item.component'; const meta: Meta = { - /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/angular/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ - title: 'List', component: List, subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent decorators: [ @@ -25,15 +19,10 @@ 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/7.0/angular/api/csf - * to learn how to use render functions. - */ export const Empty: Story = {}; export const OneItem: Story = { diff --git a/docs/snippets/react/list-story-with-subcomponents.js.mdx b/docs/snippets/react/list-story-with-subcomponents.js.mdx index 1bae39ac9a4e..4edaa677c3f5 100644 --- a/docs/snippets/react/list-story-with-subcomponents.js.mdx +++ b/docs/snippets/react/list-story-with-subcomponents.js.mdx @@ -1,17 +1,11 @@ -```js +```jsx // List.stories.js|jsx - import React from 'react'; import { List } from './List'; import { ListItem } from './ListItem'; export default { - /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ - title: 'List', component: List, subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent }; diff --git a/docs/snippets/react/list-story-with-subcomponents.ts-4-9.mdx b/docs/snippets/react/list-story-with-subcomponents.ts-4-9.mdx index 71abc96d3c2c..d527fe149fac 100644 --- a/docs/snippets/react/list-story-with-subcomponents.ts-4-9.mdx +++ b/docs/snippets/react/list-story-with-subcomponents.ts-4-9.mdx @@ -1,23 +1,17 @@ -```ts +```tsx // List.stories.ts|tsx - +import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { List } from './List'; import { ListItem } from './ListItem'; const meta = { - /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ - title: 'List', component: List, - //πŸ‘ˆ Adds the ListItem component as a subcomponent - subcomponents: { ListItem }, + subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent } satisfies Meta; - export default meta; + type Story = StoryObj; export const Empty: Story = {}; diff --git a/docs/snippets/react/list-story-with-subcomponents.ts.mdx b/docs/snippets/react/list-story-with-subcomponents.ts.mdx index dcb959020f98..71a08b1fe6bb 100644 --- a/docs/snippets/react/list-story-with-subcomponents.ts.mdx +++ b/docs/snippets/react/list-story-with-subcomponents.ts.mdx @@ -1,22 +1,17 @@ ```tsx // List.stories.ts|tsx - +import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { List } from './List'; import { ListItem } from './ListItem'; const meta: Meta = { - /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ - title: 'List', component: List, subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent }; - export default meta; + type Story = StoryObj; export const Empty: Story = {}; diff --git a/docs/snippets/vue/list-story-with-sub-components.js.mdx b/docs/snippets/vue/list-story-with-sub-components.js.mdx index 9d674dbfebf4..0c6e082e6a92 100644 --- a/docs/snippets/vue/list-story-with-sub-components.js.mdx +++ b/docs/snippets/vue/list-story-with-sub-components.js.mdx @@ -1,24 +1,13 @@ ```js // List.stories.js - import List from './List.vue'; import ListItem from './ListItem.vue'; export default { - /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ - title: 'List', component: List, subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent }; -/* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ export const Empty = { render: () => ({ components: { List }, diff --git a/docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx b/docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx index b4d2023904bc..7d9c073bfa83 100644 --- a/docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx +++ b/docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx @@ -1,31 +1,19 @@ ```ts // List.stories.ts - -// Replace vue3 with vue if you are using Storybook for Vue 2 import type { Meta, StoryObj } from '@storybook/vue3'; import List from './List.vue'; import ListItem from './ListItem.vue'; const meta = { - /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ - title: 'List', component: List, subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent } satisfies 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/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const Empty = { +export const Empty: Story = { render: () => ({ components: { List }, template: '', @@ -33,7 +21,7 @@ export const Empty = { }; export const OneItem: Story = { - render: (args) => ({ + render: () => ({ components: { List, ListItem }, template: '', }), diff --git a/docs/snippets/vue/list-story-with-sub-components.ts.mdx b/docs/snippets/vue/list-story-with-sub-components.ts.mdx index e6e6a2a58942..b299d5350314 100644 --- a/docs/snippets/vue/list-story-with-sub-components.ts.mdx +++ b/docs/snippets/vue/list-story-with-sub-components.ts.mdx @@ -1,34 +1,22 @@ ```ts // List.stories.ts - -// Replace vue3 with vue if you are using Storybook for Vue 2 import type { Meta, StoryObj } from '@storybook/vue3'; import List from './List.vue'; import ListItem from './ListItem.vue'; const meta: Meta = { - /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ - title: 'List', component: List, subcomponents: { ListItem }, //πŸ‘ˆ Adds the ListItem component as a subcomponent }; - 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/7.0/vue/api/csf - * to learn how to use render functions. - */ export const Empty: Story = { render: () => ({ components: { List }, - template: '', + template: '', }), }; diff --git a/docs/snippets/web-components/list-story-with-subcomponents.js.mdx b/docs/snippets/web-components/list-story-with-subcomponents.js.mdx index ced80cc450bf..2e34a5e7104d 100644 --- a/docs/snippets/web-components/list-story-with-subcomponents.js.mdx +++ b/docs/snippets/web-components/list-story-with-subcomponents.js.mdx @@ -1,6 +1,5 @@ ```js // List.stories.js - import { html } from 'lit'; export default { diff --git a/docs/snippets/web-components/list-story-with-subcomponents.ts.mdx b/docs/snippets/web-components/list-story-with-subcomponents.ts.mdx index 511213a1030e..d433d2f02fd0 100644 --- a/docs/snippets/web-components/list-story-with-subcomponents.ts.mdx +++ b/docs/snippets/web-components/list-story-with-subcomponents.ts.mdx @@ -1,6 +1,5 @@ ```ts // List.stories.ts - import type { Meta, StoryObj } from '@storybook/web-components'; import { html } from 'lit'; From b644216cc4c8be2e0d95271b60bd7f9675f86a57 Mon Sep 17 00:00:00 2001 From: Kyle Gach Date: Tue, 30 Jan 2024 10:07:24 -0700 Subject: [PATCH 10/20] Consolidate snippets --- .../common/subcomponents-in-meta.js.mdx | 10 ---------- .../common/subcomponents-in-meta.ts-4-9.mdx | 15 --------------- .../common/subcomponents-in-meta.ts.mdx | 15 --------------- docs/writing-docs/autodocs.md | 13 ++++++++++--- .../doc-block-arg-types-subcomponents.png | Bin 10007 -> 0 bytes 5 files changed, 10 insertions(+), 43 deletions(-) delete mode 100644 docs/snippets/common/subcomponents-in-meta.js.mdx delete mode 100644 docs/snippets/common/subcomponents-in-meta.ts-4-9.mdx delete mode 100644 docs/snippets/common/subcomponents-in-meta.ts.mdx delete mode 100644 docs/writing-docs/doc-block-arg-types-subcomponents.png diff --git a/docs/snippets/common/subcomponents-in-meta.js.mdx b/docs/snippets/common/subcomponents-in-meta.js.mdx deleted file mode 100644 index c925367d0b09..000000000000 --- a/docs/snippets/common/subcomponents-in-meta.js.mdx +++ /dev/null @@ -1,10 +0,0 @@ -```js -// ButtonGroup.stories.js|jsx - -import { Button, ButtonGroup } from './ButtonGroup'; - -export default { - component: ButtonGroup, - subcomponents: { Button }, -}; -``` diff --git a/docs/snippets/common/subcomponents-in-meta.ts-4-9.mdx b/docs/snippets/common/subcomponents-in-meta.ts-4-9.mdx deleted file mode 100644 index 49f5deefb5ca..000000000000 --- a/docs/snippets/common/subcomponents-in-meta.ts-4-9.mdx +++ /dev/null @@ -1,15 +0,0 @@ -```ts -// ButtonGroup.stories.ts|tsx - -// Replace your-framework with the name of your framework -import type { Meta, StoryObj } from '@storybook/your-framework'; - -import { Button, ButtonGroup } from './ButtonGroup'; - -const meta = { - component: ButtonGroup, - subcomponents: { Button }, -} satisfies Meta; - -export default meta; -``` \ No newline at end of file diff --git a/docs/snippets/common/subcomponents-in-meta.ts.mdx b/docs/snippets/common/subcomponents-in-meta.ts.mdx deleted file mode 100644 index 8847609e9fac..000000000000 --- a/docs/snippets/common/subcomponents-in-meta.ts.mdx +++ /dev/null @@ -1,15 +0,0 @@ -```ts -// ButtonGroup.stories.ts|tsx - -// Replace your-framework with the name of your framework -import type { Meta } from '@storybook/your-framework'; - -import { Button, ButtonGroup } from './ButtonGroup'; - -const meta: Meta = { - component: ButtonGroup, - subcomponents: { Button }, -}; - -export default meta; -``` \ No newline at end of file diff --git a/docs/writing-docs/autodocs.md b/docs/writing-docs/autodocs.md index 9ea752168c12..a89dd0a51d2f 100644 --- a/docs/writing-docs/autodocs.md +++ b/docs/writing-docs/autodocs.md @@ -193,14 +193,21 @@ Autodocs allows you to document your "main" component, defined by the `component -![Subcomponents in ArgTypes doc block](./doc-block-arg-types-subcomponents.png) +![Subcomponents in ArgTypes doc block](../writing-stories/doc-block-arg-types-subcomponents-for-list.png) The main component and its subcomponents will show up in a tabbed version of the [`ArgTypes` doc block](./doc-blocks.md#argtypes). The tab titles will correspond to the keys of the `subcomponents` object. diff --git a/docs/writing-docs/doc-block-arg-types-subcomponents.png b/docs/writing-docs/doc-block-arg-types-subcomponents.png deleted file mode 100644 index bd883288f6f154c547b35ce94b3a972a4494ba5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10007 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 From de25f2e937e45e3a3efcfd4a94495f893d16b4cd Mon Sep 17 00:00:00 2001 From: Kyle Gach Date: Tue, 30 Jan 2024 10:14:55 -0700 Subject: [PATCH 11/20] Clarify subcomponents limitations --- docs/writing-stories/stories-for-multiple-components.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/writing-stories/stories-for-multiple-components.md b/docs/writing-stories/stories-for-multiple-components.md index f03ec9a3c8e0..708ccce28787 100644 --- a/docs/writing-stories/stories-for-multiple-components.md +++ b/docs/writing-stories/stories-for-multiple-components.md @@ -26,10 +26,10 @@ Note that by adding a `subcomponents` property to the default export, we get an ![Subcomponents in ArgTypes doc block](./doc-block-arg-types-subcomponents-for-list.png) -The downside of the approach used above, where each story creates its own combination of components, is that it does not take advantage of Storybook [Args](../writing-stories/args.md) meaning: +Subcomponents are only intended for documentation purposes and have some limitations: -1. You cannot change the stories via the controls panel -2. There is no [args reuse](../writing-stories/index.md#using-args) possible, which makes the stories harder to maintain. +1. The [argTypes](../api/arg-types.md) of subcomponents are [inferred (for the renderers that support that feature)](../api/arg-types.md#automatic-argtype-inference) and cannot be manually defined or overridden. +2. The table for each documented subcomponent does _not_ include [controls](../essentials/controls.md) to change the value of the props, because controls always apply to the main component's args. Let's talk about some techniques you can use to mitigate the above, which are especially useful in more complicated situations. From a96d34843e2b34c69444a409a09fd6ad61ea8bd8 Mon Sep 17 00:00:00 2001 From: Kyle Gach Date: Tue, 30 Jan 2024 10:20:01 -0700 Subject: [PATCH 12/20] Update Vue snippets --- docs/snippets/vue/list-story-with-sub-components.js.mdx | 7 +++++-- .../snippets/vue/list-story-with-sub-components.ts-4-9.mdx | 7 +++++-- docs/snippets/vue/list-story-with-sub-components.ts.mdx | 7 +++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/snippets/vue/list-story-with-sub-components.js.mdx b/docs/snippets/vue/list-story-with-sub-components.js.mdx index 0c6e082e6a92..a19b58f3b3d1 100644 --- a/docs/snippets/vue/list-story-with-sub-components.js.mdx +++ b/docs/snippets/vue/list-story-with-sub-components.js.mdx @@ -16,9 +16,12 @@ export const Empty = { }; export const OneItem = { - render: () => ({ + render: (args) => ({ components: { List, ListItem }, - template: '', + setup() { + return { args } + } + template: '', }), }; ``` diff --git a/docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx b/docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx index 7d9c073bfa83..6e99a25445df 100644 --- a/docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx +++ b/docs/snippets/vue/list-story-with-sub-components.ts-4-9.mdx @@ -21,9 +21,12 @@ export const Empty: Story = { }; export const OneItem: Story = { - render: () => ({ + render: (args) => ({ components: { List, ListItem }, - template: '', + setup() { + return { args } + } + template: '', }), }; ``` diff --git a/docs/snippets/vue/list-story-with-sub-components.ts.mdx b/docs/snippets/vue/list-story-with-sub-components.ts.mdx index b299d5350314..87ae30aed24a 100644 --- a/docs/snippets/vue/list-story-with-sub-components.ts.mdx +++ b/docs/snippets/vue/list-story-with-sub-components.ts.mdx @@ -21,9 +21,12 @@ export const Empty: Story = { }; export const OneItem: Story = { - render: () => ({ + render: (args) => ({ components: { List, ListItem }, - template: '', + setup() { + return { args } + } + template: '', }), }; ``` From d1ce421e18c5522a282834d3624a3c76f9a82ff4 Mon Sep 17 00:00:00 2001 From: jonniebigodes Date: Wed, 31 Jan 2024 12:27:55 +0000 Subject: [PATCH 13/20] address feedback --- docs/configure/typescript.md | 2 +- docs/essentials/controls.md | 12 ++++++------ .../snippets/react/storybook-main-prop-filter.ts.mdx | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/configure/typescript.md b/docs/configure/typescript.md index 61bc30d7eeb3..cbbfccd4833d 100644 --- a/docs/configure/typescript.md +++ b/docs/configure/typescript.md @@ -134,7 +134,7 @@ If you're using Vue single file components and TypeScript, you can add both [Vol ### Storybook doesn't create the required types for external packages -If you're working with a project relying on a third-party library and you're running into an issue where you notice that the required types are not being generated, preventing you from accurately documenting your components, you can adjust the `reactDocgen` configuration option in your Storybook configuration file to use `react-docgen-typescript` instead and include the required options. For example: +If your project relies on a third-party library and the expected types are not being generated, preventing you from accurately documenting your components, you can adjust the `reactDocgen` configuration option in your Storybook configuration file to use `react-docgen-typescript` instead and include the required options. For example: diff --git a/docs/essentials/controls.md b/docs/essentials/controls.md index 962009c6f96d..60c950c34d29 100644 --- a/docs/essentials/controls.md +++ b/docs/essentials/controls.md @@ -73,7 +73,7 @@ Finally, update your `.storybook/preview.ts` file to include the following confi -When you set the `component` annotation to the default export of your story file, it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component. +When you set the `component` annotation of the default export of your story file, it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component. @@ -89,9 +89,9 @@ When you set the `component` annotation to the default export of your story file -By default, Storybook will try to infer the required argTypes and associated controls for your stories based on the metadata provided by the [`@storybook/ember-cli-storybook`](https://github.com/storybookjs/ember-cli-storybook) addon. You'll need to take some additional steps to set it up properly. +By default, Storybook will try to infer the required argTypes and associated controls for your stories based on the metadata provided by the [`@storybook/ember-cli-storybook`](https://github.com/storybookjs/ember-cli-storybook) adapter. You'll need to take some additional steps to set it up properly. -Update your `ember-cli-build.js` configuration file to include the addon. +Update your `ember-cli-build.js` configuration file to include the adapter. @@ -121,7 +121,7 @@ Enabling this feature will generate a `storybook-docgen/index.json` automaticall
-When you set the `component` annotation to the default export of your story file, it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component. +When you set the `component` annotation of the default export of your story file, it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component. @@ -171,7 +171,7 @@ By default, Storybook will choose a control for each arg based on its initial va -By default, Storybook will try to infer the required argTypes and associated controls for your stories based on the component's definition and the initial value of the args. You'll need to take some additional steps to set it up properly. You can opt to generate a [`custom-elements.json`](https://github.com/webcomponents/custom-elements-json) file with [`@custom-elements-manifest/analyzer`](https://github.com/open-wc/custom-elements-manifest) if you're using the `pre-v1.0.0` version of the elements file or [`@custom-elements-manifest/analyzer`](https://github.com/open-wc/custom-elements-manifest) for newer versions and configure it in your Storybook UI configuration file (i.e., `.storybook/preview.js|ts`) to enable it. +By default, Storybook will try to infer the required argTypes and associated controls for your stories based on the component's definition and the initial value of the args. You'll need to take some additional steps to set it up properly. You can opt to generate a [`custom-elements.json`](https://github.com/webcomponents/custom-elements-json) file with [`@custom-elements-manifest/analyzer`](https://github.com/open-wc/custom-elements-manifest) if you're using the `pre-v1.0.0` version of the elements file or [`@custom-elements-manifest/analyzer`](https://github.com/open-wc/custom-elements-manifest/tree/master/packages/analyzer) for newer versions and configure it in your Storybook UI configuration file (i.e., `.storybook/preview.js|ts`) to enable it. @@ -185,7 +185,7 @@ By default, Storybook will try to infer the required argTypes and associated con -When you set the `component` annotation to the default export of your story file, it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component. +When you set the `component` annotation of the default export of your story file, it will be used to infer the controls and auto-generate the matching [`argTypes`](../api/arg-types.md) for your component. diff --git a/docs/snippets/react/storybook-main-prop-filter.ts.mdx b/docs/snippets/react/storybook-main-prop-filter.ts.mdx index 7d4f2763ac7e..4dd6b9d649e5 100644 --- a/docs/snippets/react/storybook-main-prop-filter.ts.mdx +++ b/docs/snippets/react/storybook-main-prop-filter.ts.mdx @@ -14,7 +14,9 @@ const config: StorybookConfig = { allowSyntheticDefaultImports: false, esModuleInterop: false, }, - propFilter: () => true, + // Filter out third-party props from node_modules except @mui packages. + propFilter: (prop) => + prop.parent ? !/node_modules\/(?!@mui)/.test(prop.parent.fileName) : true, }, }, }; From 66010a21046588edaf11a4e47de496aa5385aac5 Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Wed, 31 Jan 2024 14:24:05 +0100 Subject: [PATCH 14/20] Add documentation to getCoercedStorybookVersion func --- code/lib/core-common/src/utils/cli.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/lib/core-common/src/utils/cli.ts b/code/lib/core-common/src/utils/cli.ts index 0dd8eae5277d..c4103bd59137 100644 --- a/code/lib/core-common/src/utils/cli.ts +++ b/code/lib/core-common/src/utils/cli.ts @@ -13,6 +13,12 @@ export function parseList(str: string): string[] { .filter((item) => item.length > 0); } +/** + * Given a package manager, returns the coerced version of Storybook. + * It tries to find renderer packages in the project and returns the coerced version of the first one found. + * Example: + * If @storybook/react version 8.0.0-alpha.14 is installed, it returns the coerced version 8.0.0 + */ export async function getCoercedStorybookVersion(packageManager: JsPackageManager) { const packages = ( await Promise.all( From 5c368f2e8341909971da4108399035c0e6a16065 Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Wed, 31 Jan 2024 14:59:55 +0100 Subject: [PATCH 15/20] Refactor package version retrieval in JsPackageManager --- .../core-common/src/js-package-manager/JsPackageManager.ts | 5 ++++- code/lib/core-common/src/js-package-manager/NPMProxy.ts | 6 ------ code/lib/core-common/src/js-package-manager/PNPMProxy.ts | 7 ------- code/lib/core-common/src/js-package-manager/Yarn1Proxy.ts | 6 ------ code/lib/core-common/src/js-package-manager/Yarn2Proxy.ts | 6 ------ 5 files changed, 4 insertions(+), 26 deletions(-) diff --git a/code/lib/core-common/src/js-package-manager/JsPackageManager.ts b/code/lib/core-common/src/js-package-manager/JsPackageManager.ts index 79dfe4a5fb29..923a06409968 100644 --- a/code/lib/core-common/src/js-package-manager/JsPackageManager.ts +++ b/code/lib/core-common/src/js-package-manager/JsPackageManager.ts @@ -55,7 +55,10 @@ export abstract class JsPackageManager { basePath?: string ): Promise; - public abstract getPackageVersion(packageName: string, basePath?: string): Promise; + async getPackageVersion(packageName: string, basePath = this.cwd): Promise { + const packageJSON = await this.getPackageJSON(packageName, basePath); + return packageJSON ? packageJSON.version ?? null : null; + } // NOTE: for some reason yarn prefers the npm registry in // local development, so always use npm diff --git a/code/lib/core-common/src/js-package-manager/NPMProxy.ts b/code/lib/core-common/src/js-package-manager/NPMProxy.ts index 6e4e2939fca1..62d8be2fec5c 100644 --- a/code/lib/core-common/src/js-package-manager/NPMProxy.ts +++ b/code/lib/core-common/src/js-package-manager/NPMProxy.ts @@ -4,7 +4,6 @@ import dedent from 'ts-dedent'; import { sync as findUpSync } from 'find-up'; import { existsSync, readFileSync } from 'fs'; import path from 'path'; -import semver from 'semver'; import { logger } from '@storybook/node-logger'; import { JsPackageManager } from './JsPackageManager'; import type { PackageJson } from './PackageJson'; @@ -102,11 +101,6 @@ export class NPMProxy extends JsPackageManager { return packageJson; } - public async getPackageVersion(packageName: string, basePath = this.cwd): Promise { - const packageJson = await this.getPackageJSON(packageName, basePath); - return packageJson ? semver.coerce(packageJson.version)?.version ?? null : null; - } - getInstallArgs(): string[] { if (!this.installArgs) { this.installArgs = []; diff --git a/code/lib/core-common/src/js-package-manager/PNPMProxy.ts b/code/lib/core-common/src/js-package-manager/PNPMProxy.ts index d6cb6c99c175..7e7f0279e226 100644 --- a/code/lib/core-common/src/js-package-manager/PNPMProxy.ts +++ b/code/lib/core-common/src/js-package-manager/PNPMProxy.ts @@ -3,7 +3,6 @@ import dedent from 'ts-dedent'; import { sync as findUpSync } from 'find-up'; import path from 'path'; import fs from 'fs'; -import semver from 'semver'; import { JsPackageManager } from './JsPackageManager'; import type { PackageJson } from './PackageJson'; import type { InstallationMetadata, PackageMetadata } from './types'; @@ -159,12 +158,6 @@ export class PNPMProxy extends JsPackageManager { return JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); } - async getPackageVersion(packageName: string, basePath = this.cwd): Promise { - const packageJSON = await this.getPackageJSON(packageName, basePath); - - return packageJSON ? semver.coerce(packageJSON.version)?.version ?? null : null; - } - protected getResolutions(packageJson: PackageJson, versions: Record) { return { overrides: { diff --git a/code/lib/core-common/src/js-package-manager/Yarn1Proxy.ts b/code/lib/core-common/src/js-package-manager/Yarn1Proxy.ts index 039a06f956cf..2018e8f8ddf4 100644 --- a/code/lib/core-common/src/js-package-manager/Yarn1Proxy.ts +++ b/code/lib/core-common/src/js-package-manager/Yarn1Proxy.ts @@ -2,7 +2,6 @@ import dedent from 'ts-dedent'; import { sync as findUpSync } from 'find-up'; import { existsSync, readFileSync } from 'fs'; import path from 'path'; -import semver from 'semver'; import { createLogStream } from '../utils/cli'; import { JsPackageManager } from './JsPackageManager'; import type { PackageJson } from './PackageJson'; @@ -82,11 +81,6 @@ export class Yarn1Proxy extends JsPackageManager { return JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as Record; } - public async getPackageVersion(packageName: string, basePath = this.cwd): Promise { - const packageJson = await this.getPackageJSON(packageName, basePath); - return packageJson ? semver.coerce(packageJson.version)?.version ?? null : null; - } - public async findInstallations(pattern: string[]) { const commandResult = await this.executeCommand({ command: 'yarn', diff --git a/code/lib/core-common/src/js-package-manager/Yarn2Proxy.ts b/code/lib/core-common/src/js-package-manager/Yarn2Proxy.ts index 3dde844cba15..4f76868d395c 100644 --- a/code/lib/core-common/src/js-package-manager/Yarn2Proxy.ts +++ b/code/lib/core-common/src/js-package-manager/Yarn2Proxy.ts @@ -4,7 +4,6 @@ import { existsSync, readFileSync } from 'fs'; import path from 'path'; import { PosixFS, VirtualFS, ZipOpenFS } from '@yarnpkg/fslib'; import { getLibzipSync } from '@yarnpkg/libzip'; -import semver from 'semver'; import { createLogStream } from '../utils/cli'; import { JsPackageManager } from './JsPackageManager'; import type { PackageJson } from './PackageJson'; @@ -174,11 +173,6 @@ export class Yarn2Proxy extends JsPackageManager { return packageJson; } - async getPackageVersion(packageName: string, basePath = this.cwd): Promise { - const packageJSON = await this.getPackageJSON(packageName, basePath); - return packageJSON ? semver.coerce(packageJSON.version)?.version ?? null : null; - } - protected getResolutions(packageJson: PackageJson, versions: Record) { return { resolutions: { From f70a6b955d492056bb592e9baa0b8a1f0bb4af8e Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 31 Jan 2024 16:16:16 +0100 Subject: [PATCH 16/20] Fix vitest patch --- .../@vitest-expect-npm-1.1.3-2062bf533f.patch | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/code/.yarn/patches/@vitest-expect-npm-1.1.3-2062bf533f.patch b/code/.yarn/patches/@vitest-expect-npm-1.1.3-2062bf533f.patch index ea5e834a06df..9a1b74e203bd 100644 --- a/code/.yarn/patches/@vitest-expect-npm-1.1.3-2062bf533f.patch +++ b/code/.yarn/patches/@vitest-expect-npm-1.1.3-2062bf533f.patch @@ -1,10 +1,10 @@ diff --git a/dist/index.js b/dist/index.js -index 974d6b26f626024fc9904908100c9ecaa54f43e1..5be2d35267e7f0525c6588758dbebe72599f88a9 100644 +index 974d6b26f626024fc9904908100c9ecaa54f43e1..5d9d92a0796e02630ccdd1174d4fd25e016d2b06 100644 --- a/dist/index.js +++ b/dist/index.js -@@ -6,31 +6,37 @@ import { processError } from '@vitest/utils/error'; +@@ -6,28 +6,35 @@ import { processError } from '@vitest/utils/error'; import { util } from 'chai'; - + const MATCHERS_OBJECT = Symbol.for("matchers-object"); -const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object"); +// Patched this symbol for storybook, so that @storybook/test can be used in a jest environment as well. @@ -12,17 +12,14 @@ index 974d6b26f626024fc9904908100c9ecaa54f43e1..5be2d35267e7f0525c6588758dbebe72 +const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object-storybook"); const GLOBAL_EXPECT = Symbol.for("expect-global"); const ASYMMETRIC_MATCHERS_OBJECT = Symbol.for("asymmetric-matchers-object"); - + if (!Object.prototype.hasOwnProperty.call(globalThis, MATCHERS_OBJECT)) { const globalState = /* @__PURE__ */ new WeakMap(); - const matchers = /* @__PURE__ */ Object.create(null); - const assymetricMatchers = /* @__PURE__ */ Object.create(null); +- const assymetricMatchers = /* @__PURE__ */ Object.create(null); Object.defineProperty(globalThis, MATCHERS_OBJECT, { get: () => globalState }); -+ Object.defineProperty(globalThis, ASYMMETRIC_MATCHERS_OBJECT, { -+ get: () => assymetricMatchers -+ }); +} +if (!Object.prototype.hasOwnProperty.call(globalThis, JEST_MATCHERS_OBJECT)) { + const matchers = /* @__PURE__ */ Object.create(null); @@ -34,15 +31,14 @@ index 974d6b26f626024fc9904908100c9ecaa54f43e1..5be2d35267e7f0525c6588758dbebe72 matchers }) }); -- Object.defineProperty(globalThis, ASYMMETRIC_MATCHERS_OBJECT, { -- get: () => assymetricMatchers -- }); ++} ++if (!Object.prototype.hasOwnProperty.call(globalThis, ASYMMETRIC_MATCHERS_OBJECT)) { ++ const assymetricMatchers = /* @__PURE__ */ Object.create(null); + Object.defineProperty(globalThis, ASYMMETRIC_MATCHERS_OBJECT, { + get: () => assymetricMatchers + }); } + function getState(expect) { return globalThis[MATCHERS_OBJECT].get(expect); } -+ - function setState(state, expect) { - const map = globalThis[MATCHERS_OBJECT]; - const current = map.get(expect) || {}; From 8f52eac95be2a4104e5d291c9c87a6f26d198741 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 31 Jan 2024 16:18:18 +0100 Subject: [PATCH 17/20] Fix yarn.lock --- code/yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/yarn.lock b/code/yarn.lock index 7ba452bc433f..e0901c716f38 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -8479,12 +8479,12 @@ __metadata: "@vitest/expect@patch:@vitest/expect@npm%3A1.1.3#~/.yarn/patches/@vitest-expect-npm-1.1.3-2062bf533f.patch": version: 1.1.3 - resolution: "@vitest/expect@patch:@vitest/expect@npm%3A1.1.3#~/.yarn/patches/@vitest-expect-npm-1.1.3-2062bf533f.patch::version=1.1.3&hash=5d51c9" + resolution: "@vitest/expect@patch:@vitest/expect@npm%3A1.1.3#~/.yarn/patches/@vitest-expect-npm-1.1.3-2062bf533f.patch::version=1.1.3&hash=8fb073" dependencies: "@vitest/spy": "npm:1.1.3" "@vitest/utils": "npm:1.1.3" chai: "npm:^4.3.10" - checksum: 426287f864f58b05b1c4689bc87b4ef2ca7b3316a22e8e42d94ee9c125cbc0caf294618c9a1201a8ddf8ab68ce1ab194d1e34589f7d608906a3dc679074cfe22 + checksum: c3bbcae82050b7e92438c85e679ef2cb09162dc5638a10b3f0b5a8fc5600dfb0be578a244d84012ae2f1715748189393ac0fc72b891efff3503338221795ebe5 languageName: node linkType: hard From 08800fe63d3af33efd0b1fb9a704b8d879f24481 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 31 Jan 2024 16:36:33 +0100 Subject: [PATCH 18/20] Upgrade testing-library/jest-dom --- code/lib/test/package.json | 2 +- code/lib/test/src/expect.ts | 3 ++- code/yarn.lock | 51 +++++++++++++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/code/lib/test/package.json b/code/lib/test/package.json index f49a54ad4b89..ef71e012cd78 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -48,7 +48,7 @@ "@storybook/instrumenter": "workspace:*", "@storybook/preview-api": "workspace:*", "@testing-library/dom": "^9.3.1", - "@testing-library/jest-dom": "^6.1.3", + "@testing-library/jest-dom": "^6.4.0", "@testing-library/user-event": "14.3.0", "@vitest/expect": "1.1.3", "@vitest/spy": "^1.1.3", diff --git a/code/lib/test/src/expect.ts b/code/lib/test/src/expect.ts index 7e8b9d95cf03..da17eb52ff59 100644 --- a/code/lib/test/src/expect.ts +++ b/code/lib/test/src/expect.ts @@ -16,9 +16,10 @@ import { } from '@vitest/expect'; import * as matchers from '@testing-library/jest-dom/matchers'; import type { PromisifyObject } from './utils'; +import type { TestingLibraryMatchers } from '@testing-library/jest-dom/types/matchers'; type Matchers = PromisifyObject> & - matchers.TestingLibraryMatchers, Promise>; + TestingLibraryMatchers, Promise>; // We only expose the jest compatible API for now export interface Assertion extends Matchers { diff --git a/code/yarn.lock b/code/yarn.lock index e0901c716f38..02847b06a441 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -31,6 +31,13 @@ __metadata: languageName: node linkType: hard +"@adobe/css-tools@npm:^4.3.2": + version: 4.3.3 + resolution: "@adobe/css-tools@npm:4.3.3" + checksum: e76e712df713964b87cdf2aca1f0477f19bebd845484d5fcba726d3ec7782366e2f26ec8cb2dcfaf47081a5c891987d8a9f5c3f30d11e1eb3c1848adc27fcb24 + languageName: node + linkType: hard + "@ampproject/remapping@npm:2.2.1, @ampproject/remapping@npm:^2.2.0, @ampproject/remapping@npm:^2.2.1": version: 2.2.1 resolution: "@ampproject/remapping@npm:2.2.1" @@ -6663,7 +6670,7 @@ __metadata: "@storybook/instrumenter": "workspace:*" "@storybook/preview-api": "workspace:*" "@testing-library/dom": "npm:^9.3.1" - "@testing-library/jest-dom": "npm:^6.1.3" + "@testing-library/jest-dom": "npm:^6.4.0" "@testing-library/user-event": "npm:14.3.0" "@vitest/expect": "npm:1.1.3" "@vitest/spy": "npm:^1.1.3" @@ -6925,7 +6932,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/jest-dom@npm:^6.1.3, @testing-library/jest-dom@npm:^6.1.4": +"@testing-library/jest-dom@npm:^6.1.4": version: 6.1.5 resolution: "@testing-library/jest-dom@npm:6.1.5" dependencies: @@ -6955,6 +6962,39 @@ __metadata: languageName: node linkType: hard +"@testing-library/jest-dom@npm:^6.4.0": + version: 6.4.0 + resolution: "@testing-library/jest-dom@npm:6.4.0" + dependencies: + "@adobe/css-tools": "npm:^4.3.2" + "@babel/runtime": "npm:^7.9.2" + aria-query: "npm:^5.0.0" + chalk: "npm:^3.0.0" + css.escape: "npm:^1.5.1" + dom-accessibility-api: "npm:^0.6.3" + lodash: "npm:^4.17.15" + redent: "npm:^3.0.0" + peerDependencies: + "@jest/globals": ">= 28" + "@types/bun": "*" + "@types/jest": ">= 28" + jest: ">= 28" + vitest: ">= 0.32" + peerDependenciesMeta: + "@jest/globals": + optional: true + "@types/bun": + optional: true + "@types/jest": + optional: true + jest: + optional: true + vitest: + optional: true + checksum: 6b7eba9ca388986a721fb12f84adf0f5534bf7ec5851982023a889c4a0afac6e9e91291bdac39e1f59a05adefd7727e30463d98b21c3da32fbfec229ccb11ef1 + languageName: node + linkType: hard + "@testing-library/react@npm:^11.2.2": version: 11.2.7 resolution: "@testing-library/react@npm:11.2.7" @@ -12993,6 +13033,13 @@ __metadata: languageName: node linkType: hard +"dom-accessibility-api@npm:^0.6.3": + version: 0.6.3 + resolution: "dom-accessibility-api@npm:0.6.3" + checksum: 10bee5aa514b2a9a37c87cd81268db607a2e933a050074abc2f6fa3da9080ebed206a320cbc123567f2c3087d22292853bdfdceaffdd4334ffe2af9510b29360 + languageName: node + linkType: hard + "dom-converter@npm:^0.2.0": version: 0.2.0 resolution: "dom-converter@npm:0.2.0" From 0f3d22c79bcd28e6946a07ae500a543efa12333d Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 31 Jan 2024 16:46:01 +0100 Subject: [PATCH 19/20] Add a test for using storybook/test in vitest --- code/lib/test/src/index.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 code/lib/test/src/index.test.ts diff --git a/code/lib/test/src/index.test.ts b/code/lib/test/src/index.test.ts new file mode 100644 index 000000000000..bed58592c1d6 --- /dev/null +++ b/code/lib/test/src/index.test.ts @@ -0,0 +1,8 @@ +import { it } from 'vitest'; +import { expect, fn } from '@storybook/test'; + +it('storybook expect and fn can be used in vitest test', () => { + const spy = fn(); + spy(1); + expect(spy).toHaveBeenCalledWith(1); +}); From 32327d305f17721929efe91e672f02e982b4ae97 Mon Sep 17 00:00:00 2001 From: jonniebigodes Date: Wed, 31 Jan 2024 19:52:00 +0000 Subject: [PATCH 20/20] Docs: Addon theme cleanup --- code/addons/themes/docs/getting-started/bootstrap.md | 2 -- code/addons/themes/docs/getting-started/emotion.md | 2 -- code/addons/themes/docs/getting-started/material-ui.md | 2 -- code/addons/themes/docs/getting-started/styled-components.md | 2 -- code/addons/themes/docs/getting-started/tailwind.md | 2 -- 5 files changed, 10 deletions(-) diff --git a/code/addons/themes/docs/getting-started/bootstrap.md b/code/addons/themes/docs/getting-started/bootstrap.md index fd0a59d6fdce..41673332bba5 100644 --- a/code/addons/themes/docs/getting-started/bootstrap.md +++ b/code/addons/themes/docs/getting-started/bootstrap.md @@ -2,8 +2,6 @@ ## πŸ“¦ Install addon - - To get started, **install the package** as a dev dependency. yarn: diff --git a/code/addons/themes/docs/getting-started/emotion.md b/code/addons/themes/docs/getting-started/emotion.md index 1671b93b3583..7c44c20fc3d1 100644 --- a/code/addons/themes/docs/getting-started/emotion.md +++ b/code/addons/themes/docs/getting-started/emotion.md @@ -2,8 +2,6 @@ ## πŸ“¦ Install addon - - To get started, **install the package** as a dev dependency. yarn: diff --git a/code/addons/themes/docs/getting-started/material-ui.md b/code/addons/themes/docs/getting-started/material-ui.md index 1b88fae1451a..3c6209205161 100644 --- a/code/addons/themes/docs/getting-started/material-ui.md +++ b/code/addons/themes/docs/getting-started/material-ui.md @@ -2,8 +2,6 @@ ## πŸ“¦ Install addon - - To get started, **install the package** as a dev dependency. yarn: diff --git a/code/addons/themes/docs/getting-started/styled-components.md b/code/addons/themes/docs/getting-started/styled-components.md index e5e31361f121..d844dfe4af3b 100644 --- a/code/addons/themes/docs/getting-started/styled-components.md +++ b/code/addons/themes/docs/getting-started/styled-components.md @@ -2,8 +2,6 @@ ## πŸ“¦ Install addon - - To get started, **install the package** as a dev dependency. yarn: diff --git a/code/addons/themes/docs/getting-started/tailwind.md b/code/addons/themes/docs/getting-started/tailwind.md index c5475c621550..e4b95a823e52 100644 --- a/code/addons/themes/docs/getting-started/tailwind.md +++ b/code/addons/themes/docs/getting-started/tailwind.md @@ -2,8 +2,6 @@ ## πŸ“¦ Install addon - - To get started, **install the package** as a dev dependency. yarn: