diff --git a/.circleci/config.yml b/.circleci/config.yml index 5082db950b20..b212c825ddc2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -43,7 +43,7 @@ executors: default: "small" working_directory: /tmp/storybook docker: - - image: mcr.microsoft.com/playwright:v1.41.1-jammy + - image: mcr.microsoft.com/playwright:v1.36.0-focal environment: NODE_OPTIONS: --max_old_space_size=6144 resource_class: <> @@ -359,19 +359,6 @@ jobs: clone_options: "--depth 1 --verbose" - attach_workspace: at: . - - run: - name: Swap node versions - command: | - set +e - wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash - export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" - nvm install v18.14.0 - nvm alias default 18.14.0 - - echo 'export NVM_DIR="$HOME/.nvm"' >> $BASH_ENV - echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV - run: name: Running Test Runner command: yarn task --task test-runner --template $(yarn get-template --cadence << pipeline.parameters.workflow >> --task test-runner) --no-link --start-from=never --junit @@ -392,19 +379,6 @@ jobs: clone_options: "--depth 1 --verbose" - attach_workspace: at: . - - run: - name: Swap node versions - command: | - set +e - wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash - export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" - nvm install v18.14.0 - nvm alias default 18.14.0 - - echo 'export NVM_DIR="$HOME/.nvm"' >> $BASH_ENV - echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV - run: name: Running Test Runner in Dev mode command: yarn task --task test-runner-dev --template $(yarn get-template --cadence << pipeline.parameters.workflow >> --task test-runner-dev) --no-link --start-from=never --junit @@ -444,19 +418,6 @@ jobs: clone_options: "--depth 1 --verbose" - attach_workspace: at: . - - run: - name: Swap node versions - command: | - set +e - wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash - export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" - nvm install v18.14.0 - nvm alias default 18.14.0 - - echo 'export NVM_DIR="$HOME/.nvm"' >> $BASH_ENV - echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV - run: name: Running E2E Tests command: yarn task --task e2e-tests --template $(yarn get-template --cadence << pipeline.parameters.workflow >> --task e2e-tests) --no-link --start-from=never --junit @@ -480,19 +441,6 @@ jobs: clone_options: "--depth 1 --verbose" - attach_workspace: at: . - - run: - name: Swap node versions - command: | - set +e - wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash - export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" - nvm install v18.14.0 - nvm alias default 18.14.0 - - echo 'export NVM_DIR="$HOME/.nvm"' >> $BASH_ENV - echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV - run: name: Running E2E Tests command: yarn task --task e2e-tests-dev --template $(yarn get-template --cadence << pipeline.parameters.workflow >> --task e2e-tests-dev) --no-link --start-from=never --junit @@ -516,19 +464,6 @@ jobs: clone_options: "--depth 1 --verbose" - attach_workspace: at: . - - run: - name: Swap node versions - command: | - set +e - wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash - export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" - nvm install v18.14.0 - nvm alias default 18.14.0 - - echo 'export NVM_DIR="$HOME/.nvm"' >> $BASH_ENV - echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV - run: name: Running Bench command: yarn task --task bench --template $(yarn get-template --cadence << pipeline.parameters.workflow >> --task bench) --no-link --start-from=never --junit diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index f6fd32e1f285..b3cf463bf917 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,15 @@ +## 8.0.0-beta.1 + +- Addon-docs: Fix MDX components not applied in Vite and theme loading twice - [#25925](https://github.com/storybookjs/storybook/pull/25925), thanks [@JReinhold](https://github.com/JReinhold)! +- Core: Fix React peer dependency warnings - [#25926](https://github.com/storybookjs/storybook/pull/25926), thanks [@JReinhold](https://github.com/JReinhold)! +- Core: Remove CSF batching, as it isn't required any more - [#25872](https://github.com/storybookjs/storybook/pull/25872), thanks [@tmeasday](https://github.com/tmeasday)! +- Next.js: Fix frameworkOptions resolution - [#25907](https://github.com/storybookjs/storybook/pull/25907), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)! +- React Native: Fix init fails when package is already installed - [#25908](https://github.com/storybookjs/storybook/pull/25908), thanks [@dannyhw](https://github.com/dannyhw)! +- React Native: Remove watcher from init - [#25895](https://github.com/storybookjs/storybook/pull/25895), thanks [@dannyhw](https://github.com/dannyhw)! +- Test: Fix jest-dom matcher type imports - [#25869](https://github.com/storybookjs/storybook/pull/25869), thanks [@alitas](https://github.com/alitas)! +- UI: Fix overlapping on the ref button in the sidebar - [#25914](https://github.com/storybookjs/storybook/pull/25914), thanks [@cdedreuille](https://github.com/cdedreuille)! +- UI: Remove keyboard shortcut hint in search bar on mobile viewports - [#25866](https://github.com/storybookjs/storybook/pull/25866), thanks [@tusharwebd](https://github.com/tusharwebd)! + ## 8.0.0-beta.0 - CLI: Add Visual Tests addon to `init` - [#25850](https://github.com/storybookjs/storybook/pull/25850), thanks [@shilman](https://github.com/shilman)! diff --git a/MIGRATION.md b/MIGRATION.md index bc3727aa4528..15b17681953b 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -28,6 +28,7 @@ - [Removed stories.json](#removed-storiesjson) - [Removed `sb babelrc` command](#removed-sb-babelrc-command) - [Changed interfaces for `@storybook/router` components](#changed-interfaces-for-storybookrouter-components) + - [Extract no longer batches](#extract-no-longer-batches) - [Framework-specific changes](#framework-specific-changes) - [React](#react) - [`react-docgen` component analysis by default](#react-docgen-component-analysis-by-default) @@ -35,6 +36,8 @@ - [Require Next.js 13.5 and up](#require-nextjs-135-and-up) - [Automatic SWC mode detection](#automatic-swc-mode-detection) - [RSC config moved to React renderer](#rsc-config-moved-to-react-renderer) + - [Vue](#vue) + - [Require Vue 3 and up](#require-vue-3-and-up) - [Angular](#angular) - [Require Angular 15 and up](#require-angular-15-and-up) - [Svelte](#svelte) @@ -710,6 +713,10 @@ The reasoning behind is to condense and provide some clarity to what's happened The `hideOnly` prop has been removed from the `` component in `@storybook/router`. If needed this can be implemented manually with the `` component. +#### Extract no longer batches + +`Preview.extract()` no longer loads CSF files in batches. This was a workaround for resource limitations that slowed down extract. This shouldn't affect behaviour. + ### Framework-specific changes #### React @@ -749,6 +756,12 @@ Storybook 7.6 introduced a new feature flag, `experimentalNextRSC`, to enable Re These flags have been renamed to `experimentalRSC` and `react.rsc`, respectively. This is a breaking change to accommodate RSC support in other, non-Next.js frameworks. For now, `@storybook/nextjs` is the only framework that supports it, and does so experimentally. +#### Vue + +##### Require Vue 3 and up + +Starting in 8.0, Storybook requires Vue 3 and up. + #### Angular ##### Require Angular 15 and up diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json index 014b90c65a27..a1b64a1fccee 100644 --- a/code/addons/backgrounds/package.json +++ b/code/addons/backgrounds/package.json @@ -53,13 +53,13 @@ }, "dependencies": { "@storybook/global": "^5.0.0", - "@storybook/icons": "^1.2.3", "memoizerific": "^1.11.3", "ts-dedent": "^2.0.0" }, "devDependencies": { "@storybook/client-logger": "workspace:*", "@storybook/components": "workspace:*", + "@storybook/icons": "^1.2.3", "@storybook/manager-api": "workspace:*", "@storybook/preview-api": "workspace:*", "@storybook/theming": "workspace:*", diff --git a/code/addons/docs/docs/props-tables.md b/code/addons/docs/docs/props-tables.md index dcfe92476c04..8dd5e8f7a285 100644 --- a/code/addons/docs/docs/props-tables.md +++ b/code/addons/docs/docs/props-tables.md @@ -228,7 +228,7 @@ This package relies on a variety of sub-packages to extract property information | Framework | Underlying library | Docs | Open issues | | -------------- | ---------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | React | `react-docgen` `react-docgen-typescript` | [Docs](../react/README.md#props-tables) | [Open issues](https://github.com/storybookjs/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22block%3A+props%22+label%3Abug+label%3A%22app%3A+react%22) | -| Vue 3 | `vue-docgen-api` | [Docs](../vue3/README.md#props-tables) | [Open issues](https://github.com/storybookjs/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22block%3A+props%22+label%3Abug+label%3A%22vue3%22) | +| Vue 3 | `vue-docgen-api` | [Docs](../vue3/README.md#props-tables) | [Open issues](https://github.com/storybookjs/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22block%3A+props%22+label%3Abug+label%3A%22vue3%22) | | Angular | `compodoc` | [Docs](../angular/README.md#props-tables) | [Open issues](https://github.com/storybookjs/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22block%3A+props%22+label%3Abug+label%3A%22app%3A+angular%22) | | Web-components | `custom-elements.json` | [Docs](../web-components/README.md#props-tables) | [Open issues](https://github.com/storybookjs/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22block%3A+props%22+label%3Abug+label%3A%22app%3A+web-components%22) | | Ember | `yui-doc` | [Docs](../ember/README.md#props-tables) | [Open issues](https://github.com/storybookjs/storybook/issues?q=is%3Aopen+is%3Aissue+label%3A%22block%3A+props%22+label%3Abug+label%3A%22app%3A+ember%22) | diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json index 5d5bfe1c1a6b..00e2eb665df9 100644 --- a/code/addons/docs/package.json +++ b/code/addons/docs/package.json @@ -111,9 +111,10 @@ "@storybook/react-dom-shim": "workspace:*", "@storybook/theming": "workspace:*", "@storybook/types": "workspace:*", + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", "fs-extra": "^11.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", "rehype-external-links": "^3.0.0", "rehype-slug": "^6.0.0", "ts-dedent": "^2.0.0" @@ -122,6 +123,8 @@ "@mdx-js/mdx": "^3.0.0", "@rollup/pluginutils": "^5.0.2", "@storybook/test": "workspace:*", + "react": "^18.2.0", + "react-dom": "^18.2.0", "typescript": "^5.3.2", "vite": "^4.0.4" }, diff --git a/code/addons/docs/src/preset.ts b/code/addons/docs/src/preset.ts index ae79832240d1..45c832b5fe42 100644 --- a/code/addons/docs/src/preset.ts +++ b/code/addons/docs/src/preset.ts @@ -138,24 +138,26 @@ export const viteFinal = async (config: any, options: Options) => { const { mdxPlugin } = await import('./plugins/mdx-plugin'); // Use the resolvedReact preset to alias react and react-dom to either the users version or the version shipped with addon-docs - const { react, reactDom } = await getResolvedReact(options); + const { react, reactDom, mdx } = await getResolvedReact(options); - const reactAliasPlugin = { - name: 'storybook:react-alias', + const packageDeduplicationPlugin = { + name: 'storybook:package-deduplication', enforce: 'pre', config: () => ({ resolve: { alias: { react, 'react-dom': reactDom, + '@mdx-js/react': mdx, }, + dedupe: ['@storybook/theming', '@storybook/components', '@storybook/blocks'], }, }), }; // add alias plugin early to ensure any other plugins that also add the aliases will override this // eg. the preact vite plugin adds its own aliases - plugins.unshift(reactAliasPlugin); + plugins.unshift(packageDeduplicationPlugin); plugins.push(mdxPlugin(options)); return config; diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json index 83209d573b5b..1dba11e3c4c6 100644 --- a/code/addons/interactions/package.json +++ b/code/addons/interactions/package.json @@ -50,7 +50,6 @@ }, "dependencies": { "@storybook/global": "^5.0.0", - "@storybook/icons": "^1.2.3", "@storybook/types": "workspace:*", "jest-mock": "^27.0.6", "polished": "^4.2.2", @@ -62,6 +61,7 @@ "@storybook/components": "workspace:*", "@storybook/core-common": "workspace:*", "@storybook/core-events": "workspace:*", + "@storybook/icons": "^1.2.3", "@storybook/instrumenter": "workspace:*", "@storybook/manager-api": "workspace:*", "@storybook/preview-api": "workspace:*", diff --git a/code/addons/measure/package.json b/code/addons/measure/package.json index 372022fb39f9..fc8b9f7e6693 100644 --- a/code/addons/measure/package.json +++ b/code/addons/measure/package.json @@ -65,13 +65,13 @@ }, "dependencies": { "@storybook/global": "^5.0.0", - "@storybook/icons": "^1.2.3", "tiny-invariant": "^1.3.1" }, "devDependencies": { "@storybook/client-logger": "workspace:*", "@storybook/components": "workspace:*", "@storybook/core-events": "workspace:*", + "@storybook/icons": "^1.2.3", "@storybook/manager-api": "workspace:*", "@storybook/preview-api": "workspace:*", "@storybook/types": "workspace:*", diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json index b05149872107..92a14a1228df 100644 --- a/code/addons/outline/package.json +++ b/code/addons/outline/package.json @@ -55,13 +55,13 @@ }, "dependencies": { "@storybook/global": "^5.0.0", - "@storybook/icons": "^1.2.3", "ts-dedent": "^2.0.0" }, "devDependencies": { "@storybook/client-logger": "workspace:*", "@storybook/components": "workspace:*", "@storybook/core-events": "workspace:*", + "@storybook/icons": "^1.2.3", "@storybook/manager-api": "workspace:*", "@storybook/preview-api": "workspace:*", "@storybook/types": "workspace:*", diff --git a/code/builders/builder-vite/input/iframe.html b/code/builders/builder-vite/input/iframe.html index dd976d6c4ab4..7720ef6b9482 100644 --- a/code/builders/builder-vite/input/iframe.html +++ b/code/builders/builder-vite/input/iframe.html @@ -1,44 +1,66 @@ - + + + + Storybook + - - - Storybook - + + + + + - - - - - + + + - // We do this so that "module && module.hot" etc. in Storybook source code - // doesn't fail (it will simply be disabled) - window.module = undefined; - window.global = window; - - - - - - -
-
- - - - - \ No newline at end of file + + +
+
+ + + + diff --git a/code/frameworks/nextjs/README.md b/code/frameworks/nextjs/README.md index 94158fce5b02..87019027ca9a 100644 --- a/code/frameworks/nextjs/README.md +++ b/code/frameworks/nextjs/README.md @@ -1,10 +1,10 @@ # Storybook for Next.js -See [documentation](https://storybook.js.org/docs/get-started/nextjs) for installation instructions, usage examples, api, and more. +See [documentation](https://storybook.js.org/docs/8.0/get-started/nextjs) for installation instructions, usage examples, APIs, and more. ## Acknowledgements This framework borrows heavily from these Storybook addons: - [storybook-addon-next](https://github.com/RyanClementsHax/storybook-addon-next) by [RyanClementsHax](https://github.com/RyanClementsHax/) -- [storybook-addon-next-router](https://github.com/lifeiscontent/storybook-addon-next-router) by [lifeiscontent](https://github.com/lifeiscontent) \ No newline at end of file +- [storybook-addon-next-router](https://github.com/lifeiscontent/storybook-addon-next-router) by [lifeiscontent](https://github.com/lifeiscontent) diff --git a/code/frameworks/nextjs/src/preset.ts b/code/frameworks/nextjs/src/preset.ts index 027d5bad0b2b..bb7ac0ddf153 100644 --- a/code/frameworks/nextjs/src/preset.ts +++ b/code/frameworks/nextjs/src/preset.ts @@ -110,10 +110,7 @@ export const babel: PresetProperty<'babel'> = async (baseConfig: TransformOption }; export const webpackFinal: StorybookConfig['webpackFinal'] = async (baseConfig, options) => { - const frameworkOptions = await options.presets.apply<{ options: FrameworkOptions }>( - 'frameworkOptions' - ); - const { options: { nextConfigPath } = {} } = frameworkOptions; + const { nextConfigPath } = await options.presets.apply('frameworkOptions'); const nextConfig = await configureConfig({ baseConfig, nextConfigPath, diff --git a/code/lib/cli/src/generators/REACT_NATIVE/index.ts b/code/lib/cli/src/generators/REACT_NATIVE/index.ts index 94724ba1af59..c8e4582382dd 100644 --- a/code/lib/cli/src/generators/REACT_NATIVE/index.ts +++ b/code/lib/cli/src/generators/REACT_NATIVE/index.ts @@ -14,12 +14,15 @@ const generator = async ( const reactVersion = packageJson.dependencies.react; - const packagesToResolve = [ - // addon-ondevice-controls peer deps + const controlsPeerDependencies = [ 'react-native-safe-area-context', '@react-native-async-storage/async-storage', '@react-native-community/datetimepicker', '@react-native-community/slider', + ].filter((dep) => !packageJson.dependencies[dep] && !packageJson.devDependencies[dep]); + + const packagesToResolve = [ + ...controlsPeerDependencies, '@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-actions', '@storybook/react-native', @@ -47,7 +50,6 @@ const generator = async ( packageManager.addScripts({ 'storybook-generate': 'sb-rn-get-stories', - 'storybook-watch': 'sb-rn-watcher', }); const storybookConfigFolder = '.storybook'; diff --git a/code/lib/cli/tsconfig.json b/code/lib/cli/tsconfig.json index e32ebe0f7b90..9c5db279ca2d 100644 --- a/code/lib/cli/tsconfig.json +++ b/code/lib/cli/tsconfig.json @@ -1,15 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "types": [ - "node" - ], + "types": ["node"], "strict": true, "skipLibCheck": true, "resolveJsonModule": true, "noEmit": true }, - "include": [ - "src/**/*" - ] -} \ No newline at end of file + "include": ["src/**/*"] +} diff --git a/code/lib/core-common/templates/base-preview-head.html b/code/lib/core-common/templates/base-preview-head.html index c19b0b5bdbcf..c4732d25281c 100644 --- a/code/lib/core-common/templates/base-preview-head.html +++ b/code/lib/core-common/templates/base-preview-head.html @@ -62,8 +62,17 @@ left: 0; right: 0; padding: 20px; - font-family: 'Nunito Sans', -apple-system, '.SFNSText-Regular', 'San Francisco', - BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-family: + 'Nunito Sans', + -apple-system, + '.SFNSText-Regular', + 'San Francisco', + BlinkMacSystemFont, + 'Segoe UI', + 'Helvetica Neue', + Helvetica, + Arial, + sans-serif; -webkit-font-smoothing: antialiased; overflow: auto; } @@ -257,7 +266,9 @@ .sb-argstableBlock-body { border-radius: 4px; - box-shadow: rgba(0, 0, 0, 0.1) 0 1px 3px 1px, rgba(0, 0, 0, 0.065) 0 0 0 1px; + box-shadow: + rgba(0, 0, 0, 0.1) 0 1px 3px 1px, + rgba(0, 0, 0, 0.065) 0 0 0 1px; } .sb-argstableBlock-body tr { background: transparent; diff --git a/code/lib/preview-api/docs/storiesOf.md b/code/lib/preview-api/docs/storiesOf.md index 00f3b2945879..08e7009a9d0d 100644 --- a/code/lib/preview-api/docs/storiesOf.md +++ b/code/lib/preview-api/docs/storiesOf.md @@ -4,7 +4,7 @@ In Storybook 5.2 we introduced a simpler and more portable [Component Story Format](https://storybook.js.org/docs/react/api/csf), and all future tools and infrastructure will be oriented towards CSF. Therefore, we recommend migrating your stories out of `storiesOf` API, and even provide [automated tools to do this](#component-story-format-migration). -That said, the `storiesOf` API is not officially deprecated. For the time being we plan to support it for the foreseeable future. +That said, the `storiesOf` API is no longer actively maintained and has been removed as part of the Storybook 8 release. If you're working with a custom indexer or similar tooling that implements this API, we encourage using custom story indexers instead. Read our [Indexer API documentation](https://storybook.js.org/docs/api/main-config-indexers) for more information. ## storiesOf API diff --git a/code/lib/preview-api/src/modules/store/StoryStore.test.ts b/code/lib/preview-api/src/modules/store/StoryStore.test.ts index 7d796970b560..65f225c8ef6e 100644 --- a/code/lib/preview-api/src/modules/store/StoryStore.test.ts +++ b/code/lib/preview-api/src/modules/store/StoryStore.test.ts @@ -28,14 +28,6 @@ vi.mock('@storybook/global', async (importOriginal) => ({ vi.mock('@storybook/client-logger'); -const createGate = (): [Promise, (_?: any) => void] => { - let openGate = (_?: any) => {}; - const gate = new Promise((resolve) => { - openGate = resolve; - }); - return [gate, openGate]; -}; - const componentOneExports = { default: { title: 'Component One' }, a: { args: { foo: 'a' } }, @@ -435,22 +427,6 @@ describe('StoryStore', () => { './src/ComponentTwo.stories.js', ]); }); - - it('imports in batches', async () => { - const [gate, openGate] = createGate(); - const blockedImportFn = vi.fn(async (file) => { - await gate; - return importFn(file); - }); - const store = new StoryStore(storyIndex, blockedImportFn, projectAnnotations); - - const promise = store.loadAllCSFFiles({ batchSize: 1 }); - expect(blockedImportFn).toHaveBeenCalledTimes(1); - - openGate(); - await promise; - expect(blockedImportFn).toHaveBeenCalledTimes(3); - }); }); describe('extract', () => { diff --git a/code/lib/preview-api/src/modules/store/StoryStore.ts b/code/lib/preview-api/src/modules/store/StoryStore.ts index c779f13ddd2c..123ea5b984c8 100644 --- a/code/lib/preview-api/src/modules/store/StoryStore.ts +++ b/code/lib/preview-api/src/modules/store/StoryStore.ts @@ -41,9 +41,9 @@ import { prepareContext, } from './csf'; +// TODO -- what are reasonable values for these? const CSF_CACHE_SIZE = 1000; const STORY_CACHE_SIZE = 10000; -const EXTRACT_BATCH_SIZE = 20; export class StoryStore { public storyIndex: StoryIndexStore; @@ -127,32 +127,19 @@ export class StoryStore { return this.processCSFFileWithCache(moduleExports, importPath, title); } - async loadAllCSFFiles({ batchSize = EXTRACT_BATCH_SIZE } = {}): Promise< - StoryStore['cachedCSFFiles'] - > { - const importPaths = Object.entries(this.storyIndex.entries).map(([storyId, { importPath }]) => [ - importPath, - storyId, - ]); - - const loadInBatches = async ( - remainingImportPaths: typeof importPaths - ): Promise<{ importPath: Path; csfFile: CSFFile }[]> => { - if (remainingImportPaths.length === 0) return Promise.resolve([]); - - const csfFilePromiseList = remainingImportPaths - .slice(0, batchSize) - .map(async ([importPath, storyId]) => ({ - importPath, - csfFile: await this.loadCSFFileByStoryId(storyId), - })); - - const firstResults = await Promise.all(csfFilePromiseList); - const restResults = await loadInBatches(remainingImportPaths.slice(batchSize)); - return firstResults.concat(restResults); - }; + async loadAllCSFFiles(): Promise['cachedCSFFiles']> { + const importPaths: Record = {}; + Object.entries(this.storyIndex.entries).forEach(([storyId, { importPath }]) => { + importPaths[importPath] = storyId; + }); + + const list = await Promise.all( + Object.entries(importPaths).map(async ([importPath, storyId]) => ({ + importPath, + csfFile: await this.loadCSFFileByStoryId(storyId), + })) + ); - const list = await loadInBatches(importPaths); return list.reduce( (acc, { importPath, csfFile }) => { acc[importPath] = csfFile; diff --git a/code/lib/test/src/expect.ts b/code/lib/test/src/expect.ts index da17eb52ff59..aa898bd7e36a 100644 --- a/code/lib/test/src/expect.ts +++ b/code/lib/test/src/expect.ts @@ -16,7 +16,7 @@ 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'; +import type { TestingLibraryMatchers } from '@testing-library/jest-dom/matchers'; type Matchers = PromisifyObject> & TestingLibraryMatchers, Promise>; diff --git a/code/lib/theming/package.json b/code/lib/theming/package.json index f4eba20e29c2..711f4693b829 100644 --- a/code/lib/theming/package.json +++ b/code/lib/theming/package.json @@ -71,6 +71,14 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + }, "publishConfig": { "access": "public" }, diff --git a/code/package.json b/code/package.json index 873161d24b2d..9dd44c00a1a2 100644 --- a/code/package.json +++ b/code/package.json @@ -76,18 +76,18 @@ "defaults" ], "resolutions": { - "@playwright/test": "1.41.1", + "@playwright/test": "1.36.0", "@storybook/theming": "workspace:*", "@vitest/expect@1.1.3": "patch:@vitest/expect@npm%3A1.1.3#~/.yarn/patches/@vitest-expect-npm-1.1.3-2062bf533f.patch", "esbuild": "^0.18.0", - "playwright": "1.41.1", - "playwright-core": "1.41.1", + "playwright": "1.36.0", + "playwright-core": "1.36.0", "serialize-javascript": "^3.1.0", "type-fest": "~2.19" }, "dependencies": { "@nx/workspace": "17.0.2", - "@playwright/test": "1.41.1", + "@playwright/test": "1.36.0", "@storybook/addon-a11y": "workspace:*", "@storybook/addon-actions": "workspace:*", "@storybook/addon-backgrounds": "workspace:*", @@ -292,5 +292,6 @@ "Dependency Upgrades" ] ] - } + }, + "deferredNextVersion": "8.0.0-beta.1" } diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/a11y.snapshot b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/a11y.snapshot index 0057e3dd70c4..6d22e73bf022 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/a11y.snapshot +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/a11y.snapshot @@ -1,23 +1,18 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`json-to-csf-compiler a11y.json 1`] = ` -" export default { - title: \\"Addons/a11y\\", + title: "Addons/a11y", parameters: { options: { - selectedPanel: \\"storybook/a11y/panel\\" + selectedPanel: "storybook/a11y/panel" } } }; export const Label = { - name: \\"Label\\", + name: "Label", parameters: { server: { - id: \\"addons/a11y/label\\" + id: "addons/a11y/label" } } }; -" -`; diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/actions.snapshot b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/actions.snapshot index b2f7434f4b0b..2317e70d92d2 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/actions.snapshot +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/actions.snapshot @@ -1,30 +1,25 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`json-to-csf-compiler actions.json 1`] = ` -" export default { - title: \\"Addons/Actions\\", + title: "Addons/Actions", parameters: { options: { - selectedPanel: \\"storybook/actions/panel\\" + selectedPanel: "storybook/actions/panel" } } }; export const Multiple_actions_config = { - name: \\"Multiple actions + config\\", + name: "Multiple actions + config", parameters: { actions: [ - \\"click\\", - \\"contextmenu\\", + "click", + "contextmenu", { clearOnStoryChange: false } ], server: { - id: \\"addons/actions/story3\\" + id: "addons/actions/story3" } } }; -" -`; diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/backgrounds.snapshot b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/backgrounds.snapshot index 12bac06c25cb..40a2bf3524a1 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/backgrounds.snapshot +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/backgrounds.snapshot @@ -1,18 +1,15 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`json-to-csf-compiler backgrounds.json 1`] = ` -" export default { - title: \\"Addons/Backgrounds\\", + title: "Addons/Backgrounds", parameters: { backgrounds: [ { - name: \\"light\\", - value: \\"#eeeeee\\" + name: "light", + value: "#eeeeee" }, { - name: \\"dark\\", - value: \\"#222222\\", + name: "dark", + value: "#222222", default: true } ] @@ -20,12 +17,10 @@ export default { }; export const Story_1 = { - name: \\"Story 1\\", + name: "Story 1", parameters: { server: { - id: \\"addons/backgrounds/story1\\" + id: "addons/backgrounds/story1" } } }; -" -`; diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/controls.snapshot b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/controls.snapshot index ccbda5cd711c..519ae472aca0 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/controls.snapshot +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/controls.snapshot @@ -1,62 +1,57 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`json-to-csf-compiler controls.json 1`] = ` -" export default { - title: \\"Addons/Controls\\", + title: "Addons/Controls", parameters: { options: { - selectedPanel: \\"storybook/controls/panel\\" + selectedPanel: "storybook/controls/panel" } } }; export const Simple = { - name: \\"Simple\\", + name: "Simple", parameters: { server: { - id: \\"addons/controls/simple\\" + id: "addons/controls/simple" } }, args: { - name: \\"John Doe\\", - birthday: \\"1960-12-25T00:42:03.600Z\\", - favorite_color: \\"red\\", + name: "John Doe", + birthday: "1960-12-25T00:42:03.600Z", + favorite_color: "red", active: true, pets: 2, sports: [ - \\"football\\", - \\"baseball\\" + "football", + "baseball" ], - favorite_food: \\"Ice Cream\\", + favorite_food: "Ice Cream", other_things: { - hair: \\"Brown\\", - eyes: \\"Blue\\" + hair: "Brown", + eyes: "Blue" } }, argTypes: { birthday: { control: { - type: \\"date\\" + type: "date" } }, favorite_color: { control: { - type: \\"color\\" + type: "color" } }, favorite_food: { control: { - type: \\"select\\", + type: "select", options: { - hot_dog: \\"Hot Dog\\", - pizza: \\"Pizza\\", - burgers: \\"Burgers\\", - ice_cream: \\"Ice Cream\\" + hot_dog: "Hot Dog", + pizza: "Pizza", + burgers: "Burgers", + ice_cream: "Ice Cream" } } } } }; -" -`; diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/kitchen_sink.snapshot b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/kitchen_sink.snapshot index 14b34271465e..c8af3046016c 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/kitchen_sink.snapshot +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/kitchen_sink.snapshot @@ -1,62 +1,57 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`json-to-csf-compiler kitchen_sink.json 1`] = ` -" export default { - title: \\"Kitchen Sink\\", + title: "Kitchen Sink", parameters: { backgrounds: [ { - name: \\"light\\", - value: \\"#eeeeee\\" + name: "light", + value: "#eeeeee" }, { - name: \\"dark\\", - value: \\"#222222\\", + name: "dark", + value: "#222222", default: true } ], options: { - selectedPanel: \\"storybook/a11y/panel\\" + selectedPanel: "storybook/a11y/panel" }, server: { params: { - color: \\"red\\" + color: "red" } } } }; export const Heading = { - name: \\"Heading\\", + name: "Heading", parameters: { actions: [ - \\"click\\", - \\"contextmenu\\", + "click", + "contextmenu", { clearOnStoryChange: false } ], server: { - id: \\"demo/heading\\", + id: "demo/heading", params: { - color: \\"orange\\" + color: "orange" } } }, args: { - name: \\"John Doe\\", + name: "John Doe", age: 44 } }; export const Button = { - name: \\"Button\\", + name: "Button", parameters: { server: { - id: \\"demo/button\\" + id: "demo/button" } } }; -" -`; diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/links.snapshot b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/links.snapshot index 9c269a837cf1..140837fa3c52 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/links.snapshot +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/links.snapshot @@ -1,18 +1,13 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`json-to-csf-compiler links.json 1`] = ` -" export default { - title: \\"Welcome\\", + title: "Welcome", }; export const Welcome = { - name: \\"Welcome\\", + name: "Welcome", parameters: { server: { - id: \\"welcome/welcome\\" + id: "welcome/welcome" } } }; -" -`; diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/multiple_stories.snapshot b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/multiple_stories.snapshot index 756da4e91ab6..1e4c59f1ea35 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/multiple_stories.snapshot +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/multiple_stories.snapshot @@ -1,36 +1,31 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`json-to-csf-compiler multiple_stories.json 1`] = ` -" export default { - title: \\"Demo\\", + title: "Demo", }; export const Heading = { - name: \\"Heading\\", + name: "Heading", parameters: { server: { - id: \\"demo/heading\\" + id: "demo/heading" } } }; export const Headings = { - name: \\"Headings\\", + name: "Headings", parameters: { server: { - id: \\"demo/headings\\" + id: "demo/headings" } } }; export const Button = { - name: \\"Button\\", + name: "Button", parameters: { server: { - id: \\"demo/button\\" + id: "demo/button" } } }; -" -`; diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params.json b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params.json index 60f6b720cf42..5084fdbe743f 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params.json +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params.json @@ -2,7 +2,8 @@ "title": "Params", "parameters": { "server": { - "params": { "color": "red" } + "params": { "color": "red" }, + "1200x600": { "viewport": { "width": 1200, "height": 600 } } } }, "stories": [ diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params.snapshot b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params.snapshot index 1423ce39b9c5..0c6757db5a00 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params.snapshot +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params.snapshot @@ -1,28 +1,29 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`json-to-csf-compiler params.json 1`] = ` -" export default { - title: \\"Params\\", + title: "Params", parameters: { server: { params: { - color: \\"red\\" + color: "red" + }, + 1200x600: { + viewport: { + width: 1200, + height: 600 + } } } } }; export const Story = { - name: \\"Story\\", + name: "Story", parameters: { server: { - id: \\"params/story\\", + id: "params/story", params: { - message: \\"Hello World\\" + message: "Hello World" } } } }; -" -`; diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params_override.snapshot b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params_override.snapshot index 11a59bd1b516..7d6396a17ece 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params_override.snapshot +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/params_override.snapshot @@ -1,29 +1,24 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`json-to-csf-compiler params_override.json 1`] = ` -" export default { - title: \\"Params\\", + title: "Params", parameters: { server: { params: { - color: \\"red\\" + color: "red" } } } }; export const Override = { - name: \\"Override\\", + name: "Override", parameters: { server: { - id: \\"params/override\\", + id: "params/override", params: { - message: \\"Hello World\\", - color: \\"green\\" + message: "Hello World", + color: "green" } } } }; -" -`; diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/yaml.snapshot b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/yaml.snapshot index cde9cda3d0bc..f22f2f5685d5 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/yaml.snapshot +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/yaml.snapshot @@ -1,36 +1,31 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ya?ml-to-csf-compiler yaml.yaml 1`] = ` -" export default { - title: \\"Demo YAML\\", + title: "Demo YAML", }; export const Heading = { - name: \\"Heading\\", + name: "Heading", parameters: { server: { - id: \\"yaml/heading\\" + id: "yaml/heading" } } }; export const Headings = { - name: \\"Headings\\", + name: "Headings", parameters: { server: { - id: \\"yaml/headings\\" + id: "yaml/headings" } } }; export const Button = { - name: \\"Button\\", + name: "Button", parameters: { server: { - id: \\"yaml/button\\" + id: "yaml/button" } } }; -" -`; diff --git a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/yml.snapshot b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/yml.snapshot index 15c610e2fe6e..c95096f6c85e 100644 --- a/code/presets/server-webpack/src/lib/compiler/__testfixtures__/yml.snapshot +++ b/code/presets/server-webpack/src/lib/compiler/__testfixtures__/yml.snapshot @@ -1,36 +1,31 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ya?ml-to-csf-compiler yml.yml 1`] = ` -" export default { - title: \\"Demo YML\\", + title: "Demo YML", }; export const Heading = { - name: \\"Heading\\", + name: "Heading", parameters: { server: { - id: \\"yaml/heading\\" + id: "yaml/heading" } } }; export const Headings = { - name: \\"Headings\\", + name: "Headings", parameters: { server: { - id: \\"yaml/headings\\" + id: "yaml/headings" } } }; export const Button = { - name: \\"Button\\", + name: "Button", parameters: { server: { - id: \\"yaml/button\\" + id: "yaml/button" } } }; -" -`; diff --git a/code/presets/server-webpack/vitest.config.ts b/code/presets/server-webpack/vitest.config.ts new file mode 100644 index 000000000000..045610882bc0 --- /dev/null +++ b/code/presets/server-webpack/vitest.config.ts @@ -0,0 +1,14 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { defineConfig, mergeConfig } from 'vitest/config'; +import { sep, posix } from 'path'; +import { vitestCommonConfig } from '../../vitest.workspace'; + +export default mergeConfig( + vitestCommonConfig, + defineConfig({ + test: { + environment: 'node', + name: __dirname.split(sep).slice(-2).join(posix.sep), + }, + }) +); diff --git a/code/presets/vue3-webpack/README.md b/code/presets/vue3-webpack/README.md index e361f8bc4222..4c2a2df89914 100644 --- a/code/presets/vue3-webpack/README.md +++ b/code/presets/vue3-webpack/README.md @@ -3,4 +3,4 @@ This package is a [preset](https://storybook.js.org/docs/addons/writing-presets#presets-api) that configures Storybook's webpack settings for handling Vue 3. It's an internal package that's not intended to be used directly by users. -- More info on [Storybook for Vue3](https://storybook.js.org/docs/get-started/why-storybook) \ No newline at end of file +- More info on [Storybook for Vue3](https://storybook.js.org/docs/get-started/why-storybook) diff --git a/code/ui/blocks/package.json b/code/ui/blocks/package.json index 40180c3914ed..c721cb2ecd11 100644 --- a/code/ui/blocks/package.json +++ b/code/ui/blocks/package.json @@ -78,6 +78,14 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + }, "publishConfig": { "access": "public" }, diff --git a/code/ui/manager/src/components/sidebar/Refs.tsx b/code/ui/manager/src/components/sidebar/Refs.tsx index 04f90148f7b8..1cd5c6c7a5a0 100644 --- a/code/ui/manager/src/components/sidebar/Refs.tsx +++ b/code/ui/manager/src/components/sidebar/Refs.tsx @@ -67,6 +67,7 @@ const CollapseButton = styled.button(({ theme }) => ({ gap: 6, alignItems: 'center', cursor: 'pointer', + overflow: 'hidden', '&:focus': { borderColor: theme.color.secondary, diff --git a/code/ui/manager/src/components/sidebar/Search.tsx b/code/ui/manager/src/components/sidebar/Search.tsx index 525337b8b2aa..cbbecc8264a6 100644 --- a/code/ui/manager/src/components/sidebar/Search.tsx +++ b/code/ui/manager/src/components/sidebar/Search.tsx @@ -20,6 +20,7 @@ import { isSearchResult, isExpandType } from './types'; import { scrollIntoView, searchItem } from '../../utils/tree'; import { getGroupStatus, getHighestStatus } from '../../utils/status'; +import { useLayout } from '../layout/LayoutProvider'; const { document } = global; @@ -288,6 +289,7 @@ export const Search = React.memo<{ }, [inputRef, selectStory, showAllComponents] ); + const { isMobile } = useLayout(); return ( @@ -359,7 +361,7 @@ export const Search = React.memo<{ {/* @ts-expect-error (TODO) */} - {enableShortcuts && !isOpen && ( + {!isMobile && enableShortcuts && !isOpen && ( {searchShortcut === '⌘ K' ? ( <> diff --git a/code/yarn.lock b/code/yarn.lock index 135de6c3f84e..56313ad4174c 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -4238,14 +4238,19 @@ __metadata: languageName: node linkType: hard -"@playwright/test@npm:1.41.1": - version: 1.41.1 - resolution: "@playwright/test@npm:1.41.1" +"@playwright/test@npm:1.36.0": + version: 1.36.0 + resolution: "@playwright/test@npm:1.36.0" dependencies: - playwright: "npm:1.41.1" + "@types/node": "npm:*" + fsevents: "npm:2.3.2" + playwright-core: "npm:1.36.0" + dependenciesMeta: + fsevents: + optional: true bin: playwright: cli.js - checksum: 72bd5bb67c512027d214b9c54c2a22a469bd19d7809771e53a5bfdcc11330591e01579bb22f807d1ebbcdcea35d625e0fc9eb9791cebcc63bf55b82dd1cdefdd + checksum: 9d06764f55ae10569981d518838d588d820678a4e6a8a1bbfab78b7b4b4245cf055e94a0dea90fe2ecf1ce4559d06e02986757270e7c54a52d0bdf1963cb03e6 languageName: node linkType: hard @@ -4838,6 +4843,7 @@ __metadata: "@storybook/test": "workspace:*" "@storybook/theming": "workspace:*" "@storybook/types": "workspace:*" + "@types/react": "npm:^16.8.0 || ^17.0.0 || ^18.0.0" fs-extra: "npm:^11.1.0" react: "npm:^18.2.0" react-dom: "npm:^18.2.0" @@ -5206,6 +5212,11 @@ __metadata: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true languageName: unknown linkType: soft @@ -6311,7 +6322,7 @@ __metadata: dependencies: "@chromaui/addon-visual-tests": "npm:^0.0.124" "@nx/workspace": "npm:17.0.2" - "@playwright/test": "npm:1.41.1" + "@playwright/test": "npm:1.36.0" "@storybook/addon-a11y": "workspace:*" "@storybook/addon-actions": "workspace:*" "@storybook/addon-backgrounds": "workspace:*" @@ -6678,6 +6689,11 @@ __metadata: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true languageName: unknown linkType: soft @@ -7841,6 +7857,17 @@ __metadata: languageName: node linkType: hard +"@types/react@npm:^16.8.0 || ^17.0.0 || ^18.0.0": + version: 18.2.55 + resolution: "@types/react@npm:18.2.55" + dependencies: + "@types/prop-types": "npm:*" + "@types/scheduler": "npm:*" + csstype: "npm:^3.0.2" + checksum: 6b1c73beafbbc582dc54ffd92b3779f6d850e8f6b5ce5d04b31e9498a3d77bfc416bb08f0d8d63ab4f4649ccd6639996472416871c01c74a528b16a55faeaf38 + languageName: node + linkType: hard + "@types/resolve@npm:^1.20.2": version: 1.20.3 resolution: "@types/resolve@npm:1.20.3" @@ -22917,27 +22944,23 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.41.1": - version: 1.41.1 - resolution: "playwright-core@npm:1.41.1" +"playwright-core@npm:1.36.0": + version: 1.36.0 + resolution: "playwright-core@npm:1.36.0" bin: playwright-core: cli.js - checksum: cdd91267ca23e3f65d519100e956859c70e3e9ca29e3fe00e700b457903129e41dfa17752f1ea37ad0a8a7c6330baf9f3be503e4cbfa3e8833e80a037f899aee + checksum: 5b5d32495e222ddd4351d1d8b116a25a7d93ea5f3439dceaceeb916d0abdce6d5b0b84f80df0b239168d55a100e7aecc9db4774ff20ba0210d8de027f258b544 languageName: node linkType: hard -"playwright@npm:1.41.1": - version: 1.41.1 - resolution: "playwright@npm:1.41.1" +"playwright@npm:1.36.0": + version: 1.36.0 + resolution: "playwright@npm:1.36.0" dependencies: - fsevents: "npm:2.3.2" - playwright-core: "npm:1.41.1" - dependenciesMeta: - fsevents: - optional: true + playwright-core: "npm:1.36.0" bin: playwright: cli.js - checksum: 32d48c1f8ff881770a19c9245fb4191fc36b5e97ab5f48effa0b1cf5e83fa958f6fdd7e4268dd984aa306ac5fe9e4324510211910751fb52cebb9bae819d13ca + checksum: dc39eb6271b22901cb6219a8ecdd44736169edd789d2a8be5885ded5414ee2a9e2c73a19e24d55336ddbae6f9d69522b46f1fe92998740745f1cb78d58b6cb6e languageName: node linkType: hard diff --git a/docs/api/csf.md b/docs/api/csf.md index 1ef89f2e4605..5ddbab04d894 100644 --- a/docs/api/csf.md +++ b/docs/api/csf.md @@ -8,14 +8,12 @@ Component Story Format (CSF) is the recommended way to [write stories](../writin -If you are writing stories in the older `storiesOf()` syntax, you can find documentation in an [advanced README](https://github.com/storybookjs/storybook/blob/next/code/lib/preview-api/docs/storiesOf.md). +If you have stories written in the older `storiesOf()` syntax, it was removed in Storybook 8.0 and is no longer maintained. We recommend migrating your stories to CSF. See the [migration guide](../migration-guide.md#storiesof-to-csf) for more information. In CSF, stories and component metadata are defined as ES Modules. Every component story file consists of a required [default export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export#Using_the_default_export) and one or more [named exports](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export). -CSF is supported in all frameworks except React Native, where you should use the [storiesOf API](https://github.com/storybookjs/storybook/blob/next/code/lib/preview-api/docs/storiesOf.md) instead. - ## Default export The default export defines metadata about your component, including the `component` itself, its `title` (where it will show up in the [navigation UI story hierarchy](../writing-stories/naming-components-and-hierarchy.md#sorting-stories)), [decorators](../writing-stories/decorators.md), and [parameters](../writing-stories/parameters.md). diff --git a/docs/api/doc-block-canvas.md b/docs/api/doc-block-canvas.md index 4deda4611680..ad84f57929bc 100644 --- a/docs/api/doc-block-canvas.md +++ b/docs/api/doc-block-canvas.md @@ -203,51 +203,3 @@ Type: `boolean` Default: `parameters.docs.canvas.withToolbar` Determines whether to render a toolbar containing tools to interact with the story. - -### `children` - -(⛔️ **Deprecated**) - -Type: `React.ReactNode` - -Expects only [Story](./doc-block-story.md) children. Reference the story with the `of` prop instead. - -### `columns` - -(⛔️ **Deprecated**) - -Type: `number` - -Splits the stories based on the number of defined columns. Multiple stories are not supported. - -### `isColumn` - -(⛔️ **Deprecated**) - -Type: `boolean` - -Displays the stories one above the other. Multiple stories are not supported. - -### `mdxSource` - -(⛔️ **Deprecated**) - -Type: `string` - -Provides source to display. Use [`source.code`](#source) instead. - -### `withSource` - -(⛔️ **Deprecated**) - -Type: `'open' | 'closed' | 'none'` - -Controls the source code block visibility. Use [`sourceState`](#sourcestate) instead. - -### `withToolbar` - -(⛔️ **Deprecated**) - -Type: `boolean` - -Sets the Canvas toolbar visibility. Use [`story.withToolbar`](#story) instead. diff --git a/docs/api/main-config-swc.md b/docs/api/main-config-swc.md index 0a102bf0cf13..2bb867033572 100644 --- a/docs/api/main-config-swc.md +++ b/docs/api/main-config-swc.md @@ -6,7 +6,7 @@ Parent: [main.js|ts configuration](./main-config.md) Type: `(config: swc.Options, options: Options) => swc.Options | Promise` -Customize Storybook's [SWC](https://swc.rs/) setup. +Customize Storybook's [SWC](https://swc.rs/) setup for Webpack-based projects enabled via the [`@storybook/addon-webpack5-compiler-swc`](https://storybook.js.org/addons/@storybook/addon-webpack5-compiler-swc) addon based on the supported [frameworks](../configure/frameworks.md), except Angular, Create React App, Ember.js and Next.js. diff --git a/docs/configure/compilers.md b/docs/configure/compilers.md index 803237b8b725..2019398344c1 100644 --- a/docs/configure/compilers.md +++ b/docs/configure/compilers.md @@ -6,18 +6,7 @@ Javascript compilers are essential in optimizing and transforming code, enhancin ## SWC -SWC is a fast, highly extensible tool for compiling and bundling modern JavaScript applications. Powered by [Rust](https://www.rust-lang.org/), it improves performance and reduces build times. Storybook includes a built-in integration with SWC, allowing zero-configuration setup and built-in types for APIs. If you've initialized Storybook in a Webpack-based project with any of the supported [frameworks](./frameworks.md), except Angular, it will automatically use SWC as its default, providing you with faster loading time. However, if you're upgrading from a previous version of Storybook, you may need to opt-in to use SWC by adjusting your Storybook configuration file (i.e., `.storybook/main.js|ts`) as follows: - - - - - - +SWC is a fast, highly extensible tool for compiling and bundling modern JavaScript applications. Powered by [Rust](https://www.rust-lang.org/), it improves performance and reduces build times. Storybook includes a built-in integration with SWC, allowing zero-configuration setup and built-in types for APIs. If you've initialized Storybook in a Webpack-based project with any of the supported [frameworks](./frameworks.md), except Angular, Create React App, Ember.js and Next.js, it will automatically use SWC as its default, providing you with faster loading time. diff --git a/docs/configure/frameworks-feature-support.md b/docs/configure/frameworks-feature-support.md index 912ee32eb207..7ae41614e248 100644 --- a/docs/configure/frameworks-feature-support.md +++ b/docs/configure/frameworks-feature-support.md @@ -110,8 +110,8 @@ Community frameworks have fewer contributors which means they may not be as up t To align the Storybook ecosystem with the current state of frontend development, the following features and addons are now deprecated, no longer maintained, and will be removed in future versions of Storybook -| Feature | Status | -| -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Knobs](https://github.com/storybookjs/addon-knobs) | The Knobs addon was officially deprecated with the release of Storybook 6.3 and is no longer actively maintained. We recommend using the [controls](../essentials/controls.md) instead. | -| [Storyshots](../writing-tests/snapshot-testing.md) | The Storyshots addon was officially deprecated with the release of Storybook 7.6, is no longer actively maintained and was removed in Storybook 8. See the [migration guide](../writing-tests/storyshots-migration-guide.md) for the available alternatives. | -| [`StoriesOf`](https://github.com/storybookjs/storybook/blob/next/code/lib/preview-api/docs/storiesOf.md) | The `storiesOf` API was officially deprecated with the release of Storybook 7.5 and is no longer actively maintained. We recommend using the [CSF API](../api/csf.md) instead for writing stories.
See the [migration guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#storystorev6-and-storiesof-is-deprecated) for more information. | +| Feature | Status | +| -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Knobs](https://github.com/storybookjs/addon-knobs) | The Knobs addon was officially deprecated with the release of Storybook 6.3 and is no longer actively maintained. We recommend using the [controls](../essentials/controls.md) instead. | +| [Storyshots](../writing-tests/snapshot-testing.md) | The Storyshots addon was officially deprecated with the release of Storybook 7.6, is no longer actively maintained and was removed in Storybook 8. See the [migration guide](../writing-tests/storyshots-migration-guide.md) for the available alternatives. | +| [`StoriesOf`](https://github.com/storybookjs/storybook/blob/next/code/lib/preview-api/docs/storiesOf.md) | The `storiesOf` API was officially removed with the release of Storybook 8 and is no longer maintained. We recommend using the [CSF API](../api/csf.md) instead for writing stories.
See the [migration guide](../migration-guide.md#storiesof-to-csf) for more information. | diff --git a/docs/contribute/framework.md b/docs/contribute/framework.md index 825b2f451d12..f54e19bae401 100644 --- a/docs/contribute/framework.md +++ b/docs/contribute/framework.md @@ -88,7 +88,7 @@ Because a framework is a node package, it must contain a `package.json` file. He "test": "..." }, "dependencies": { - "@storybook/addons": "^7.0.0", + "@storybook/manager-api": "^7.0.0", "@storybook/core-common": "^7.0.0", "@storybook/node-logger": "^7.0.0", "@storybook/": "^7.0.0", diff --git a/docs/migration-guide.md b/docs/migration-guide.md index 126a8fc715b5..1fa7d7c5ad4c 100644 --- a/docs/migration-guide.md +++ b/docs/migration-guide.md @@ -42,10 +42,15 @@ The rest of this guide will help you upgrade successfully, either automatically - [`*.stories.mdx` format has been removed](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#dropping-support-for-storiesmdx-csf-in-mdx-format-and-mdx1-support) - [Implicit actions (from `argTypesRegex`) can no longer be used during rendering (e.g. in a play function)](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#implicit-actions-can-not-be-used-during-rendering-for-example-in-the-play-function) - [`react-docgen` (instead of `react-docgen-typescript`) is the default for component analysis](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#react-docgen-component-analysis-by-default) -- [Yarn 1 is no longer supported](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#dropping-support-for-yarn-1) -- [Node 16 is no longer supported](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#dropping-support-for-nodejs-16) - [Storyshots has been removed](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#storyshots-has-been-removed) - [Addons API introduced in Storybook 7 is now required](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#new-addons-api) +- Ecosystem updates + - [Node 18+ is now required](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#dropping-support-for-nodejs-16) + - [Next.js 13.5+ is now required](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#require-nextjs-135-and-up) + - [Vue 3+ is now required](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#require-vue-3-and-up) + - [Angular 15+ is now required](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#require-angular-15-and-up) + - [Svelte 4+ is now required](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#require-svelte-4-and-up) + - [Yarn 1 is no longer supported](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#dropping-support-for-yarn-1) If any of these apply to your project, please read through the the linked migration notes before continuing. If any of these new requirements or changes do not fit your project, you should probably stick with Storybook 7.x. diff --git a/docs/snippets/common/chromatic-storybook-add.npm.js.mdx b/docs/snippets/common/chromatic-storybook-add.npm.js.mdx new file mode 100644 index 000000000000..e2acf17f17e3 --- /dev/null +++ b/docs/snippets/common/chromatic-storybook-add.npm.js.mdx @@ -0,0 +1,3 @@ +```shell +npx storybook@latest add @chromatic-com/storybook +``` diff --git a/docs/snippets/common/chromatic-storybook-add.pnpm.js.mdx b/docs/snippets/common/chromatic-storybook-add.pnpm.js.mdx new file mode 100644 index 000000000000..eec9409ebf86 --- /dev/null +++ b/docs/snippets/common/chromatic-storybook-add.pnpm.js.mdx @@ -0,0 +1,3 @@ +```shell +pnpm dlx storybook@latest add @chromatic-com/storybook +``` diff --git a/docs/snippets/common/chromatic-storybook-add.yarn.js.mdx b/docs/snippets/common/chromatic-storybook-add.yarn.js.mdx new file mode 100644 index 000000000000..e105517209d9 --- /dev/null +++ b/docs/snippets/common/chromatic-storybook-add.yarn.js.mdx @@ -0,0 +1,3 @@ +```shell +yarn dlx storybook@latest add @chromatic-com/storybook +``` diff --git a/docs/versions/next.json b/docs/versions/next.json index f183795f3f3e..2f237198e882 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"8.0.0-beta.0","info":{"plain":"- CLI: Add Visual Tests addon to `init` - [#25850](https://github.com/storybookjs/storybook/pull/25850), thanks [@shilman](https://github.com/shilman)!\n- CLI: Upgrade boxen library - [#25713](https://github.com/storybookjs/storybook/pull/25713), thanks [@yannbf](https://github.com/yannbf)!\n- UI: Fix custom tabs not showing in the manager - [#25792](https://github.com/storybookjs/storybook/pull/25792), thanks [@ndelangen](https://github.com/ndelangen)!"}} +{"version":"8.0.0-beta.1","info":{"plain":"- Addon-docs: Fix MDX components not being applied in Vite and theming loading twice - [#25925](https://github.com/storybookjs/storybook/pull/25925), thanks [@JReinhold](https://github.com/JReinhold)!\n- Core: Fix React peer dependency warnings - [#25926](https://github.com/storybookjs/storybook/pull/25926), thanks [@JReinhold](https://github.com/JReinhold)!\n- Core: Remove CSF batching, as it isn't required any more - [#25872](https://github.com/storybookjs/storybook/pull/25872), thanks [@tmeasday](https://github.com/tmeasday)!\n- Fix: Add Visual Test Addon to init command - [#25883](https://github.com/storybookjs/storybook/pull/25883), thanks [@vanessayuenn](https://github.com/vanessayuenn)!\n- Next.js: Fix frameworkOptions resolution - [#25907](https://github.com/storybookjs/storybook/pull/25907), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!\n- React Native: Fix init fails when package is already installed - [#25908](https://github.com/storybookjs/storybook/pull/25908), thanks [@dannyhw](https://github.com/dannyhw)!\n- React Native: Remove watcher from init - [#25895](https://github.com/storybookjs/storybook/pull/25895), thanks [@dannyhw](https://github.com/dannyhw)!\n- Test: Fix jest-dom matcher type imports - [#25869](https://github.com/storybookjs/storybook/pull/25869), thanks [@alitas](https://github.com/alitas)!\n- UI: Fix overlapping on the ref button in the sidebar - [#25914](https://github.com/storybookjs/storybook/pull/25914), thanks [@cdedreuille](https://github.com/cdedreuille)!\n- UI: Remove keyboard shortcut hint in search bar on mobile viewports - [#25866](https://github.com/storybookjs/storybook/pull/25866), thanks [@tusharwebd](https://github.com/tusharwebd)!"}} diff --git a/docs/writing-tests/accessibility-testing.md b/docs/writing-tests/accessibility-testing.md index 7151a43e8b73..8c29a2a2c6b5 100644 --- a/docs/writing-tests/accessibility-testing.md +++ b/docs/writing-tests/accessibility-testing.md @@ -252,7 +252,7 @@ Additionally, if you have already [disabled accessibility](#how-to-disable-a11y- Browser-based accessibility tests, like those found in Storybook, evaluate the rendered DOM because that gives you the highest accuracy. Auditing code that hasn't been compiled yet is one step removed from the real thing, so you won't catch everything the user might experience. -#### Learn about other UI tests +**Learn about other UI tests** - [Test runner](./test-runner.md) to automate test execution - [Visual tests](./visual-testing.md) for appearance diff --git a/docs/writing-tests/chromatic-first-build-optimized.png b/docs/writing-tests/chromatic-first-build-optimized.png deleted file mode 100644 index a325b18fd148..000000000000 Binary files a/docs/writing-tests/chromatic-first-build-optimized.png and /dev/null differ diff --git a/docs/writing-tests/chromatic-second-build-optimized.png b/docs/writing-tests/chromatic-second-build-optimized.png deleted file mode 100644 index c751c0547c13..000000000000 Binary files a/docs/writing-tests/chromatic-second-build-optimized.png and /dev/null differ diff --git a/docs/writing-tests/component-visual-testing-optimized.mp4 b/docs/writing-tests/component-visual-testing-optimized.mp4 index 0f5491b70550..34ce04dd0962 100644 Binary files a/docs/writing-tests/component-visual-testing-optimized.mp4 and b/docs/writing-tests/component-visual-testing-optimized.mp4 differ diff --git a/docs/writing-tests/interaction-testing.md b/docs/writing-tests/interaction-testing.md index 4cc94872b15f..b949aa284a8a 100644 --- a/docs/writing-tests/interaction-testing.md +++ b/docs/writing-tests/interaction-testing.md @@ -224,7 +224,7 @@ Interaction tests can be expensive to maintain when applied wholesale to every c Interaction tests integrate Jest and Testing Library into Storybook. The biggest benefit is the ability to view the component you're testing in a real browser. That helps you debug visually, instead of getting a dump of the (fake) DOM in the command line or hitting the limitations of how JSDOM mocks browser functionality. It's also more convenient to keep stories and tests together in one file than having them spread across files. -#### Learn about other UI tests +**Learn about other UI tests** - [Test runner](./test-runner.md) to automate test execution - [Visual tests](./visual-testing.md) for appearance diff --git a/docs/writing-tests/stories-in-unit-tests.md b/docs/writing-tests/stories-in-unit-tests.md index 146bae494833..0b7989bf0d12 100644 --- a/docs/writing-tests/stories-in-unit-tests.md +++ b/docs/writing-tests/stories-in-unit-tests.md @@ -182,7 +182,7 @@ When using the `composeStories` or `composeStory` functions, the components bein -#### Learn about other UI tests +**Learn about other UI tests** - [Test runner](./test-runner.md) to automate test execution - [Visual tests](./visual-testing.md) for appearance diff --git a/docs/writing-tests/test-coverage.md b/docs/writing-tests/test-coverage.md index de8b5e3cbf20..07dd1d17bcfe 100644 --- a/docs/writing-tests/test-coverage.md +++ b/docs/writing-tests/test-coverage.md @@ -193,7 +193,7 @@ If you generated a production build optimized for performance with the [`--test` As the [coverage addon](https://storybook.js.org/addons/@storybook/addon-coverage) is based on Webpack5 loaders and Vite plugins for code instrumentation, frameworks that don't rely upon these libraries (e.g., Angular configured with Webpack), will require additional configuration to enable code instrumentation. In that case, you can refer to the following [repository](https://github.com/yannbf/storybook-coverage-recipes) for more information. -#### Learn about other UI tests +**Learn about other UI tests** - [Test runner](./test-runner.md) to automate test execution - [Visual tests](./visual-testing.md) for appearance diff --git a/docs/writing-tests/test-runner.md b/docs/writing-tests/test-runner.md index 9bd1a8f5f0d8..d83ae2af1143 100644 --- a/docs/writing-tests/test-runner.md +++ b/docs/writing-tests/test-runner.md @@ -465,7 +465,7 @@ As the test runner is based on Playwright, you might need to use specific docker If you've enabled filtering tests with tags and provided similar tags to the `include` and `exclude` lists, the test-runner will execute the tests based on the `exclude` list and ignore the `include` list. To avoid this, make sure the tags provided to the `include` and `exclude` lists differ. -#### Learn about other UI tests +**Learn about other UI tests** - Test runner to automate test execution - [Visual tests](./visual-testing.md) for appearance diff --git a/docs/writing-tests/visual-testing.md b/docs/writing-tests/visual-testing.md index c4e2f66f68ac..a848ada9eb60 100644 --- a/docs/writing-tests/visual-testing.md +++ b/docs/writing-tests/visual-testing.md @@ -1,10 +1,11 @@ --- -title: 'Visual tests' +title: Visual tests +hideRendererSelector: true --- -Visual tests, also called visual regression tests, catch bugs in UI appearance. They work by taking screenshots of every story and comparing them commit-to-commit to identify changes. +Visual tests catch bugs in UI appearance. They work by taking screenshots of every story and comparing them to previous versions to identify visual changes. This is ideal for verifying layout, color, size, contrast, and any other visual aspect of your UI. -Ideal for verifying what the user sees: layout, color, size, and contrast. Storybook is a fantastic tool for visual testing because every story is essentially a test specification. Any time you write or update a story, you get a spec for free. +Storybook supports cross-browser visual testing natively using [Chromatic](https://www.chromatic.com/storybook/?ref=storybook_site), a cloud service made by the Storybook team. When you enable visual testing, every story is automatically turned into a test. This gives you instant feedback on UI bugs directly in Storybook. -There are [many tools](https://github.com/mojoaxel/awesome-regression-testing) for visual testing. We recommend [Chromatic](https://www.chromatic.com?utm_source=storybook_website&utm_medium=link&utm_campaign=storybook) by Storybook maintainers to run visual tests in a lightning-fast cloud browser environment. +### Install the addon -For a self-managed alternative to Chromatic, we offer [test runner](./test-runner.md). It allows you to run visual tests on stories by integrating with [Jest](https://jestjs.io/) and [Playwright](https://playwright.dev/). Here's an example [recipe for visual testing stories](https://github.com/storybookjs/test-runner#image-snapshot-recipe). - -## Setup Chromatic addon - -Chromatic is a cloud service built for Storybook. It allows you to run visual tests with zero-config. - -To get started, sign up with your [GitHub](https://github.com/), [GitLab](https://about.gitlab.com/), [Bitbucket](https://bitbucket.org/), or email and generate a unique `` for your Storybook. - -Next, install the [chromatic](https://www.npmjs.com/package/chromatic) CLI package from npm: +Add visual tests to your project by installing `@chromatic-com/storybook`, the official addon by Storybook maintainers: -Run the following command after the package finishes installing: + -```shell -npx chromatic --project-token -``` +Storybook 7.4 or higher is required. Read the [migration guide](../migration-guide.md) to upgrade your project. - - - Don't forget to replace `your-project-token` with the one provided by Chromatic. - -```shell -Build 1 published. +### Enable visual tests + +When you start Storybook, you'll see a new addon panel for Visual Tests where you can run tests and view results. + +![Visual Tests addon enabled](./vta-enable.png) + +To enable visual testing, sign up for [Chromatic](https://www.chromatic.com/start?startWithSignup=true&ref=storybook_site) and create a project. This will give you access to a fleet of cloud browsers. + +![Visual Tests addon project selection](./vta-select-project.png) + +Select a project from your project list to finish setup. If you're setting up the addon for the first time, the configuration files and necessary project identifiers will be added for you automatically. + +### Configure -View it online at https://www.chromatic.com/build?appId=...&number=1. +The addon includes configuration options covering most use cases by default. You can also fine-tune the addon configuration to match your project's requirements via the [`./chromatic.config.json`](https://www.chromatic.com/docs/cli#configuration) file. Below are the available options and examples of how to use them. + +| Option | Description | +| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| `projectId` | Automatically configured. Sets the value for the project identifier
`options: { projectId: 'Project:64cbcde96f99841e8b007d75' }` | +| `buildScriptName` | Optional. Defines the custom Storybook build script
`options: { buildScriptName: 'deploy-storybook' }` | +| `debug` | Optional. Output verbose debugging information to the console.
`options: { debug: true }` | +| `zip` | Optional. Recommended for large projects. Configures the addon to deploy your Storybook to Chromatic as a zip file.
`options: { zip: true }` | + +```jsonc +// .storybook/chromatic.config.json +{ + "buildScriptName": "deploy-storybook", + "debug": true, + "projectId": "Project:64cbcde96f99841e8b007d75", + "zip": true +} ``` - +### Run visual tests -Before running Chromatic's CLI ensure you have at least two commits added to the repository to prevent build failures, as Chromatic relies on a full Git history graph to establish the baselines. Read more about baselines in Chromatic's [documentation](https://www.chromatic.com/docs/branching-and-baselines?utm_source=storybook_website&utm_medium=link&utm_campaign=storybook). +Click the ▶️ Play button in the Storybook sidebar to run visual tests. This will send your stories to the cloud to take snapshots and detect visual changes. - +![Storybook running visual tests with the addon](./vta-run-tests.png) + +### Review changes + +If there are visual changes in your stories, they will be 🟡 highlighted in the sidebar. Click the story and go to the Visual Tests addon panel to see which pixels changed. + +If the changes are intentional, ✅ accept them as baselines locally. If the changes aren't intentional, fix the story and rerun the tests using the ▶️ Play button. -When Chromatic finishes, it should have successfully deployed your Storybook and established the baselines, that is to say, the starting point for all your component's stories. Additionally, providing you with a link to the published Storybook that you can share with your team to gather feedback. +![Confirm UI changes in Storybook](./vta-changes-found.png) -![Chromatic project first build](./chromatic-first-build-optimized.png) +When you finish accepting changes as baselines in the addon, you're ready to push the code to your remote repository. This will sync baselines to the cloud for anyone who checks out your branch. -## Catching UI changes +![Accept UI changes in Storybook](./vta-changes-accepted.png) -Each time you run Chromatic, it will generate new snapshots and compare them against the existing baselines. That’s ideal for detecting UI changes and preventing potential UI regressions. +### Automate with CI -For example, let's assume you're working on a component and you tweak the styling. When Chromatic is re-run, it will highlight the difference between the baseline and the updated component. +The addon is designed to be used in tandem with CI. We recommend using the addon to check for changes during development and then running visual tests in CI as you get ready to merge. -![Chromatic project second build](./chromatic-second-build-optimized.png) +Changes you accept as baselines in the addon will get auto-accepted as baselines in CI so you don’t have to review twice. -If the changes are intentional, accept them as baselines. Otherwise, deny them to prevent UI regressions. +1. Add a step to your CI workflow to run Chromatic. -Learn how to [integrate Chromatic UI Tests](https://www.chromatic.com/docs/?utm_source=storybook_website&utm_medium=link&utm_campaign=storybook) into your CI pipeline. + - [GitHub Actions](https://chromatic.com/docs/github-actions?ref=storybook_docs) + - [GitLab Pipelines](https://chromatic.com/docs/gitlab?ref=storybook_docs) + - [Bitbucket Pipelines](https://chromatic.com/docs/bitbucket-pipelines?ref=storybook_docs) + - [CircleCI](https://chromatic.com/docs/circleci?ref=storybook_docs) + - [Travis CI](https://chromatic.com/docs/travisci?ref=storybook_docs) + - [Jenkins](https://chromatic.com/docs/jenkins?ref=storybook_docs) + - [Azure Pipelines](https://chromatic.com/docs/azure-pipelines?ref=storybook_docs) + - [Custom CI provider](https://chromatic.com/docs/custom-ci-provider?ref=storybook_docs) + +2. Configure your CI to include environment variables to authenticate with Chromatic (project token). + +#### PR checks + +Once you successfully set up Chromatic in CI, your pull/merge requests will be badged with a UI Tests check. The badge notifies you of test errors or UI changes that need to be verified by your team. Make the check required in your Git provider to prevent accidental UI bugs from being merged. + +![PR badge for visual tests](./vta-prbadge-test.png) --- -#### What’s the difference between visual tests and snapshot tests? +### What’s the difference between visual tests and snapshot tests? + +[Snapshot tests](./snapshot-testing.md) compare the rendered markup of every story against known baselines. This means the test compares blobs of HTML and not what the user actually sees. Which in turn, can lead to an increase in false positives as code changes don’t always yield visual changes in the component. -Snapshot tests compare the rendered markup of every story against known baselines. This means the test compares blobs of HTML and not what the user actually sees. Which in turn, can lead to an increase in false positives as code changes don’t always yield visual changes in the component. +Visual tests compare the rendered pixels of every story against known baselines. Because you're testing the same thing your users actually experience, your tests will be richer and easier to maintain. -#### Learn about other UI tests +**Learn about other UI tests** - [Test runner](./test-runner.md) to automate test execution - Visual tests for appearance diff --git a/docs/writing-tests/vta-changes-accepted.png b/docs/writing-tests/vta-changes-accepted.png new file mode 100644 index 000000000000..543ed220c5a8 Binary files /dev/null and b/docs/writing-tests/vta-changes-accepted.png differ diff --git a/docs/writing-tests/vta-changes-found.png b/docs/writing-tests/vta-changes-found.png new file mode 100644 index 000000000000..9f9785b59baf Binary files /dev/null and b/docs/writing-tests/vta-changes-found.png differ diff --git a/docs/writing-tests/vta-enable.png b/docs/writing-tests/vta-enable.png new file mode 100644 index 000000000000..cbac2eea2b80 Binary files /dev/null and b/docs/writing-tests/vta-enable.png differ diff --git a/docs/writing-tests/vta-prbadge-test.png b/docs/writing-tests/vta-prbadge-test.png new file mode 100644 index 000000000000..ed87813a2f96 Binary files /dev/null and b/docs/writing-tests/vta-prbadge-test.png differ diff --git a/docs/writing-tests/vta-run-tests.png b/docs/writing-tests/vta-run-tests.png new file mode 100644 index 000000000000..f44f98dd6b29 Binary files /dev/null and b/docs/writing-tests/vta-run-tests.png differ diff --git a/docs/writing-tests/vta-select-project.png b/docs/writing-tests/vta-select-project.png new file mode 100644 index 000000000000..182a50baea9c Binary files /dev/null and b/docs/writing-tests/vta-select-project.png differ diff --git a/scripts/package.json b/scripts/package.json index da6aa2f41c2c..1d150aca19df 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -149,8 +149,8 @@ "ora": "^5.4.1", "p-limit": "^3.1.0", "p-retry": "^5.1.2", - "playwright": "1.41.1", - "playwright-core": "1.41.1", + "playwright": "1.36.0", + "playwright-core": "1.36.0", "prettier": "^3.1.1", "pretty-bytes": "^6.1.0", "pretty-hrtime": "^1.0.0", diff --git a/scripts/utils/yarn.ts b/scripts/utils/yarn.ts index 919e380f119c..a2fb82e1fa6a 100644 --- a/scripts/utils/yarn.ts +++ b/scripts/utils/yarn.ts @@ -25,9 +25,9 @@ export const addPackageResolutions = async ({ cwd, dryRun }: YarnOptions) => { ...storybookVersions, 'enhanced-resolve': '~5.10.0', // TODO, remove this // this is for our CI test, ensure we use the same version as docker image, it should match version specified in `./code/package.json` and `.circleci/config.yml` - playwright: '1.41.1', - 'playwright-core': '1.41.1', - '@playwright/test': '1.41.1', + playwright: '1.36.0', + 'playwright-core': '1.36.0', + '@playwright/test': '1.36.0', }; await writeJSON(packageJsonPath, packageJson, { spaces: 2 }); }; diff --git a/scripts/yarn.lock b/scripts/yarn.lock index 22f0f9ce9da2..f846c07ffb0e 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -2789,8 +2789,8 @@ __metadata: ora: "npm:^5.4.1" p-limit: "npm:^3.1.0" p-retry: "npm:^5.1.2" - playwright: "npm:1.41.1" - playwright-core: "npm:1.41.1" + playwright: "npm:1.36.0" + playwright-core: "npm:1.36.0" prettier: "npm:^3.1.1" pretty-bytes: "npm:^6.1.0" pretty-hrtime: "npm:^1.0.0" @@ -7672,16 +7672,6 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:2.3.2": - version: 2.3.2 - resolution: "fsevents@npm:2.3.2" - dependencies: - node-gyp: "npm:latest" - checksum: be78a3efa3e181cda3cf7a4637cb527bcebb0bd0ea0440105a3bb45b86f9245b307dc10a2507e8f4498a7d4ec349d1910f4d73e4d4495b16103106e07eee735b - conditions: os=darwin - languageName: node - linkType: hard - "fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": version: 2.3.3 resolution: "fsevents@npm:2.3.3" @@ -7692,15 +7682,6 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin": - version: 2.3.2 - resolution: "fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin::version=2.3.2&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin - languageName: node - linkType: hard - "fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" @@ -12258,27 +12239,23 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.41.1": - version: 1.41.1 - resolution: "playwright-core@npm:1.41.1" +"playwright-core@npm:1.36.0": + version: 1.36.0 + resolution: "playwright-core@npm:1.36.0" bin: playwright-core: cli.js - checksum: cdd91267ca23e3f65d519100e956859c70e3e9ca29e3fe00e700b457903129e41dfa17752f1ea37ad0a8a7c6330baf9f3be503e4cbfa3e8833e80a037f899aee + checksum: 5b5d32495e222ddd4351d1d8b116a25a7d93ea5f3439dceaceeb916d0abdce6d5b0b84f80df0b239168d55a100e7aecc9db4774ff20ba0210d8de027f258b544 languageName: node linkType: hard -"playwright@npm:1.41.1": - version: 1.41.1 - resolution: "playwright@npm:1.41.1" +"playwright@npm:1.36.0": + version: 1.36.0 + resolution: "playwright@npm:1.36.0" dependencies: - fsevents: "npm:2.3.2" - playwright-core: "npm:1.41.1" - dependenciesMeta: - fsevents: - optional: true + playwright-core: "npm:1.36.0" bin: playwright: cli.js - checksum: 32d48c1f8ff881770a19c9245fb4191fc36b5e97ab5f48effa0b1cf5e83fa958f6fdd7e4268dd984aa306ac5fe9e4324510211910751fb52cebb9bae819d13ca + checksum: dc39eb6271b22901cb6219a8ecdd44736169edd789d2a8be5885ded5414ee2a9e2c73a19e24d55336ddbae6f9d69522b46f1fe92998740745f1cb78d58b6cb6e languageName: node linkType: hard