diff --git a/.changeset/pink-feet-trade.md b/.changeset/pink-feet-trade.md new file mode 100644 index 000000000..d63683ebd --- /dev/null +++ b/.changeset/pink-feet-trade.md @@ -0,0 +1,11 @@ +--- +'sku': minor +--- + +Adds support for Storybook configuration via the `.storybook` directory + +sku now supports the standard `.storybook` configuration directory, as documented in [Storybook's configuration documentation]. +Please read [sku's storybook documentation][sku storybook docs] for more info. + +[Storybook configuration documentation]: https://storybook.js.org/docs/react/configure/overview +[sku storybook docs]: https://seek-oss.github.io/sku/#/./docs/storybook diff --git a/.changeset/real-rabbits-yawn.md b/.changeset/real-rabbits-yawn.md new file mode 100644 index 000000000..f05d82128 --- /dev/null +++ b/.changeset/real-rabbits-yawn.md @@ -0,0 +1,13 @@ +--- +'sku': minor +--- + +Drop support for running `devServerMiddleware` alongside `sku storybook` + +Now that sku supports Storybook configuration via the `.storybook` directory, this feature is unnecessary. +Storybook middleware can be configured by creating a `middleware.js` file in the `.storybook` directory. +See [the sku docs][sku storybook middleware] for more info. + +**NOTE**: While this is technically a breaking change, it does not affect app builds, therefore it has been downgraded to a `minor` release. + +[sku storybook middleware]: https://seek-oss.github.io/sku/#/./docs/storybook?id=devserver-middleware diff --git a/.changeset/thick-cameras-arrive.md b/.changeset/thick-cameras-arrive.md new file mode 100644 index 000000000..0e0726122 --- /dev/null +++ b/.changeset/thick-cameras-arrive.md @@ -0,0 +1,5 @@ +--- +'sku': patch +--- + +Disable Storybook telemetry diff --git a/docs/docs/storybook.md b/docs/docs/storybook.md index 28d198cc6..353af6f59 100644 --- a/docs/docs/storybook.md +++ b/docs/docs/storybook.md @@ -21,6 +21,35 @@ export const Secondary = () => ; _**NOTE:** To access the Storybook API, you should import from `sku/@storybook/...`, since your project isn't depending on Storybook packages directly._ +## Configuration + +Storybook can be configured by creating specially-named files inside the `.storybook` folder of your app. +Take a look at the [Storybook configuration docs] for all the ways to customize your Storybook. + +_**NOTE:** sku maintains control of the `main.js` configuration file as it is critical to ensuring compatibility between Storybook and your app. +If you have a valid use case for customizing this file, please reach out in [`#sku-support`]._ + +[Storybook configuration docs]: https://storybook.js.org/docs/react/configure/overview +[`#sku-support`]: https://seekchat.slack.com/channels/sku-support + +### Addons + +There are no storybook addons configured by default in sku but they can be added through the `storybookAddons` option in `sku.config.ts`. + +For example, if you want to use `@storybook/addon-essentials`, first install the addon. + +```bash +yarn add --dev @storybook/addon-essentials +``` + +Then add it to your `sku.config.ts`. + +```ts +export default { + storybookAddons: ['@storybook/addon-essentials'], +} satisfies SkuConfig; +``` + ### Story Rendering Story rendering can be customized globally by creating a `.storybook/preview.js` (or `.ts`, or `.tsx`) file. @@ -53,7 +82,14 @@ See [the Storybook docs][storybook preview.js] for more info. ### DevServer Middleware -When running `sku storybook`, if you have configured [`devServerMiddleware`][devserver middleware] in your sku config, that middleware will be passed through to storybook and injected into its own middleware stack. +When running `sku storybook`, if you want to run your [`devServerMiddleware`][devserver middleware] at the same time, add a `middleware.js` file to the `.storybook` folder and export it: + +```js +// .storybook/middleware.js +import devServerMiddleware from '../devServerMiddleware.js'; + +export default devServerMiddleware; +``` [devserver middleware]: ./docs/extra-features.md#devserver-middleware @@ -68,24 +104,6 @@ export default { } satisfies SkuConfig; ``` -## Addons - -There are no storybook addons configured by default in sku but they can be added through the `storybookAddons` option in `sku.config.ts`. - -For example, if you want to use `@storybook/addon-essentials`, first install the addon. - -```bash -yarn add --dev @storybook/addon-essentials -``` - -Then add it to your `sku.config.ts`. - -```ts -export default { - storybookAddons: ['@storybook/addon-essentials'], -} satisfies SkuConfig; -``` - ## Build Storybook To build your Storybook, first add the following npm script: diff --git a/fixtures/assertion-removal/.eslintignore b/fixtures/assertion-removal/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/assertion-removal/.eslintignore +++ b/fixtures/assertion-removal/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/assertion-removal/.gitignore b/fixtures/assertion-removal/.gitignore index 9472e0ebe..d2e00244e 100644 --- a/fixtures/assertion-removal/.gitignore +++ b/fixtures/assertion-removal/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/assertion-removal/.prettierignore b/fixtures/assertion-removal/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/assertion-removal/.prettierignore +++ b/fixtures/assertion-removal/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/braid-design-system/.eslintignore b/fixtures/braid-design-system/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/braid-design-system/.eslintignore +++ b/fixtures/braid-design-system/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/braid-design-system/.gitignore b/fixtures/braid-design-system/.gitignore index 9472e0ebe..d2e00244e 100644 --- a/fixtures/braid-design-system/.gitignore +++ b/fixtures/braid-design-system/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/braid-design-system/.prettierignore b/fixtures/braid-design-system/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/braid-design-system/.prettierignore +++ b/fixtures/braid-design-system/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/custom-src-paths/.eslintignore b/fixtures/custom-src-paths/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/custom-src-paths/.eslintignore +++ b/fixtures/custom-src-paths/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/custom-src-paths/.gitignore b/fixtures/custom-src-paths/.gitignore index 9472e0ebe..d2e00244e 100644 --- a/fixtures/custom-src-paths/.gitignore +++ b/fixtures/custom-src-paths/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/custom-src-paths/.prettierignore b/fixtures/custom-src-paths/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/custom-src-paths/.prettierignore +++ b/fixtures/custom-src-paths/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/library-build/.eslintignore b/fixtures/library-build/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/library-build/.eslintignore +++ b/fixtures/library-build/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/library-build/.gitignore b/fixtures/library-build/.gitignore index 9472e0ebe..d2e00244e 100644 --- a/fixtures/library-build/.gitignore +++ b/fixtures/library-build/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/library-build/.prettierignore b/fixtures/library-build/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/library-build/.prettierignore +++ b/fixtures/library-build/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/library-file/.eslintignore b/fixtures/library-file/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/library-file/.eslintignore +++ b/fixtures/library-file/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/library-file/.gitignore b/fixtures/library-file/.gitignore index 9472e0ebe..d2e00244e 100644 --- a/fixtures/library-file/.gitignore +++ b/fixtures/library-file/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/library-file/.prettierignore b/fixtures/library-file/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/library-file/.prettierignore +++ b/fixtures/library-file/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/lint-format/.eslintignore b/fixtures/lint-format/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/lint-format/.eslintignore +++ b/fixtures/lint-format/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/lint-format/.gitignore b/fixtures/lint-format/.gitignore index e603e2924..4f42a791f 100644 --- a/fixtures/lint-format/.gitignore +++ b/fixtures/lint-format/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/lint-format/.prettierignore b/fixtures/lint-format/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/lint-format/.prettierignore +++ b/fixtures/lint-format/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/multiple-routes/.eslintignore b/fixtures/multiple-routes/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/multiple-routes/.eslintignore +++ b/fixtures/multiple-routes/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/multiple-routes/.gitignore b/fixtures/multiple-routes/.gitignore index 9472e0ebe..d2e00244e 100644 --- a/fixtures/multiple-routes/.gitignore +++ b/fixtures/multiple-routes/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/multiple-routes/.prettierignore b/fixtures/multiple-routes/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/multiple-routes/.prettierignore +++ b/fixtures/multiple-routes/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/public-path/.eslintignore b/fixtures/public-path/.eslintignore index 58df60132..1c8778aba 100644 --- a/fixtures/public-path/.eslintignore +++ b/fixtures/public-path/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/static/ diff --git a/fixtures/public-path/.gitignore b/fixtures/public-path/.gitignore index 987acfe8f..f10987025 100644 --- a/fixtures/public-path/.gitignore +++ b/fixtures/public-path/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/static/ diff --git a/fixtures/public-path/.prettierignore b/fixtures/public-path/.prettierignore index 58df60132..1c8778aba 100644 --- a/fixtures/public-path/.prettierignore +++ b/fixtures/public-path/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/static/ diff --git a/fixtures/react-css-modules/.eslintignore b/fixtures/react-css-modules/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/react-css-modules/.eslintignore +++ b/fixtures/react-css-modules/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/react-css-modules/.gitignore b/fixtures/react-css-modules/.gitignore index 9472e0ebe..d2e00244e 100644 --- a/fixtures/react-css-modules/.gitignore +++ b/fixtures/react-css-modules/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/react-css-modules/.prettierignore b/fixtures/react-css-modules/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/react-css-modules/.prettierignore +++ b/fixtures/react-css-modules/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/sku-test/.eslintignore b/fixtures/sku-test/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/sku-test/.eslintignore +++ b/fixtures/sku-test/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/sku-test/.gitignore b/fixtures/sku-test/.gitignore index 9472e0ebe..d2e00244e 100644 --- a/fixtures/sku-test/.gitignore +++ b/fixtures/sku-test/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/sku-test/.prettierignore b/fixtures/sku-test/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/sku-test/.prettierignore +++ b/fixtures/sku-test/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/sku-with-https/.eslintignore b/fixtures/sku-with-https/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/sku-with-https/.eslintignore +++ b/fixtures/sku-with-https/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/sku-with-https/.gitignore b/fixtures/sku-with-https/.gitignore index 7bfb4a45b..f6980b14d 100644 --- a/fixtures/sku-with-https/.gitignore +++ b/fixtures/sku-with-https/.gitignore @@ -2,6 +2,7 @@ .eslintrc .prettierrc .ssl +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/sku-with-https/.prettierignore b/fixtures/sku-with-https/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/sku-with-https/.prettierignore +++ b/fixtures/sku-with-https/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/source-maps/.eslintignore b/fixtures/source-maps/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/source-maps/.eslintignore +++ b/fixtures/source-maps/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/source-maps/.gitignore b/fixtures/source-maps/.gitignore index 9472e0ebe..d2e00244e 100644 --- a/fixtures/source-maps/.gitignore +++ b/fixtures/source-maps/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/source-maps/.prettierignore b/fixtures/source-maps/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/source-maps/.prettierignore +++ b/fixtures/source-maps/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/ssr-hello-world/.eslintignore b/fixtures/ssr-hello-world/.eslintignore index e9b94e25e..bca860144 100644 --- a/fixtures/ssr-hello-world/.eslintignore +++ b/fixtures/ssr-hello-world/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-build/ dist-storybook/ diff --git a/fixtures/ssr-hello-world/.gitignore b/fixtures/ssr-hello-world/.gitignore index 2395ad75e..e646cbdd9 100644 --- a/fixtures/ssr-hello-world/.gitignore +++ b/fixtures/ssr-hello-world/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-build/ dist-storybook/ diff --git a/fixtures/ssr-hello-world/.prettierignore b/fixtures/ssr-hello-world/.prettierignore index e9b94e25e..bca860144 100644 --- a/fixtures/ssr-hello-world/.prettierignore +++ b/fixtures/ssr-hello-world/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-build/ dist-storybook/ diff --git a/fixtures/storybook-config/.eslintignore b/fixtures/storybook-config/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/storybook-config/.eslintignore +++ b/fixtures/storybook-config/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/storybook-config/.gitignore b/fixtures/storybook-config/.gitignore index 6e1650ecc..5d73a2f5c 100644 --- a/fixtures/storybook-config/.gitignore +++ b/fixtures/storybook-config/.gitignore @@ -4,6 +4,7 @@ npm-debug.log # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/storybook-config/.prettierignore b/fixtures/storybook-config/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/storybook-config/.prettierignore +++ b/fixtures/storybook-config/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/storybook-config/.storybook/middleware.js b/fixtures/storybook-config/.storybook/middleware.js new file mode 100644 index 000000000..6d7fa83d6 --- /dev/null +++ b/fixtures/storybook-config/.storybook/middleware.js @@ -0,0 +1,3 @@ +import middleware from '../dev-middleware'; + +export default middleware; diff --git a/fixtures/storybook-config/.storybook/preview.tsx b/fixtures/storybook-config/.storybook/preview.tsx index f561527bb..57fe89090 100644 --- a/fixtures/storybook-config/.storybook/preview.tsx +++ b/fixtures/storybook-config/.storybook/preview.tsx @@ -5,7 +5,7 @@ import apac from 'braid-design-system/themes/apac'; import type { Preview } from 'sku/@storybook/react'; -const preview: Preview = { +export default { decorators: [ (Story) => (
@@ -21,6 +21,4 @@ const preview: Preview = { ), ], -}; - -export default preview; +} satisfies Preview; diff --git a/fixtures/styling/.eslintignore b/fixtures/styling/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/styling/.eslintignore +++ b/fixtures/styling/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/styling/.gitignore b/fixtures/styling/.gitignore index 9472e0ebe..d2e00244e 100644 --- a/fixtures/styling/.gitignore +++ b/fixtures/styling/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/styling/.prettierignore b/fixtures/styling/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/styling/.prettierignore +++ b/fixtures/styling/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/translations/.eslintignore b/fixtures/translations/.eslintignore index b2d0a058b..70e1e3110 100644 --- a/fixtures/translations/.eslintignore +++ b/fixtures/translations/.eslintignore @@ -1,6 +1,7 @@ # managed by sku **/*.vocab/index.ts *.less.d.ts +.storybook/main.js coverage/ dist-ssr/ dist-storybook/ diff --git a/fixtures/translations/.gitignore b/fixtures/translations/.gitignore index 9aaf8c715..83ebc8152 100644 --- a/fixtures/translations/.gitignore +++ b/fixtures/translations/.gitignore @@ -4,6 +4,7 @@ **/*.vocab/index.ts .eslintrc .prettierrc +.storybook/main.js coverage/ dist-ssr/ dist-storybook/ diff --git a/fixtures/translations/.prettierignore b/fixtures/translations/.prettierignore index 5121f98f6..ba10121aa 100644 --- a/fixtures/translations/.prettierignore +++ b/fixtures/translations/.prettierignore @@ -3,6 +3,7 @@ translations.ts # managed by sku **/*.vocab/index.ts *.less.d.ts +.storybook/main.js coverage/ dist-ssr/ dist-storybook/ diff --git a/fixtures/typescript-css-modules/.eslintignore b/fixtures/typescript-css-modules/.eslintignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/typescript-css-modules/.eslintignore +++ b/fixtures/typescript-css-modules/.eslintignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/typescript-css-modules/.gitignore b/fixtures/typescript-css-modules/.gitignore index 9472e0ebe..d2e00244e 100644 --- a/fixtures/typescript-css-modules/.gitignore +++ b/fixtures/typescript-css-modules/.gitignore @@ -1,6 +1,7 @@ # managed by sku .eslintrc .prettierrc +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/fixtures/typescript-css-modules/.prettierignore b/fixtures/typescript-css-modules/.prettierignore index be5af46ed..a8fee4a3e 100644 --- a/fixtures/typescript-css-modules/.prettierignore +++ b/fixtures/typescript-css-modules/.prettierignore @@ -1,5 +1,6 @@ # managed by sku *.less.d.ts +.storybook/main.js coverage/ dist-storybook/ dist/ diff --git a/packages/sku/config/storybook/build/main.js b/packages/sku/config/storybook/build/main.js deleted file mode 100644 index 5686f9864..000000000 --- a/packages/sku/config/storybook/build/main.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../config'); diff --git a/packages/sku/config/storybook/build/webpack.config.js b/packages/sku/config/storybook/build/webpack.config.js deleted file mode 100644 index f150312fa..000000000 --- a/packages/sku/config/storybook/build/webpack.config.js +++ /dev/null @@ -1,4 +0,0 @@ -const storybookWebpackConfig = require('../storybookWebpackConfig'); - -module.exports = (storybookConfig) => - storybookWebpackConfig(storybookConfig, { isDevServer: false }); diff --git a/packages/sku/config/storybook/config.js b/packages/sku/config/storybook/config.js deleted file mode 100644 index c060dc4e4..000000000 --- a/packages/sku/config/storybook/config.js +++ /dev/null @@ -1,45 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const { - paths, - storybookAddons, - storybookStoryStore, -} = require('../../context'); - -/** @type {import("@storybook/react-webpack5").StorybookConfig} */ -module.exports = { - stories: paths.src - .filter((srcPath) => fs.statSync(srcPath).isDirectory()) - .map((srcPath) => path.join(srcPath, '**/*.stories.@(js|ts|tsx)')), - addons: storybookAddons, - framework: { - name: '@storybook/react-webpack5', - options: {}, - }, - core: { - builder: { - name: '@storybook/builder-webpack5', - options: { - fsCache: true, - }, - }, - }, - features: { - storyStoreV7: storybookStoryStore, - }, - babel: (config) => ({ - ...config, - presets: [ - ...config.presets, - [ - require.resolve('@babel/preset-env'), - { - targets: { - chrome: 100, - }, - }, - ], - require.resolve('@babel/preset-typescript'), - ], - }), -}; diff --git a/packages/sku/config/storybook/index.js b/packages/sku/config/storybook/index.js new file mode 100644 index 000000000..b5a277560 --- /dev/null +++ b/packages/sku/config/storybook/index.js @@ -0,0 +1,75 @@ +/** + * This file and all its dependencies must be CJS + * https://github.com/storybookjs/storybook/pull/23018 + */ + +const fs = require('fs'); +const path = require('path'); +const { + paths, + storybookAddons, + storybookStoryStore, +} = require('../../context'); + +const makeStorybookWebpackConfig = require('./storybookWebpackConfig'); + +/** @type {import("@storybook/react-webpack5").StorybookConfig} */ +module.exports = { + stories: paths.src + .filter((srcPath) => fs.statSync(srcPath).isDirectory()) + .map((srcPath) => path.join(srcPath, '**/*.stories.@(js|ts|tsx)')), + addons: storybookAddons, + framework: { + // Storybook looks for a `/preset` entrypoint on the framework package, + // so we give it the dirname of the resolved path to package.json + // https://github.com/storybookjs/storybook/blob/aecfa1791f982bef6a06b51d20df3e31dd82b5b4/code/lib/core-common/src/utils/validate-config.ts#L34 + name: path.dirname( + require.resolve('@storybook/react-webpack5/package.json'), + ), + options: {}, + }, + core: { + builder: { + name: require.resolve('@storybook/builder-webpack5'), + options: { + fsCache: true, + }, + }, + disableTelemetry: true, + }, + features: { + storyStoreV7: storybookStoryStore, + }, + // sku storybook -> configType === 'DEVELOPMENT' + // sku build-storybook -> configType === 'PRODUCTION' + webpackFinal: (config, { configType }) => + makeStorybookWebpackConfig(config, { + isDevServer: configType === 'DEVELOPMENT', + }), + babel: (config) => ({ + ...config, + presets: [ + // Includes `@babel/preset-react` + ...config.presets, + + // Storybook as of 7.0 no longer handles babel stuff for you (other than react) + // We need to configure TypeScript support ourselves, if we want it + // https://github.com/storybookjs/storybook/issues/22357#issuecomment-1532548058 + [ + require.resolve('@babel/preset-env'), + { + targets: { + chrome: 100, + }, + }, + ], + [ + require.resolve('@babel/preset-typescript'), + { + allExtensions: true, + isTSX: true, + }, + ], + ], + }), +}; diff --git a/packages/sku/config/storybook/start/main.js b/packages/sku/config/storybook/start/main.js deleted file mode 100644 index 5686f9864..000000000 --- a/packages/sku/config/storybook/start/main.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../config'); diff --git a/packages/sku/config/storybook/start/middleware.js b/packages/sku/config/storybook/start/middleware.js deleted file mode 100644 index c48e34d7d..000000000 --- a/packages/sku/config/storybook/start/middleware.js +++ /dev/null @@ -1,10 +0,0 @@ -const { paths, useDevServerMiddleware } = require('../../../context'); - -const dummyMiddleware = (app) => app; -let middleware = dummyMiddleware; - -if (useDevServerMiddleware) { - middleware = require(paths.devServerMiddleware); -} - -module.exports = middleware; diff --git a/packages/sku/config/storybook/start/webpack.config.js b/packages/sku/config/storybook/start/webpack.config.js deleted file mode 100644 index c26d286be..000000000 --- a/packages/sku/config/storybook/start/webpack.config.js +++ /dev/null @@ -1,4 +0,0 @@ -const storybookWebpackConfig = require('../storybookWebpackConfig'); - -module.exports = (storybookConfig) => - storybookWebpackConfig(storybookConfig, { isDevServer: true }); diff --git a/packages/sku/config/storybook/storybookWebpackConfig.js b/packages/sku/config/storybook/storybookWebpackConfig.js index 6ddf57604..b6546be4e 100644 --- a/packages/sku/config/storybook/storybookWebpackConfig.js +++ b/packages/sku/config/storybook/storybookWebpackConfig.js @@ -6,7 +6,11 @@ const { resolvePackage } = require('../webpack/utils/resolvePackage'); const hot = process.env.SKU_HOT !== 'false'; -module.exports = ({ config }, { isDevServer }) => { +/** + * @param {import("webpack").Configuration} config + * @param {{isDevServer: boolean}} + */ +module.exports = (config, { isDevServer }) => { const clientWebpackConfig = find( makeWebpackConfig({ isIntegration: true, diff --git a/packages/sku/lib/configure.js b/packages/sku/lib/configure.js index 4c0539af3..2d064e99f 100755 --- a/packages/sku/lib/configure.js +++ b/packages/sku/lib/configure.js @@ -1,4 +1,5 @@ #!/usr/bin/env node + const { writeFile, rm } = require('fs/promises'); const path = require('path'); @@ -13,12 +14,14 @@ const prettierConfig = require('../config/prettier/prettierConfig'); const eslintConfig = require('../config/eslint/eslintConfig'); const createTSConfig = require('../config/typescript/tsconfig.js'); const getCertificate = require('./certificate'); +const { storybookMainConfigPath } = require('./storybook'); +const managedConfigBanner = require('./managedConfigBanner.js'); + const coverageFolder = 'coverage'; const convertToForwardSlashPaths = (pathStr) => pathStr.replace(/\\/g, '/'); const addSep = (p) => `${p}${path.sep}`; -const prependBanner = (str) => - `/** THIS FILE IS GENERATED BY SKU, MANUAL CHANGES WILL BE DISCARDED **/\n${str}`; +const prependBanner = (str) => `${managedConfigBanner}\n${str}`; const writeFileToCWD = async (fileName, content, { banner = true } = {}) => { const outPath = getPathFromCwd(fileName); @@ -33,11 +36,13 @@ module.exports = async () => { const gitIgnorePatterns = [ addSep(bundleReportFolder), addSep(coverageFolder), + storybookMainConfigPath, ]; const lintIgnorePatterns = [ addSep(bundleReportFolder), addSep(coverageFolder), '*.less.d.ts', + storybookMainConfigPath, ]; // Ignore webpack target directories diff --git a/packages/sku/lib/managedConfigBanner.js b/packages/sku/lib/managedConfigBanner.js new file mode 100644 index 000000000..a5e8e157b --- /dev/null +++ b/packages/sku/lib/managedConfigBanner.js @@ -0,0 +1 @@ +module.exports = `/** THIS FILE IS GENERATED BY SKU, MANUAL CHANGES WILL BE DISCARDED **/`; diff --git a/packages/sku/lib/storybook.js b/packages/sku/lib/storybook.js index cdc8ac1fe..f3fe7816c 100644 --- a/packages/sku/lib/storybook.js +++ b/packages/sku/lib/storybook.js @@ -1,70 +1,35 @@ const path = require('path'); - -const { paths } = require('../context'); const fs = require('fs/promises'); const debug = require('debug'); -const glob = require('fast-glob'); const log = debug('sku:storybook'); -const previewFileName = 'preview.{js,ts,tsx}'; - -const previewFileAbsolutePath = path.join( - path.dirname(paths.appSkuConfigPath), - '.storybook', - previewFileName, -); - -/** - * This function first cleans up any existing preview.{js,ts,tsx} files in the provided storybook config directory. - * This includes any potentially dangling symlinks. - * Then it looks for a `.storybook/preview.{js,ts,tsx}` file relative to the sku config. - * If 1 file is found, a symlink pointing to it is created in the provided storybook config directory. - * Does nothing if 0 or >1 files are found. - * - * @param {string} storybookConfigDirectory The path to the storybook config directory - */ -const setUpStorybookPreviewFile = async (storybookConfigDirectory) => { - const symlinkFileAsbolutePath = path.join( - storybookConfigDirectory, - previewFileName, - ); - const symlinkFiles = await glob(symlinkFileAsbolutePath, { - dot: true, - onlyFiles: false, // Required to find dangling symlinks - }); - - // Clean up any existing files in the storybook config folder so we have a clean slate - for (const symlinkFile of symlinkFiles) { - await fs.unlink(symlinkFile); - log(`Cleaning up exising file ${symlinkFile}.`); - } +const managedConfigBanner = require('./managedConfigBanner'); - const previewFiles = await glob(previewFileAbsolutePath); +// Since this config will be in the user's project, we can use ESM +// Spread `storybookConfig` to prevent warning +// https://github.com/storybookjs/storybook/issues/23675 +const mainConfigFileContents = `${managedConfigBanner} +import storybookConfig from 'sku/config/storybook'; - if (previewFiles.length > 1) { - console.error( - 'Multiple storybook preview files found. Please only define a single preview file.', - ); - console.error(previewFiles); +export default { ...storybookConfig }; +`; - return; - } +const storybookMainConfigPath = '.storybook/main.js'; +const storybookConfigDirectory = path.dirname(storybookMainConfigPath); - const previewFile = previewFiles?.[0]; - - if (previewFile) { - const previewFileExtension = path.extname(previewFile); - const symlinkFile = path.join( +const setUpStorybookConfigDirectory = async () => { + await fs.mkdir(storybookConfigDirectory, { recursive: true }); + log( + `Created '${path.resolve( storybookConfigDirectory, - `preview${previewFileExtension}`, - ); - - log(`Found preview file at ${previewFile}`); - log(`Creating symlink from ${symlinkFile} to ${previewFile}`); + )}' directory if it didn't exist`, + ); - await fs.symlink(previewFile, symlinkFile); - } + await fs.writeFile(storybookMainConfigPath, mainConfigFileContents); + log( + `Wrote storybook config file to '${path.resolve(storybookMainConfigPath)}'`, + ); }; -module.exports = { setUpStorybookPreviewFile }; +module.exports = { setUpStorybookConfigDirectory, storybookMainConfigPath }; diff --git a/packages/sku/scripts/build-storybook.js b/packages/sku/scripts/build-storybook.js index 5952879b1..d7ccabb1a 100644 --- a/packages/sku/scripts/build-storybook.js +++ b/packages/sku/scripts/build-storybook.js @@ -1,23 +1,20 @@ // First, ensure the build is running in production mode process.env.NODE_ENV = 'production'; -const path = require('path'); const { rimraf } = require('rimraf'); const { argv, config } = require('../config/args'); const gracefulSpawn = require('../lib/gracefulSpawn'); const { storybookTarget } = require('../context'); const buildStorybookPath = require.resolve('@storybook/cli/bin/index'); -const configDir = path.resolve(__dirname, '../config/storybook/build'); const { runVocabCompile } = require('../lib/runVocab'); -const { setUpStorybookPreviewFile } = require('../lib/storybook'); +const { setUpStorybookConfigDirectory } = require('../lib/storybook'); (async () => { await runVocabCompile(); await rimraf(storybookTarget); - await setUpStorybookPreviewFile(configDir); + await setUpStorybookConfigDirectory(); argv.push('build'); - argv.push('--config-dir', configDir); argv.push('--output-dir', storybookTarget); argv.push('--quiet'); diff --git a/packages/sku/scripts/storybook.js b/packages/sku/scripts/storybook.js index c82cb7d2b..0f9783022 100644 --- a/packages/sku/scripts/storybook.js +++ b/packages/sku/scripts/storybook.js @@ -1,21 +1,18 @@ -const path = require('path'); const { argv, config } = require('../config/args'); const gracefulSpawn = require('../lib/gracefulSpawn'); const { storybookPort } = require('../context'); const startStorybookPath = require.resolve('@storybook/cli/bin/index'); -const configDir = path.resolve(__dirname, '../config/storybook/start'); const { watchVocabCompile } = require('../lib/runVocab'); -const { setUpStorybookPreviewFile } = require('../lib/storybook'); +const { setUpStorybookConfigDirectory } = require('../lib/storybook'); // Unshift args to allow pushing --ci as an arg during storybook-config tests argv.unshift('--quiet'); -argv.unshift('--config-dir', configDir); argv.unshift('--port', storybookPort); argv.unshift('dev'); (async () => { await watchVocabCompile(); - await setUpStorybookPreviewFile(configDir); + await setUpStorybookConfigDirectory(); const storybookProcess = gracefulSpawn(startStorybookPath, argv, { stdio: 'inherit', diff --git a/tests/configure.test.ts b/tests/configure.test.ts index 53b5ff3a7..12bb29fa6 100644 --- a/tests/configure.test.ts +++ b/tests/configure.test.ts @@ -77,9 +77,10 @@ describe('configure', () => { it(`should generate \`.gitignore\``, async () => { const ignoreContents = await readIgnore(appFolder, '.gitignore'); - expect(ignoreContents.length).toEqual(7); + expect(ignoreContents.length).toEqual(8); expect(ignoreContents).toContain(`.eslintrc`); expect(ignoreContents).toContain(`.prettierrc`); + expect(ignoreContents).toContain(`.storybook/main.js`); expect(ignoreContents).toContain(`${defaultTargetDir}/`); expect(ignoreContents).toContain(`${defaultStorybookTargetDir}/`); expect(ignoreContents).toContain(`${bundleReportFolder}/`); @@ -90,8 +91,9 @@ describe('configure', () => { ['.eslintignore', '.prettierignore'].forEach((ignore) => it(`should generate \`${ignore}\``, async () => { const ignoreContents = await readIgnore(appFolder, ignore); - expect(ignoreContents.length).toEqual(5); + expect(ignoreContents.length).toEqual(6); expect(ignoreContents).toContain('*.less.d.ts'); + expect(ignoreContents).toContain(`.storybook/main.js`); expect(ignoreContents).toContain(`${defaultTargetDir}/`); expect(ignoreContents).toContain(`${bundleReportFolder}/`); expect(ignoreContents).toContain(`${coverageFolder}/`); @@ -137,10 +139,11 @@ describe('configure', () => { it(`should generate \`.gitignore\``, async () => { const ignoreContents = await readIgnore(appFolderTS, '.gitignore'); - expect(ignoreContents.length).toEqual(7); + expect(ignoreContents.length).toEqual(8); expect(ignoreContents).toContain(`.eslintrc`); expect(ignoreContents).toContain(`.prettierrc`); expect(ignoreContents).toContain(`tsconfig.json`); + expect(ignoreContents).toContain(`.storybook/main.js`); expect(ignoreContents).toContain(`${skuConfig.target}/`); expect(ignoreContents).toContain(`${skuConfig.storybookTarget}/`); expect(ignoreContents).toContain(`${bundleReportFolder}/`); @@ -150,8 +153,9 @@ describe('configure', () => { ['.eslintignore', '.prettierignore'].forEach((ignore) => it(`should generate \`${ignore}\``, async () => { const ignoreContents = await readIgnore(appFolderTS, ignore); - expect(ignoreContents.length).toEqual(5); + expect(ignoreContents.length).toEqual(6); expect(ignoreContents).toContain('*.less.d.ts'); + expect(ignoreContents).toContain(`.storybook/main.js`); expect(ignoreContents).toContain(`${skuConfig.target}/`); expect(ignoreContents).toContain(`${skuConfig.storybookTarget}/`); expect(ignoreContents).toContain(`${bundleReportFolder}/`);