diff --git a/.circleci/config.yml b/.circleci/config.yml index ffe339dcda97..550dc9e6b994 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -165,17 +165,15 @@ jobs: root: . paths: - code/node_modules + - code/addons - scripts/node_modules - code/bench - code/examples - - code/node_modules - - code/addons - code/frameworks - code/deprecated - code/lib - code/core - code/builders - - code/ui - code/renderers - code/presets - .verdaccio-cache @@ -211,23 +209,88 @@ jobs: yarn knip --no-exit-code - report-workflow-on-failure - cancel-workflow-on-failure - check: + bench-packages: executor: - class: xlarge + class: medium name: sb_node_22_classic steps: - git-shallow-clone/checkout_advanced: clone_options: "--depth 1 --verbose" - attach_workspace: at: . + # if there is a base branch AND a PR number in parameters, benchmark packages against those + # this happens when run against a PR + - when: + condition: + and: + - << pipeline.parameters.ghBaseBranch >> + - << pipeline.parameters.ghPrNumber >> + steps: + - run: + name: Benchmarking packages against base branch + working_directory: scripts + command: | + yarn local-registry --open & + until curl -s http://localhost:6001 > /dev/null; do + echo 'Waiting for local registry to be available...' + sleep 2 + done + yarn bench-packages --base-branch << pipeline.parameters.ghBaseBranch >> --pull-request << pipeline.parameters.ghPrNumber >> --upload + # if there is a NOT a base branch OR NOT a PR number in parameters, just upload benchmarks for the branch + # this happens when runned directly on branches, like next or main + - when: + condition: + or: + - not: << pipeline.parameters.ghBaseBranch >> + - not: << pipeline.parameters.ghPrNumber >> + steps: + - run: + name: Uploading package benchmarks for branch + working_directory: scripts + command: | + yarn local-registry --open & + until curl -s http://localhost:6001 > /dev/null; do + echo 'Waiting for local registry to be available...' + sleep 2 + done + yarn bench-packages --upload + - store_artifacts: + path: bench/packages/results.json + - store_artifacts: + path: bench/packages/compare-with-<< pipeline.parameters.ghBaseBranch >>.json + - report-workflow-on-failure + - cancel-workflow-on-failure + check: + executor: + class: xlarge + name: sb_node_22_classic + steps: + - git-shallow-clone/checkout_advanced: + clone_options: "--depth 1 --verbose" - nx/set-shas: main-branch-name: "next" workflow-name: << pipeline.parameters.workflow >> + - run: + name: install in scripts + command: | + cd scripts + yarn install + - run: + name: install in code + command: | + cd code + yarn install + - run: + name: Compile + command: | + yarn task --task compile --start-from=compile --no-link --debug - run: name: Check command: | - yarn task --task compile --start-from=auto --no-link --debug - yarn task --task check --start-from=auto --no-link --debug + yarn task --task check --start-from=check --no-link --debug + - run: + name: Ensure no changes pending + command: | git diff --exit-code - report-workflow-on-failure - cancel-workflow-on-failure @@ -543,7 +606,7 @@ jobs: - store_artifacts: # this is where playwright puts more complex stuff path: code/playwright-results/ destination: playwright - bench: + bench-sandboxes: parameters: parallelism: type: integer @@ -753,9 +816,10 @@ workflows: - knip: requires: - build - - check: + - bench-packages: requires: - build + - check - unit-tests: requires: - build @@ -799,7 +863,7 @@ workflows: parallelism: 5 requires: - create-sandboxes - - bench: + - bench-sandboxes: parallelism: 5 requires: - build-sandboxes @@ -828,9 +892,10 @@ workflows: - knip: requires: - build - - check: + - bench-packages: requires: - build + - check - unit-tests: requires: - build @@ -883,7 +948,7 @@ workflows: - test-ui-testing-module: requires: - build - - bench: + - bench-sandboxes: parallelism: 5 requires: - build-sandboxes @@ -904,9 +969,10 @@ workflows: - knip: requires: - build - - check: + - bench-packages: requires: - build + - check - unit-tests: requires: - build @@ -977,7 +1043,7 @@ workflows: # --smoke-test is not supported for the angular builder right now # - "angular-cli" - "lit-vite-ts" - - bench: + - bench-sandboxes: parallelism: 5 requires: - build-sandboxes diff --git a/CHANGELOG.md b/CHANGELOG.md index 06520612a48a..e836b81e7ad8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## 8.4.5 + +- Angular: Support v19 - [#29659](https://github.com/storybookjs/storybook/pull/29659), thanks @leosvelperez! +- CLI: Disable corepack auto pin behavior - [#29627](https://github.com/storybookjs/storybook/pull/29627), thanks @yannbf! +- CLI: Fix qwik init - [#29632](https://github.com/storybookjs/storybook/pull/29632), thanks @shilman! +- Nextjs-Vite: Add Next.js 15 support - [#29640](https://github.com/storybookjs/storybook/pull/29640), thanks @yannbf! + +## 8.4.4 + +- Addon Test: Only optimize react deps if applicable in vitest-plugin - [#29617](https://github.com/storybookjs/storybook/pull/29617), thanks @yannbf! + +## 8.4.3 + +- Addon Test: Optimize internal dependencies - [#29595](https://github.com/storybookjs/storybook/pull/29595), thanks @yannbf! +- Next.js: Add support for Next 15 - [#29587](https://github.com/storybookjs/storybook/pull/29587), thanks @yannbf! + ## 8.4.2 - Addon Test: Fix post-install logic for Next.js Vite framework support - [#29524](https://github.com/storybookjs/storybook/pull/29524), thanks @valentinpalkovic! diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index 597322a9ce2a..a1c1ca62d0a3 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,40 @@ +## 8.5.0-alpha.10 + +- Addon Test: Use pathe for better windows support - [#29676](https://github.com/storybookjs/storybook/pull/29676), thanks @yannbf! +- Angular: Default to standalone components in Angular v19 - [#29677](https://github.com/storybookjs/storybook/pull/29677), thanks @ingowagner! + +## 8.5.0-alpha.9 + +- Angular: Support v19 - [#29659](https://github.com/storybookjs/storybook/pull/29659), thanks @leosvelperez! +- Manager: Fix size regression - [#29660](https://github.com/storybookjs/storybook/pull/29660), thanks @JReinhold! +- Nextjs-Vite: Add Next.js 15 support - [#29640](https://github.com/storybookjs/storybook/pull/29640), thanks @yannbf! + +## 8.5.0-alpha.8 + +- UI: Sidebar context menu addon API - [#29557](https://github.com/storybookjs/storybook/pull/29557), thanks @ndelangen! + +## 8.5.0-alpha.7 + +- CLI: Disable corepack auto pin behavior - [#29627](https://github.com/storybookjs/storybook/pull/29627), thanks @yannbf! +- RNW-Vite: Integrate with experimental-addon-test - [#29645](https://github.com/storybookjs/storybook/pull/29645), thanks @shilman! + +## 8.5.0-alpha.6 + +- CLI: Fix qwik init - [#29632](https://github.com/storybookjs/storybook/pull/29632), thanks @shilman! +- React Native Web: Add framework, CLI integration, sandboxes - [#29520](https://github.com/storybookjs/storybook/pull/29520), thanks @shilman! + +## 8.5.0-alpha.5 + +- Addon Test: Only optimize react deps if applicable in vitest-plugin - [#29617](https://github.com/storybookjs/storybook/pull/29617), thanks @yannbf! +- Addon Test: Optimize internal dependencies - [#29595](https://github.com/storybookjs/storybook/pull/29595), thanks @yannbf! +- CLI: Fix init help for `storybook` command - [#29480](https://github.com/storybookjs/storybook/pull/29480), thanks @toothlessdev! +- Composition: Fix composed story search - [#29453](https://github.com/storybookjs/storybook/pull/29453), thanks @jsingh0026! + +## 8.5.0-alpha.4 + +- Next.js: Add support for Next 15 - [#29587](https://github.com/storybookjs/storybook/pull/29587), thanks @yannbf! +- UI: Add Yarn to About Section - [#29225](https://github.com/storybookjs/storybook/pull/29225), thanks @grantwforsythe! + ## 8.5.0-alpha.3 - Addon Test: Fix post-install logic for Next.js Vite framework support - [#29524](https://github.com/storybookjs/storybook/pull/29524), thanks @valentinpalkovic! diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f65401dd4a8..6d2f04d9e253 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,6 +5,7 @@ Storybook is developed against a specific node version which is defined in an `. ## Ensure you have the required system utilities You will need to have the following installed: + - git - node - yarn @@ -20,7 +21,7 @@ You will need to have the following installed: ## Running the local development environment -- Ensure if you are using Windows to use the Windows Subsystem for Linux (WSL). +- All commands should be run in a terminal with administrator privileges in Windows environments. - Run `yarn start` in the root directory to run a basic test Storybook "sandbox". The `yarn start` script will generate a React Vite TypeScript sandbox with a set of test stories inside it, as well as taking all steps required to get it running (building the various packages we need etc). There is no need to run `yarn` or `yarn install` as `yarn start` will do this for you. diff --git a/CONTRIBUTING/RELEASING.md b/CONTRIBUTING/RELEASING.md index afc1bc377451..33a74bfdc224 100644 --- a/CONTRIBUTING/RELEASING.md +++ b/CONTRIBUTING/RELEASING.md @@ -19,6 +19,7 @@ - [5. Make Manual Changes](#5-make-manual-changes) - [6. Merge](#6-merge) - [7. See the "Publish" Workflow Finish](#7-see-the-publish-workflow-finish) +- [Releasing changes to older minor versions](#releasing-changes-to-older-minor-versions) - [Releasing Locally in an Emergency 🚨](#releasing-locally-in-an-emergency-) - [Canary Releases](#canary-releases) - [With GitHub UI](#with-github-ui) @@ -330,6 +331,59 @@ Merging the pull request will trigger [the publish workflow](https://github.com/ Done! 🚀 +## Releasing changes to older minor versions + +If you need to release a change to an older minor version that is not the latest, you have to do it manually, locally. The process is described below, with an example of releasing a new `v8.3.7` in a situation where `8.4.0` is currently the latest version. + +1. Checkout the _existing_ tag that matches the latest minor release you want to bump, and create a new branch from it. In this case, we want to do: + 1. `git fetch --all --tags` + 2. `git checkout tags/v8.3.6 -b patch-8-3-7` +2. Make the changes you need to, most likely cherry-picking commits from the fix you need to back-port. +3. Run `yarn install` in `scripts` and `code` +4. Build all packages in `code` with `yarn task --task compile --no-link` +5. Commit and push your changes. +6. Trigger _daily_ CI manually on your branch: + 1. Open [CircleCI](https://app.circleci.com/pipelines/github/storybookjs/storybook) and click "Trigger Pipeline" on the top right corner of the page. + 2. Set the following configuration options: + - Pipeline: _"storybook default"_ + - Config Source: _"storybook"_ + - Branch: Your branch, eg. `patch-8-3-7` + 3. Add a parameter, with _"name"_ `workflow`, _"value"_ `daily` +7. Wait for CI to finish successfully. +8. Bump all package versions: + 1. `cd scripts` + 2. `yarn release:version --release-type patch` +9. Commit with `git commit -m "Bump version from to MANUALLY"` +10. Add a new entry to `CHANGELOG.md`, describing your changes +11. Commit with `git commit -m "Update CHANGELOG.md with MANUALLY"` +12. Ensure you have the correct write permissions for all the Storybook npm packages. You need to be an admin of the _storybook_ org, and the packages that are not in the org. The simplest way to check this is to ensure you can see the _"Settings"_ tab in the following packages: + 1. [`@storybook/react-vite`](https://www.npmjs.com/package/@storybook/react-vite/access) + 2. [`storybook`](https://www.npmjs.com/package/storybook/access) + 3. [`sb`](https://www.npmjs.com/package/sb/access) + 4. [`create-storybook`](https://www.npmjs.com/package/create-storybook/access) +13. Get your npm access token or generate a new one at https://www.npmjs.com/settings/your-username/tokens. Remember to give it access to the `storybook` org and the packages not in the org, as listed above. +14. Publish all packages with `YARN_NPM_AUTH_TOKEN= yarn release:publish --tag tag-for-publishing-older-releases --verbose` + - It goes through all packages and publishes them. If any number of packages fails to publish, it will retry 5 times, skipping those that have already been published. +15. Confirm the new version has been released on npm with the tag `tag-for-publishing-older-releases`: + 1. [`@storybook/react-vite`](https://www.npmjs.com/package/@storybook/react-vite?activeTab=versions) + 2. [`storybook`](https://www.npmjs.com/package/storybook?activeTab=versions) + 3. [`sb`](https://www.npmjs.com/package/sb?activeTab=versions) + 4. [`create-storybook`](https://www.npmjs.com/package/create-storybook?activeTab=versions) +16. Push +17. Manually create a GitHub Release at https://github.com/storybookjs/storybook/releases/new with: + 1. Create new tag: `v` (e.g., `v8.3.7`) + 2. Target: your branch (e.g., `patch-8-3-7`) + 3. Previous tag: `v` (e.g., `v8.3.6`) + 4. Title: `v` (e.g., `v8.3.7`) + 5. Description: The content you added to `CHANGELOG.md` + 6. Untick _"Set as the latest release"_ +18. Cherry-pick your changelog changes into `next`, so they are actually visible + 1. Checkout the `next` branch + 2. Cherry-pick the commit you created with your changelog modifications + 3. Push + +Done. 🎉 + ## Releasing Locally in an Emergency 🚨 Things can fail, code can break, and bugs can exist. When automation is broken, there may be a need for an emergency escape hatch to release new fixes. In such a situation, it's valid to run the whole release process locally instead of relying on pull requests and workflows. You don't need to create pull requests or split preparation and publishing; you can do it all at once, but make sure you still follow the correct branching strategy. diff --git a/MIGRATION.md b/MIGRATION.md index d63cd568816f..2e2e735fb21f 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -105,17 +105,17 @@ - [Tab addons cannot manually route, Tool addons can filter their visibility via tabId](#tab-addons-cannot-manually-route-tool-addons-can-filter-their-visibility-via-tabid) - [Removed `config` preset](#removed-config-preset-1) - [From version 7.5.0 to 7.6.0](#from-version-750-to-760) - - [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated) - - [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated) - - [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated) - - [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop) - - [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react) + - [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated) + - [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated) + - [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated) + - [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop) + - [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react) - [From version 7.4.0 to 7.5.0](#from-version-740-to-750) - - [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated) - - [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers) + - [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated) + - [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers) - [From version 7.0.0 to 7.2.0](#from-version-700-to-720) - - [Addon API is more type-strict](#addon-api-is-more-type-strict) - - [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated) + - [Addon API is more type-strict](#addon-api-is-more-type-strict) + - [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated) - [From version 6.5.x to 7.0.0](#from-version-65x-to-700) - [7.0 breaking changes](#70-breaking-changes) - [Dropped support for Node 15 and below](#dropped-support-for-node-15-and-below) @@ -141,7 +141,7 @@ - [Deploying build artifacts](#deploying-build-artifacts) - [Dropped support for file URLs](#dropped-support-for-file-urls) - [Serving with nginx](#serving-with-nginx) - - [Ignore story files from node\_modules](#ignore-story-files-from-node_modules) + - [Ignore story files from node_modules](#ignore-story-files-from-node_modules) - [7.0 Core changes](#70-core-changes) - [7.0 feature flags removed](#70-feature-flags-removed) - [Story context is prepared before for supporting fine grained updates](#story-context-is-prepared-before-for-supporting-fine-grained-updates) @@ -155,7 +155,7 @@ - [Addon-interactions: Interactions debugger is now default](#addon-interactions-interactions-debugger-is-now-default) - [7.0 Vite changes](#70-vite-changes) - [Vite builder uses Vite config automatically](#vite-builder-uses-vite-config-automatically) - - [Vite cache moved to node\_modules/.cache/.vite-storybook](#vite-cache-moved-to-node_modulescachevite-storybook) + - [Vite cache moved to node_modules/.cache/.vite-storybook](#vite-cache-moved-to-node_modulescachevite-storybook) - [7.0 Webpack changes](#70-webpack-changes) - [Webpack4 support discontinued](#webpack4-support-discontinued) - [Babel mode v7 exclusively](#babel-mode-v7-exclusively) @@ -167,6 +167,7 @@ - [Angular: Drop support for calling Storybook directly](#angular-drop-support-for-calling-storybook-directly) - [Angular: Application providers and ModuleWithProviders](#angular-application-providers-and-modulewithproviders) - [Angular: Removed legacy renderer](#angular-removed-legacy-renderer) + - [Angular: initializer functions](#angular-initializer-functions) - [Next.js: use the `@storybook/nextjs` framework](#nextjs-use-the-storybooknextjs-framework) - [SvelteKit: needs the `@storybook/sveltekit` framework](#sveltekit-needs-the-storybooksveltekit-framework) - [Vue3: replaced app export with setup](#vue3-replaced-app-export-with-setup) @@ -205,7 +206,7 @@ - [Dropped addon-docs manual babel configuration](#dropped-addon-docs-manual-babel-configuration) - [Dropped addon-docs manual configuration](#dropped-addon-docs-manual-configuration) - [Autoplay in docs](#autoplay-in-docs) - - [Removed STORYBOOK\_REACT\_CLASSES global](#removed-storybook_react_classes-global) + - [Removed STORYBOOK_REACT_CLASSES global](#removed-storybook_react_classes-global) - [7.0 Deprecations and default changes](#70-deprecations-and-default-changes) - [storyStoreV7 enabled by default](#storystorev7-enabled-by-default) - [`Story` type deprecated](#story-type-deprecated) @@ -430,7 +431,7 @@ These APIs allowed addons to render arbitrary content in the Storybook sidebar. > [!NOTE] > You need to set the feature flag `backgroundsStoryGlobals` to `true` in your `.storybook/main.ts` to use the new format and set the value with `globals`. -> +> > See here how to set feature flags: https://storybook.js.org/docs/api/main-config/main-config-features The `addon-backgrounds` addon now uses a new format for configuring its list of selectable backgrounds. @@ -476,7 +477,7 @@ This locks that story to the `twitter` background, it cannot be changed by the a > [!NOTE] > You need to set the feature flag `viewportStoryGlobals` to `true` in your `.storybook/main.ts` to use the new format and set the value with `globals`. -> +> > See here how to set feature flags: https://storybook.js.org/docs/api/main-config/main-config-features The `addon-viewport` addon now uses a new format for configuring its list of selectable viewports. @@ -2579,6 +2580,15 @@ Please visit https://angular.io/guide/standalone-components#configuring-dependen The `parameters.angularLegacyRendering` option is removed. You cannot use the old legacy renderer anymore. +#### Angular: Initializer functions + +Initializer functions using the `APP_INITIALIZER` dependency injection token only run when the component renders. To ensure an initializer function is always executed, you can adjust your `.storybook/preview.ts` and invoke it directly. + +```js +myCustomInitializer(); +export default preview; +``` + #### Next.js: use the `@storybook/nextjs` framework In Storybook 7.0 we introduced a convenient package that provides an out of the box experience for Next.js projects: `@storybook/nextjs`. Please see the [following resource](./code/frameworks/nextjs/README.md#getting-started) to get started with it. diff --git a/README.md b/README.md index 5a49d36e82d7..aea220e8b1d8 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Sponsors on Open Collective - + Official Twitter Handle @@ -68,8 +68,8 @@ Storybook is a frontend workshop for building UI components and pages in isolati - 👥 [Community](#community) - 👏 [Contributing](#contributing) - 👨‍💻 [Development scripts](#development-scripts) - - 💵 [Backers](#backers) - 💸 [Sponsors](#sponsors) + - 💵 [Backers](#backers) - :memo: [License](#license) ## Getting Started @@ -156,7 +156,7 @@ If you're looking for material to use in your Storybook presentation, such as lo ## Community -- Tweeting via [@storybookjs](https://twitter.com/storybookjs) +- Tweeting via [@storybookjs](https://x.com/storybookjs) - Blogging at [storybook.js.org](https://storybook.js.org/blog/) and [Medium](https://medium.com/storybookjs) - Chatting on [Discord](https://discord.gg/storybook) - Videos and streams at [YouTube](https://www.youtube.com/channel/UCr7Quur3eIyA_oe8FNYexfg) diff --git a/RESOLUTIONS.md b/RESOLUTIONS.md index 4e2a64960edd..c89dd7ff96d4 100644 --- a/RESOLUTIONS.md +++ b/RESOLUTIONS.md @@ -2,10 +2,6 @@ This file keeps track of any resolutions or exact versions specified in any `package.json` file. Resolutions are used to specify a specific version of a package to be used, even if a different version is specified as a dependency of another package. -## code/renderers/svelte/package.json +## path/to/package.json -svelte-check@3.4.6 (bug: 3.5.x): Type issues - -## code/ui/components/package.json - -overlayscrollbars@2.2.1 (bug: 2.3.x): The Scrollbar doesn't disappear anymore by default. It might has something to do with the `scrollbars.autoHideSuspend` option, which was introduced in 2.3.0. https://github.com/KingSora/OverlayScrollbars/blob/master/packages/overlayscrollbars/CHANGELOG.md#230 \ No newline at end of file +example-library@3.4.6 (bug: 3.5.x): Pinned as there is a bug in version 3.5.x that prevents foo from doing bar. diff --git a/code/.storybook/preview.tsx b/code/.storybook/preview.tsx index 60135ac5a8c5..fac0c9bdb2b1 100644 --- a/code/.storybook/preview.tsx +++ b/code/.storybook/preview.tsx @@ -117,8 +117,8 @@ const ThemedSetRoot = () => { }; // eslint-disable-next-line no-underscore-dangle -const preview = (window as any).__STORYBOOK_PREVIEW__ as PreviewWeb; -const channel = (window as any).__STORYBOOK_ADDONS_CHANNEL__ as Channel; +const preview = (window as any).__STORYBOOK_PREVIEW__ as PreviewWeb | undefined; +const channel = (window as any).__STORYBOOK_ADDONS_CHANNEL__ as Channel | undefined; export const loaders = [ /** * This loader adds a DocsContext to the story, which is required for the most Blocks to work. A @@ -133,9 +133,9 @@ export const loaders = [ * The DocsContext will then be added via the decorator below. */ async ({ parameters: { relativeCsfPaths, attached = true } }) => { - // TODO bring a better way to skip tests when running as part of the vitest plugin instead of __STORYBOOK_URL__ - // eslint-disable-next-line no-underscore-dangle - if (!relativeCsfPaths || (import.meta as any).env?.__STORYBOOK_URL__) { + // __STORYBOOK_PREVIEW__ and __STORYBOOK_ADDONS_CHANNEL__ is set in the PreviewWeb constructor + // which isn't loaded in portable stories/vitest + if (!relativeCsfPaths || !preview || !channel) { return {}; } const csfFiles = await Promise.all( diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json index 750e10416ed8..32beb83cb2b6 100644 --- a/code/addons/a11y/package.json +++ b/code/addons/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-a11y", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Test component compliance with web accessibility standards", "keywords": [ "a11y", diff --git a/code/addons/actions/package.json b/code/addons/actions/package.json index d8e3c09e3677..83ed23a68904 100644 --- a/code/addons/actions/package.json +++ b/code/addons/actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-actions", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Get UI feedback when an action is performed on an interactive element", "keywords": [ "storybook", diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json index ed8837847325..72d6f428e808 100644 --- a/code/addons/backgrounds/package.json +++ b/code/addons/backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-backgrounds", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Switch backgrounds to view components in different settings", "keywords": [ "addon", diff --git a/code/addons/backgrounds/src/components/Tool.tsx b/code/addons/backgrounds/src/components/Tool.tsx index 828cc3b3a3d4..0659d8360c70 100644 --- a/code/addons/backgrounds/src/components/Tool.tsx +++ b/code/addons/backgrounds/src/components/Tool.tsx @@ -124,7 +124,7 @@ const Pure = memo(function PureTool(props: PureProps) { onHide(); }, })), - ]} + ].flat()} /> ); }} diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json index 429aa10bfe5c..ac6eab34268a 100644 --- a/code/addons/controls/package.json +++ b/code/addons/controls/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-controls", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Interact with component inputs dynamically in the Storybook UI", "keywords": [ "addon", diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json index cd8352d5247a..159bc11efff6 100644 --- a/code/addons/docs/package.json +++ b/code/addons/docs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-docs", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Document component usage and properties in Markdown", "keywords": [ "addon", diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json index d83ad0bd8a3e..20391dee6edf 100644 --- a/code/addons/essentials/package.json +++ b/code/addons/essentials/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-essentials", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Curated addons to bring out the best of Storybook", "keywords": [ "addon", diff --git a/code/addons/gfm/package.json b/code/addons/gfm/package.json index 8e4c51ba31d1..54e4dc72124e 100644 --- a/code/addons/gfm/package.json +++ b/code/addons/gfm/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-mdx-gfm", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "GitHub Flavored Markdown in Storybook", "keywords": [ "addon", diff --git a/code/addons/highlight/package.json b/code/addons/highlight/package.json index 8fefc078ae48..b3ed782127e4 100644 --- a/code/addons/highlight/package.json +++ b/code/addons/highlight/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-highlight", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Highlight DOM nodes within your stories", "keywords": [ "storybook-addons", diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json index 6611a51119bb..13320237aed9 100644 --- a/code/addons/interactions/package.json +++ b/code/addons/interactions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-interactions", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Automate, test and debug user interactions", "keywords": [ "storybook-addons", diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json index 4bbbd808658a..1f2f860c1075 100644 --- a/code/addons/jest/package.json +++ b/code/addons/jest/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-jest", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "React storybook addon that show component jest report", "keywords": [ "addon", diff --git a/code/addons/links/package.json b/code/addons/links/package.json index 7811c108d2a7..44795edb9638 100644 --- a/code/addons/links/package.json +++ b/code/addons/links/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-links", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Link stories together to build demos and prototypes with your UI components", "keywords": [ "storybook-addons", diff --git a/code/addons/measure/package.json b/code/addons/measure/package.json index 1f662322a90e..a1daef847594 100644 --- a/code/addons/measure/package.json +++ b/code/addons/measure/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-measure", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Inspect layouts by visualizing the box model", "keywords": [ "storybook-addons", diff --git a/code/addons/onboarding/package.json b/code/addons/onboarding/package.json index 0913e5da9cc5..48903150e734 100644 --- a/code/addons/onboarding/package.json +++ b/code/addons/onboarding/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-onboarding", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook Addon Onboarding - Introduces a new onboarding experience", "keywords": [ "storybook-addons", diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json index bef947388da9..54848755efd5 100644 --- a/code/addons/outline/package.json +++ b/code/addons/outline/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-outline", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Outline all elements with CSS to help with layout placement and alignment", "keywords": [ "storybook-addons", diff --git a/code/addons/storysource/package.json b/code/addons/storysource/package.json index 374e797bc5ea..1686b6f21075 100644 --- a/code/addons/storysource/package.json +++ b/code/addons/storysource/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storysource", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "View a story’s source code to see how it works and paste into your app", "keywords": [ "addon", diff --git a/code/addons/test/package.json b/code/addons/test/package.json index b778853351e5..cd4affdedc9d 100644 --- a/code/addons/test/package.json +++ b/code/addons/test/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/experimental-addon-test", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Integrate Vitest with Storybook", "keywords": [ "storybook-addons", @@ -98,6 +98,7 @@ "execa": "^8.0.1", "find-up": "^7.0.0", "formik": "^2.2.9", + "pathe": "^1.1.2", "picocolors": "^1.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/code/addons/test/src/components/ContextMenuItem.tsx b/code/addons/test/src/components/ContextMenuItem.tsx new file mode 100644 index 000000000000..8fa63f84819a --- /dev/null +++ b/code/addons/test/src/components/ContextMenuItem.tsx @@ -0,0 +1,100 @@ +import React, { + type FC, + type SyntheticEvent, + useCallback, + useEffect, + useRef, + useState, +} from 'react'; + +import { Button, ListItem } from 'storybook/internal/components'; +import { useStorybookApi } from 'storybook/internal/manager-api'; +import { useTheme } from 'storybook/internal/theming'; +import { type API_HashEntry, type Addon_TestProviderState } from 'storybook/internal/types'; + +import { PlayHollowIcon, StopAltHollowIcon } from '@storybook/icons'; + +import { TEST_PROVIDER_ID } from '../constants'; +import type { TestResult } from '../node/reporter'; +import { RelativeTime } from './RelativeTime'; + +export const ContextMenuItem: FC<{ + context: API_HashEntry; + state: Addon_TestProviderState<{ + testResults: TestResult[]; + }>; +}> = ({ context, state }) => { + const api = useStorybookApi(); + const [isDisabled, setDisabled] = useState(false); + + const id = useRef(context.id); + id.current = context.id; + + const Icon = state.running ? StopAltHollowIcon : PlayHollowIcon; + + useEffect(() => { + setDisabled(false); + }, [state.running]); + + const onClick = useCallback( + (event: SyntheticEvent) => { + setDisabled(true); + event.stopPropagation(); + if (state.running) { + api.cancelTestProvider(TEST_PROVIDER_ID); + } else { + api.runTestProvider(TEST_PROVIDER_ID, { entryId: id.current }); + } + }, + [api, state.running] + ); + + const theme = useTheme(); + + const title = state.crashed || state.failed ? 'Component tests failed' : 'Component tests'; + const errorMessage = state.error?.message; + let description: string | React.ReactNode = 'Not run'; + + if (state.running) { + description = state.progress + ? `Testing... ${state.progress.numPassedTests}/${state.progress.numTotalTests}` + : 'Starting...'; + } else if (state.failed && !errorMessage) { + description = ''; + } else if (state.crashed || (state.failed && errorMessage)) { + description = 'An error occured'; + } else if (state.progress?.finishedAt) { + description = ( + + ); + } else if (state.watching) { + description = 'Watching for file changes'; + } + + return ( +
{ + // stopPropagation to prevent the parent from closing the context menu, which is the default behavior onClick + event.stopPropagation(); + }} + > + + + + } + /> +
+ ); +}; diff --git a/code/addons/test/src/Panel.test.ts b/code/addons/test/src/components/Panel.test.ts similarity index 100% rename from code/addons/test/src/Panel.test.ts rename to code/addons/test/src/components/Panel.test.ts diff --git a/code/addons/test/src/Panel.tsx b/code/addons/test/src/components/Panel.tsx similarity index 98% rename from code/addons/test/src/Panel.tsx rename to code/addons/test/src/components/Panel.tsx index 0cc93575b35a..584872bad8c3 100644 --- a/code/addons/test/src/Panel.tsx +++ b/code/addons/test/src/components/Panel.tsx @@ -19,8 +19,8 @@ import { global } from '@storybook/global'; import { type Call, CallStates, EVENTS, type LogItem } from '@storybook/instrumenter'; import type { API_StatusValue } from '@storybook/types'; -import { InteractionsPanel } from './components/InteractionsPanel'; -import { ADDON_ID, TEST_PROVIDER_ID } from './constants'; +import { ADDON_ID, TEST_PROVIDER_ID } from '../constants'; +import { InteractionsPanel } from './InteractionsPanel'; interface Interaction extends Call { status: Call['status']; diff --git a/code/addons/test/src/components/PanelTitle.tsx b/code/addons/test/src/components/PanelTitle.tsx new file mode 100644 index 000000000000..4ef1ddedd302 --- /dev/null +++ b/code/addons/test/src/components/PanelTitle.tsx @@ -0,0 +1,23 @@ +import React from 'react'; + +import { Badge, Spaced } from 'storybook/internal/components'; +import { useAddonState } from 'storybook/internal/manager-api'; + +import { ADDON_ID } from '../constants'; + +export function PanelTitle() { + const [addonState = {}] = useAddonState(ADDON_ID); + const { hasException, interactionsCount } = addonState as any; + + return ( +
+ + Component tests + {interactionsCount && !hasException ? ( + {interactionsCount} + ) : null} + {hasException ? {interactionsCount} : null} + +
+ ); +} diff --git a/code/addons/test/src/components/RelativeTime.tsx b/code/addons/test/src/components/RelativeTime.tsx new file mode 100644 index 000000000000..d643960b06ed --- /dev/null +++ b/code/addons/test/src/components/RelativeTime.tsx @@ -0,0 +1,24 @@ +import { useEffect, useState } from 'react'; + +import { getRelativeTimeString } from '../manager'; + +export const RelativeTime = ({ timestamp, testCount }: { timestamp: Date; testCount: number }) => { + const [relativeTimeString, setRelativeTimeString] = useState(null); + + useEffect(() => { + if (timestamp) { + setRelativeTimeString(getRelativeTimeString(timestamp).replace(/^now$/, 'just now')); + + const interval = setInterval(() => { + setRelativeTimeString(getRelativeTimeString(timestamp).replace(/^now$/, 'just now')); + }, 10000); + + return () => clearInterval(interval); + } + }, [timestamp]); + + return ( + relativeTimeString && + `Ran ${testCount} ${testCount === 1 ? 'test' : 'tests'} ${relativeTimeString}` + ); +}; diff --git a/code/addons/test/src/manager.tsx b/code/addons/test/src/manager.tsx index 0b558a3d4a20..8f1888b30bf0 100644 --- a/code/addons/test/src/manager.tsx +++ b/code/addons/test/src/manager.tsx @@ -1,9 +1,9 @@ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useState } from 'react'; -import { AddonPanel, Badge, Link as LinkComponent, Spaced } from 'storybook/internal/components'; -import { TESTING_MODULE_RUN_ALL_REQUEST } from 'storybook/internal/core-events'; +import { AddonPanel, Button, Link as LinkComponent } from 'storybook/internal/components'; import type { Combo } from 'storybook/internal/manager-api'; -import { Consumer, addons, types, useAddonState } from 'storybook/internal/manager-api'; +import { Consumer, addons, types } from 'storybook/internal/manager-api'; +import { styled } from 'storybook/internal/theming'; import { type API_StatusObject, type API_StatusValue, @@ -11,28 +11,16 @@ import { Addon_TypesEnum, } from 'storybook/internal/types'; -import { Panel } from './Panel'; +import { EyeIcon, PlayHollowIcon, StopAltHollowIcon } from '@storybook/icons'; + +import { ContextMenuItem } from './components/ContextMenuItem'; import { GlobalErrorModal } from './components/GlobalErrorModal'; +import { Panel } from './components/Panel'; +import { PanelTitle } from './components/PanelTitle'; +import { RelativeTime } from './components/RelativeTime'; import { ADDON_ID, PANEL_ID, TEST_PROVIDER_ID } from './constants'; import type { TestResult } from './node/reporter'; -function Title() { - const [addonState = {}] = useAddonState(ADDON_ID); - const { hasException, interactionsCount } = addonState as any; - - return ( -
- - Component tests - {interactionsCount && !hasException ? ( - {interactionsCount} - ) : null} - {hasException ? {interactionsCount} : null} - -
- ); -} - const statusMap: Record = { failed: 'error', passed: 'success', @@ -58,26 +46,27 @@ export function getRelativeTimeString(date: Date): string { return rtf.format(Math.floor(delta / divisor), units[unitIndex]); } -const RelativeTime = ({ timestamp, testCount }: { timestamp: Date; testCount: number }) => { - const [relativeTimeString, setRelativeTimeString] = useState(null); - - useEffect(() => { - if (timestamp) { - setRelativeTimeString(getRelativeTimeString(timestamp).replace(/^now$/, 'just now')); +const Info = styled.div({ + display: 'flex', + flexDirection: 'column', + marginLeft: 6, +}); - const interval = setInterval(() => { - setRelativeTimeString(getRelativeTimeString(timestamp).replace(/^now$/, 'just now')); - }, 10000); +const SidebarContextMenuTitle = styled.div<{ crashed?: boolean }>(({ crashed, theme }) => ({ + fontSize: theme.typography.size.s1, + fontWeight: crashed ? 'bold' : 'normal', + color: crashed ? theme.color.negativeText : theme.color.defaultText, +})); - return () => clearInterval(interval); - } - }, [timestamp]); +const Description = styled.div(({ theme }) => ({ + fontSize: theme.typography.size.s1, + color: theme.barTextColor, +})); - return ( - relativeTimeString && - `Ran ${testCount} ${testCount === 1 ? 'test' : 'tests'} ${relativeTimeString}` - ); -}; +const Actions = styled.div({ + display: 'flex', + gap: 6, +}); addons.register(ADDON_ID, (api) => { const storybookBuilder = (globalThis as any).STORYBOOK_BUILDER || ''; @@ -91,25 +80,34 @@ addons.register(ADDON_ID, (api) => { type: Addon_TypesEnum.experimental_TEST_PROVIDER, runnable: true, watchable: true, - name: 'Component tests', - title: ({ crashed, failed }) => - crashed || failed ? 'Component tests failed' : 'Component tests', - description: ({ failed, running, watching, progress, crashed, error }) => { - const [isModalOpen, setIsModalOpen] = useState(false); - const errorMessage = error?.message; + sidebarContextMenu: ({ context, state }) => { + if (context.type === 'docs') { + return null; + } + if (context.type === 'story' && !context.tags.includes('test')) { + return null; + } + + return ; + }, + + render: (state) => { + const [isModalOpen, setIsModalOpen] = useState(false); - let message: string | React.ReactNode = 'Not run'; + const title = state.crashed || state.failed ? 'Component tests failed' : 'Component tests'; + const errorMessage = state.error?.message; + let description: string | React.ReactNode = 'Not run'; - if (running) { - message = progress - ? `Testing... ${progress.numPassedTests}/${progress.numTotalTests}` + if (state.running) { + description = state.progress + ? `Testing... ${state.progress.numPassedTests}/${state.progress.numTotalTests}` : 'Starting...'; - } else if (failed && !errorMessage) { - message = ''; - } else if (crashed || (failed && errorMessage)) { - message = ( + } else if (state.failed && !errorMessage) { + description = ''; + } else if (state.crashed || (state.failed && errorMessage)) { + description = ( <> { setIsModalOpen(true); }} > - {error?.name || 'View full error'} + {state.error?.name || 'View full error'} ); - } else if (progress?.finishedAt) { - message = ( + } else if (state.progress?.finishedAt) { + description = ( ); - } else if (watching) { - message = 'Watching for file changes'; + } else if (state.watching) { + description = 'Watching for file changes'; } return ( <> - {message} + + + {title} + + {description} + + + + {state.watchable && ( + + )} + {state.runnable && ( + <> + {state.running && state.cancellable ? ( + + ) : ( + + )} + + )} + + { }} onRerun={() => { setIsModalOpen(false); - api - .getChannel() - .emit(TESTING_MODULE_RUN_ALL_REQUEST, { providerId: TEST_PROVIDER_ID }); + api.runTestProvider(TEST_PROVIDER_ID); }} /> @@ -181,20 +223,20 @@ addons.register(ADDON_ID, (api) => { }>); } + const filter = ({ state }: Combo) => { + return { + storyId: state.storyId, + }; + }; + addons.add(PANEL_ID, { type: types.PANEL, - title: Title, + title: () => , match: ({ viewMode }) => viewMode === 'story', render: ({ active }) => { - const newLocal = useCallback(({ state }: Combo) => { - return { - storyId: state.storyId, - }; - }, []); - return ( - {({ storyId }) => } + {({ storyId }) => } ); }, diff --git a/code/addons/test/src/node/boot-test-runner.test.ts b/code/addons/test/src/node/boot-test-runner.test.ts index 7792bffdc9b3..f5d9fde5bf28 100644 --- a/code/addons/test/src/node/boot-test-runner.test.ts +++ b/code/addons/test/src/node/boot-test-runner.test.ts @@ -5,7 +5,6 @@ import { Channel, type ChannelTransport } from '@storybook/core/channels'; import { TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, TESTING_MODULE_PROGRESS_REPORT, - TESTING_MODULE_RUN_ALL_REQUEST, TESTING_MODULE_RUN_REQUEST, TESTING_MODULE_WATCH_MODE_REQUEST, } from '@storybook/core/core-events'; @@ -103,13 +102,6 @@ describe('bootTestRunner', () => { type: TESTING_MODULE_RUN_REQUEST, }); - mockChannel.emit(TESTING_MODULE_RUN_ALL_REQUEST, 'bar'); - expect(child.send).toHaveBeenCalledWith({ - args: ['bar'], - from: 'server', - type: TESTING_MODULE_RUN_ALL_REQUEST, - }); - mockChannel.emit(TESTING_MODULE_WATCH_MODE_REQUEST, 'baz'); expect(child.send).toHaveBeenCalledWith({ args: ['baz'], diff --git a/code/addons/test/src/node/boot-test-runner.ts b/code/addons/test/src/node/boot-test-runner.ts index 032be588b107..0771604861d9 100644 --- a/code/addons/test/src/node/boot-test-runner.ts +++ b/code/addons/test/src/node/boot-test-runner.ts @@ -1,11 +1,9 @@ import { type ChildProcess } from 'node:child_process'; -import { join } from 'node:path'; import type { Channel } from 'storybook/internal/channels'; import { TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, TESTING_MODULE_CRASH_REPORT, - TESTING_MODULE_RUN_ALL_REQUEST, TESTING_MODULE_RUN_REQUEST, TESTING_MODULE_WATCH_MODE_REQUEST, type TestingModuleCrashReportPayload, @@ -13,6 +11,7 @@ import { // eslint-disable-next-line depend/ban-dependencies import { execaNode } from 'execa'; +import { join } from 'pathe'; import { TEST_PROVIDER_ID } from '../constants'; import { log } from '../logger'; @@ -40,8 +39,6 @@ const bootTestRunner = async (channel: Channel, initEvent?: string, initArgs?: a const forwardRun = (...args: any[]) => child?.send({ args, from: 'server', type: TESTING_MODULE_RUN_REQUEST }); - const forwardRunAll = (...args: any[]) => - child?.send({ args, from: 'server', type: TESTING_MODULE_RUN_ALL_REQUEST }); const forwardWatchMode = (...args: any[]) => child?.send({ args, from: 'server', type: TESTING_MODULE_WATCH_MODE_REQUEST }); const forwardCancel = (...args: any[]) => @@ -49,7 +46,6 @@ const bootTestRunner = async (channel: Channel, initEvent?: string, initArgs?: a const killChild = () => { channel.off(TESTING_MODULE_RUN_REQUEST, forwardRun); - channel.off(TESTING_MODULE_RUN_ALL_REQUEST, forwardRunAll); channel.off(TESTING_MODULE_WATCH_MODE_REQUEST, forwardWatchMode); channel.off(TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, forwardCancel); child?.kill(); @@ -88,7 +84,6 @@ const bootTestRunner = async (channel: Channel, initEvent?: string, initArgs?: a // Forward all events from the channel to the child process channel.on(TESTING_MODULE_RUN_REQUEST, forwardRun); - channel.on(TESTING_MODULE_RUN_ALL_REQUEST, forwardRunAll); channel.on(TESTING_MODULE_WATCH_MODE_REQUEST, forwardWatchMode); channel.on(TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, forwardCancel); diff --git a/code/addons/test/src/node/reporter.ts b/code/addons/test/src/node/reporter.ts index 833ab0bf3823..51d2dc010cff 100644 --- a/code/addons/test/src/node/reporter.ts +++ b/code/addons/test/src/node/reporter.ts @@ -64,7 +64,7 @@ export class StorybookReporter implements Reporter { sendReport: (payload: TestingModuleProgressReportPayload) => void; - constructor(private testManager: TestManager) { + constructor(public testManager: TestManager) { this.sendReport = throttle((payload) => this.testManager.sendProgressReport(payload), 1000); } @@ -75,18 +75,19 @@ export class StorybookReporter implements Reporter { getProgressReport(finishedAt?: number) { const files = this.ctx.state.getFiles(); - const fileTests = getTests(files); - // The number of total tests is dynamic and can change during the run - const numTotalTests = fileTests.length; + const fileTests = getTests(files).filter((t) => t.mode === 'run' || t.mode === 'only'); + + // The total number of tests reported by Vitest is dynamic and can change during the run, so we + // use `storyCountForCurrentRun` instead, based on the list of stories provided in the run request. + const numTotalTests = finishedAt + ? fileTests.length + : Math.max(fileTests.length, this.testManager.vitestManager.storyCountForCurrentRun); const numFailedTests = fileTests.filter((t) => t.result?.state === 'fail').length; const numPassedTests = fileTests.filter((t) => t.result?.state === 'pass').length; - const numPendingTests = fileTests.filter( - (t) => t.result?.state === 'run' || t.mode === 'skip' || t.result?.state === 'skip' - ).length; - const testResults: TestResult[] = []; + const numPendingTests = fileTests.filter((t) => t.result?.state === 'run').length; - for (const file of files) { + const testResults: TestResult[] = files.map((file) => { const tests = getTests([file]); let startTime = tests.reduce( (prev, next) => Math.min(prev, next.result?.startTime ?? Number.POSITIVE_INFINITY), @@ -102,7 +103,7 @@ export class StorybookReporter implements Reporter { startTime ); - const assertionResults = tests.flatMap((t) => { + const results = tests.flatMap((t) => { const ancestorTitles: string[] = []; let iter: Suite | undefined = t.suite; while (iter) { @@ -129,15 +130,14 @@ export class StorybookReporter implements Reporter { }); const hasFailedTests = tests.some((t) => t.result?.state === 'fail'); - - testResults.push({ - results: assertionResults, + return { + results, startTime, endTime, status: file.result?.state === 'fail' || hasFailedTests ? 'failed' : 'passed', message: file.result?.errors?.[0]?.stack || file.result?.errors?.[0]?.message, - }); - } + }; + }); return { cancellable: !finishedAt, diff --git a/code/addons/test/src/node/test-manager.test.ts b/code/addons/test/src/node/test-manager.test.ts index 415c9bbc7bb6..b674c1d786f7 100644 --- a/code/addons/test/src/node/test-manager.test.ts +++ b/code/addons/test/src/node/test-manager.test.ts @@ -2,12 +2,14 @@ import { describe, expect, it, vi } from 'vitest'; import { createVitest } from 'vitest/node'; import { Channel, type ChannelTransport } from '@storybook/core/channels'; +import type { StoryIndex } from '@storybook/types'; -import path from 'path'; +import path from 'pathe'; import { TEST_PROVIDER_ID } from '../constants'; import { TestManager } from './test-manager'; +const setTestNamePattern = vi.hoisted(() => vi.fn()); const vitest = vi.hoisted(() => ({ projects: [{}], init: vi.fn(), @@ -17,6 +19,16 @@ const vitest = vi.hoisted(() => ({ cancelCurrentRun: vi.fn(), globTestSpecs: vi.fn(), getModuleProjects: vi.fn(() => []), + configOverride: { + actualTestNamePattern: undefined, + get testNamePattern() { + return this.actualTestNamePattern; + }, + set testNamePattern(value: string) { + setTestNamePattern(value); + this.actualTestNamePattern = value; + }, + }, })); vi.mock('vitest/node', () => ({ @@ -37,6 +49,33 @@ const tests = [ }, ]; +global.fetch = vi.fn().mockResolvedValue({ + json: () => + new Promise((resolve) => + resolve({ + v: 5, + entries: { + 'story--one': { + type: 'story', + id: 'story--one', + name: 'One', + title: 'story/one', + importPath: 'path/to/file', + tags: ['test'], + }, + 'another--one': { + type: 'story', + id: 'another--one', + name: 'One', + title: 'another/one', + importPath: 'path/to/another/file', + tags: ['test'], + }, + }, + } as StoryIndex) + ), +}); + const options: ConstructorParameters[1] = { onError: (message, error) => { throw error; @@ -80,18 +119,7 @@ describe('TestManager', () => { await testManager.handleRunRequest({ providerId: TEST_PROVIDER_ID, - payload: [ - { - stories: [], - importPath: 'path/to/file', - componentPath: 'path/to/component', - }, - { - stories: [], - importPath: 'path/to/another/file', - componentPath: 'path/to/another/component', - }, - ], + indexUrl: 'http://localhost:6006/index.json', }); expect(createVitest).toHaveBeenCalledTimes(1); expect(vitest.runFiles).toHaveBeenCalledWith(tests, true); @@ -103,35 +131,18 @@ describe('TestManager', () => { await testManager.handleRunRequest({ providerId: TEST_PROVIDER_ID, - payload: [ - { - stories: [], - importPath: 'path/to/unknown/file', - componentPath: 'path/to/unknown/component', - }, - ], + indexUrl: 'http://localhost:6006/index.json', + storyIds: [], }); expect(vitest.runFiles).toHaveBeenCalledWith([], true); + expect(vitest.configOverride.testNamePattern).toBeUndefined(); await testManager.handleRunRequest({ providerId: TEST_PROVIDER_ID, - payload: [ - { - stories: [], - importPath: 'path/to/file', - componentPath: 'path/to/component', - }, - ], + indexUrl: 'http://localhost:6006/index.json', + storyIds: ['story--one'], }); + expect(setTestNamePattern).toHaveBeenCalledWith(/^One$/); expect(vitest.runFiles).toHaveBeenCalledWith(tests.slice(0, 1), true); }); - - it('should handle run all request', async () => { - const testManager = await TestManager.start(mockChannel, options); - expect(createVitest).toHaveBeenCalledTimes(1); - - await testManager.handleRunAllRequest({ providerId: TEST_PROVIDER_ID }); - expect(createVitest).toHaveBeenCalledTimes(1); - expect(vitest.runFiles).toHaveBeenCalledWith(tests, true); - }); }); diff --git a/code/addons/test/src/node/test-manager.ts b/code/addons/test/src/node/test-manager.ts index a462fb1f7371..8d9a33a21e68 100644 --- a/code/addons/test/src/node/test-manager.ts +++ b/code/addons/test/src/node/test-manager.ts @@ -2,12 +2,10 @@ import type { Channel } from 'storybook/internal/channels'; import { TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, TESTING_MODULE_PROGRESS_REPORT, - TESTING_MODULE_RUN_ALL_REQUEST, TESTING_MODULE_RUN_REQUEST, TESTING_MODULE_WATCH_MODE_REQUEST, type TestingModuleCancelTestRunRequestPayload, type TestingModuleProgressReportPayload, - type TestingModuleRunAllRequestPayload, type TestingModuleRunRequestPayload, type TestingModuleWatchModeRequestPayload, } from 'storybook/internal/core-events'; @@ -16,7 +14,7 @@ import { TEST_PROVIDER_ID } from '../constants'; import { VitestManager } from './vitest-manager'; export class TestManager { - private vitestManager: VitestManager; + vitestManager: VitestManager; watchMode = false; @@ -30,7 +28,6 @@ export class TestManager { this.vitestManager = new VitestManager(channel, this); this.channel.on(TESTING_MODULE_RUN_REQUEST, this.handleRunRequest.bind(this)); - this.channel.on(TESTING_MODULE_RUN_ALL_REQUEST, this.handleRunAllRequest.bind(this)); this.channel.on(TESTING_MODULE_WATCH_MODE_REQUEST, this.handleWatchModeRequest.bind(this)); this.channel.on(TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, this.handleCancelRequest.bind(this)); @@ -43,14 +40,14 @@ export class TestManager { await this.vitestManager.startVitest(watchMode); } - async handleWatchModeRequest(request: TestingModuleWatchModeRequestPayload) { + async handleWatchModeRequest(payload: TestingModuleWatchModeRequestPayload) { try { - if (request.providerId !== TEST_PROVIDER_ID) { + if (payload.providerId !== TEST_PROVIDER_ID) { return; } - if (this.watchMode !== request.watchMode) { - this.watchMode = request.watchMode; + if (this.watchMode !== payload.watchMode) { + this.watchMode = payload.watchMode; await this.restartVitest(this.watchMode); } } catch (e) { @@ -58,33 +55,21 @@ export class TestManager { } } - async handleRunRequest(request: TestingModuleRunRequestPayload) { + async handleRunRequest(payload: TestingModuleRunRequestPayload) { try { - if (request.providerId !== TEST_PROVIDER_ID) { + if (payload.providerId !== TEST_PROVIDER_ID) { return; } - await this.vitestManager.runTests(request.payload); + await this.vitestManager.runTests(payload); } catch (e) { this.reportFatalError('Failed to run tests', e); } } - async handleRunAllRequest(request: TestingModuleRunAllRequestPayload) { + async handleCancelRequest(payload: TestingModuleCancelTestRunRequestPayload) { try { - if (request.providerId !== TEST_PROVIDER_ID) { - return; - } - - await this.vitestManager.runAllTests(); - } catch (e) { - this.reportFatalError('Failed to run all tests', e); - } - } - - async handleCancelRequest(request: TestingModuleCancelTestRunRequestPayload) { - try { - if (request.providerId !== TEST_PROVIDER_ID) { + if (payload.providerId !== TEST_PROVIDER_ID) { return; } diff --git a/code/addons/test/src/node/vitest-manager.ts b/code/addons/test/src/node/vitest-manager.ts index ab31e1fc7694..b14da16ecce7 100644 --- a/code/addons/test/src/node/vitest-manager.ts +++ b/code/addons/test/src/node/vitest-manager.ts @@ -1,22 +1,32 @@ import { existsSync } from 'node:fs'; -import path, { normalize } from 'node:path'; import type { TestProject, TestSpecification, Vitest, WorkspaceProject } from 'vitest/node'; import type { Channel } from 'storybook/internal/channels'; import type { TestingModuleRunRequestPayload } from 'storybook/internal/core-events'; +import type { DocsIndexEntry, StoryIndex, StoryIndexEntry } from '@storybook/types'; + +import path, { normalize } from 'pathe'; import slash from 'slash'; import { log } from '../logger'; import { StorybookReporter } from './reporter'; import type { TestManager } from './test-manager'; +type TagsFilter = { + include: string[]; + exclude: string[]; + skip: string[]; +}; + export class VitestManager { vitest: Vitest | null = null; vitestStartupCounter = 0; + storyCountForCurrentRun: number = 0; + constructor( private channel: Channel, private testManager: TestManager @@ -54,22 +64,6 @@ export class VitestManager { } } - async runAllTests() { - if (!this.vitest) { - await this.startVitest(); - } - - const storybookTests = await this.getStorybookTestSpecs(); - for (const storybookTest of storybookTests) { - // make sure to clear the file cache so test results are updated even if watch mode is not enabled - if (!this.testManager.watchMode) { - this.updateLastChanged(storybookTest.moduleId); - } - } - await this.cancelCurrentRun(); - await this.vitest!.runFiles(storybookTests, true); - } - private updateLastChanged(filepath: string) { const projects = this.vitest!.getModuleProjects(filepath); projects.forEach(({ server, browser }) => { @@ -83,36 +77,89 @@ export class VitestManager { }); } - async runTests(testPayload: TestingModuleRunRequestPayload['payload']) { - if (!this.vitest) { - await this.startVitest(); + private async fetchStories(indexUrl: string, requestStoryIds?: string[]) { + try { + const index = (await Promise.race([ + fetch(indexUrl).then((res) => res.json()), + new Promise((_, reject) => setTimeout(reject, 3000, new Error('Request took too long'))), + ])) as StoryIndex; + const storyIds = requestStoryIds || Object.keys(index.entries); + return storyIds.map((id) => index.entries[id]).filter((story) => story.type === 'story'); + } catch (e) { + log('Failed to fetch story index: ' + e.message); + return []; } + } - // This list contains all the test files (story files) that need to be run - // based on the test files that are passed in the tests array - // This list does NOT contain any filtering of specific - // test cases (story) within the test files - const testList: TestSpecification[] = []; - - const storybookTests = await this.getStorybookTestSpecs(); + private filterStories( + story: StoryIndexEntry | DocsIndexEntry, + moduleId: string, + tagsFilter: TagsFilter + ) { + const absoluteImportPath = path.join(process.cwd(), story.importPath); + if (absoluteImportPath !== moduleId) { + return false; + } + if (tagsFilter.include.length && !tagsFilter.include.some((tag) => story.tags?.includes(tag))) { + return false; + } + if (tagsFilter.exclude.some((tag) => story.tags?.includes(tag))) { + return false; + } + // Skipped tests are intentionally included here + return true; + } - for (const storybookTest of storybookTests) { - const match = testPayload.find((test) => { - const absoluteImportPath = path.join(process.cwd(), test.importPath); - return absoluteImportPath === storybookTest.moduleId; - }); - if (match) { - // make sure to clear the file cache so test results are updated even if watch mode is not enabled - if (!this.testManager.watchMode) { - this.updateLastChanged(storybookTest.moduleId); + async runTests(requestPayload: TestingModuleRunRequestPayload) { + if (!this.vitest) { + await this.startVitest(); + } + this.resetTestNamePattern(); + + const stories = await this.fetchStories(requestPayload.indexUrl, requestPayload.storyIds); + const vitestTestSpecs = await this.getStorybookTestSpecs(); + const isSingleStoryRun = requestPayload.storyIds?.length === 1; + + const { filteredTestFiles, totalTestCount } = vitestTestSpecs.reduce( + (acc, spec) => { + /* eslint-disable no-underscore-dangle */ + const { env = {} } = spec.project.config; + const include = env.__VITEST_INCLUDE_TAGS__?.split(',').filter(Boolean) ?? ['test']; + const exclude = env.__VITEST_EXCLUDE_TAGS__?.split(',').filter(Boolean) ?? []; + const skip = env.__VITEST_SKIP_TAGS__?.split(',').filter(Boolean) ?? []; + /* eslint-enable no-underscore-dangle */ + + const matches = stories.filter((story) => + this.filterStories(story, spec.moduleId, { include, exclude, skip }) + ); + if (matches.length) { + if (!this.testManager.watchMode) { + // Clear the file cache if watch mode is not enabled + this.updateLastChanged(spec.moduleId); + } + acc.filteredTestFiles.push(spec); + acc.totalTestCount += matches.filter( + // Don't count skipped stories, because StorybookReporter doesn't include them either + (story) => !skip.some((tag) => story.tags?.includes(tag)) + ).length; } + return acc; + }, + { filteredTestFiles: [] as TestSpecification[], totalTestCount: 0 } + ); - testList.push(storybookTest); - } + await this.cancelCurrentRun(); + this.storyCountForCurrentRun = totalTestCount; + + if (isSingleStoryRun) { + const storyName = stories[0].name; + this.vitest!.configOverride.testNamePattern = new RegExp( + `^${storyName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$` + ); } - await this.cancelCurrentRun(); - await this.vitest!.runFiles(testList, true); + await this.vitest!.runFiles(filteredTestFiles, true); + this.resetTestNamePattern(); } async cancelCurrentRun() { @@ -173,6 +220,7 @@ export class VitestManager { if (!this.vitest) { return; } + this.resetTestNamePattern(); const globTestFiles = await this.vitest.globTestSpecs(); const testGraphs = await Promise.all( @@ -202,6 +250,7 @@ export class VitestManager { const id = slash(file); this.vitest?.logger.clearHighlightCache(id); this.updateLastChanged(id); + this.storyCountForCurrentRun = 0; await this.runAffectedTests(file); } @@ -219,6 +268,7 @@ export class VitestManager { } async setupWatchers() { + this.resetTestNamePattern(); this.vitest?.server?.watcher.removeAllListeners('change'); this.vitest?.server?.watcher.removeAllListeners('add'); this.vitest?.server?.watcher.on('change', this.runAffectedTestsAfterChange.bind(this)); @@ -226,6 +276,12 @@ export class VitestManager { this.registerVitestConfigListener(); } + resetTestNamePattern() { + if (this.vitest) { + this.vitest.configOverride.testNamePattern = undefined; + } + } + isStorybookProject(project: TestProject | WorkspaceProject) { // eslint-disable-next-line no-underscore-dangle return !!project.config.env?.__STORYBOOK_URL__; diff --git a/code/addons/test/src/postinstall.ts b/code/addons/test/src/postinstall.ts index 90595b0e15d6..f6772f7691c1 100644 --- a/code/addons/test/src/postinstall.ts +++ b/code/addons/test/src/postinstall.ts @@ -1,8 +1,6 @@ import { existsSync } from 'node:fs'; import * as fs from 'node:fs/promises'; import { writeFile } from 'node:fs/promises'; -import { dirname, join, relative } from 'node:path'; -import * as path from 'node:path'; import { JsPackageManagerFactory, @@ -16,6 +14,7 @@ import { colors, logger } from 'storybook/internal/node-logger'; // eslint-disable-next-line depend/ban-dependencies import { execa } from 'execa'; import { findUp } from 'find-up'; +import { dirname, extname, join, relative, resolve } from 'pathe'; import picocolors from 'picocolors'; import prompts from 'prompts'; import { coerce, satisfies } from 'semver'; @@ -27,7 +26,8 @@ import { printError, printInfo, printSuccess, step } from './postinstall-logger' const ADDON_NAME = '@storybook/experimental-addon-test' as const; const EXTENSIONS = ['.js', '.jsx', '.ts', '.tsx', '.cts', '.mts', '.cjs', '.mjs'] as const; -const findFile = async (basename: string) => findUp(EXTENSIONS.map((ext) => basename + ext)); +const findFile = async (basename: string, extraExtensions: string[] = []) => + findUp([...EXTENSIONS, ...extraExtensions].map((ext) => basename + ext)); export default async function postInstall(options: PostinstallOptions) { printSuccess( @@ -244,7 +244,10 @@ export default async function postInstall(options: PostinstallOptions) { args: ['playwright', 'install', 'chromium', '--with-deps'], }); - const vitestSetupFile = path.resolve(options.configDir, 'vitest.setup.ts'); + const fileExtension = + allDeps['typescript'] || (await findFile('tsconfig', ['.json'])) ? 'ts' : 'js'; + + const vitestSetupFile = resolve(options.configDir, `vitest.setup.${fileExtension}`); if (existsSync(vitestSetupFile)) { printError( '🚨 Oh no!', @@ -264,9 +267,9 @@ export default async function postInstall(options: PostinstallOptions) { logger.plain(`${step} Creating a Vitest setup file for Storybook:`); logger.plain(colors.gray(` ${vitestSetupFile}`)); - const previewExists = EXTENSIONS.map((ext) => - path.resolve(options.configDir, `preview${ext}`) - ).some((config) => existsSync(config)); + const previewExists = EXTENSIONS.map((ext) => resolve(options.configDir, `preview${ext}`)).some( + (config) => existsSync(config) + ); await writeFile( vitestSetupFile, @@ -331,10 +334,10 @@ export default async function postInstall(options: PostinstallOptions) { if (rootConfig) { // If there's an existing config, we create a workspace file so we can run Storybook tests alongside. - const extname = path.extname(rootConfig); - const browserWorkspaceFile = path.resolve(dirname(rootConfig), `vitest.workspace${extname}`); + const extension = extname(rootConfig); + const browserWorkspaceFile = resolve(dirname(rootConfig), `vitest.workspace${extension}`); // to be set in vitest config - const vitestSetupFilePath = path.relative(path.dirname(browserWorkspaceFile), vitestSetupFile); + const vitestSetupFilePath = relative(dirname(browserWorkspaceFile), vitestSetupFile); logger.line(1); logger.plain(`${step} Creating a Vitest project workspace file:`); @@ -373,9 +376,9 @@ export default async function postInstall(options: PostinstallOptions) { ); } else { // If there's no existing Vitest/Vite config, we create a new Vitest config file. - const newVitestConfigFile = path.resolve('vitest.config.ts'); + const newVitestConfigFile = resolve(`vitest.config.${fileExtension}`); // to be set in vitest config - const vitestSetupFilePath = path.relative(path.dirname(newVitestConfigFile), vitestSetupFile); + const vitestSetupFilePath = relative(dirname(newVitestConfigFile), vitestSetupFile); logger.line(1); logger.plain(`${step} Creating a Vitest project config file:`); @@ -453,6 +456,12 @@ const getVitestPluginInfo = (framework: string) => { frameworkPluginCall = 'storybookVuePlugin()'; } + if (framework === '@storybook/react-native-web-vite') { + frameworkPluginImport = + "import { storybookReactNativeWeb } from '@storybook/react-native-web-vite/vite-plugin';"; + frameworkPluginCall = 'storybookReactNativeWeb()'; + } + // spaces for file identation frameworkPluginImport = `\n${frameworkPluginImport}`; frameworkPluginDocs = frameworkPluginDocs ? `\n ${frameworkPluginDocs}` : ''; @@ -491,14 +500,17 @@ async function getStorybookInfo({ configDir, packageManager: pkgMgr }: Postinsta } const builderPackageJson = await fs.readFile( - `${typeof builder === 'string' ? builder : builder.name}/package.json`, + require.resolve(join(typeof builder === 'string' ? builder : builder.name, 'package.json')), 'utf8' ); const builderPackageName = JSON.parse(builderPackageJson).name; let rendererPackageName: string | undefined; if (renderer) { - const rendererPackageJson = await fs.readFile(`${renderer}/package.json`, 'utf8'); + const rendererPackageJson = await fs.readFile( + require.resolve(join(renderer, 'package.json')), + 'utf8' + ); rendererPackageName = JSON.parse(rendererPackageJson).name; } diff --git a/code/addons/test/src/preset.ts b/code/addons/test/src/preset.ts index 685a56e2baf4..a1a6e1233faf 100644 --- a/code/addons/test/src/preset.ts +++ b/code/addons/test/src/preset.ts @@ -1,16 +1,15 @@ import { readFileSync } from 'node:fs'; -import { isAbsolute, join } from 'node:path'; import type { Channel } from 'storybook/internal/channels'; import { checkAddonOrder, getFrameworkName, serverRequire } from 'storybook/internal/common'; import { - TESTING_MODULE_RUN_ALL_REQUEST, TESTING_MODULE_RUN_REQUEST, TESTING_MODULE_WATCH_MODE_REQUEST, } from 'storybook/internal/core-events'; import { oneWayHash, telemetry } from 'storybook/internal/telemetry'; import type { Options, PresetProperty, StoryId } from 'storybook/internal/types'; +import { isAbsolute, join } from 'pathe'; import picocolors from 'picocolors'; import { dedent } from 'ts-dedent'; @@ -68,7 +67,6 @@ export const experimental_serverChannel = async (channel: Channel, options: Opti runTestRunner(channel, eventName, args); }; - channel.on(TESTING_MODULE_RUN_ALL_REQUEST, execute(TESTING_MODULE_RUN_ALL_REQUEST)); channel.on(TESTING_MODULE_RUN_REQUEST, execute(TESTING_MODULE_RUN_REQUEST)); channel.on(TESTING_MODULE_WATCH_MODE_REQUEST, (payload) => { if (payload.watchMode) { diff --git a/code/addons/test/src/vitest-plugin/index.ts b/code/addons/test/src/vitest-plugin/index.ts index 458d0292e295..08f2a3b07cb4 100644 --- a/code/addons/test/src/vitest-plugin/index.ts +++ b/code/addons/test/src/vitest-plugin/index.ts @@ -1,6 +1,4 @@ /* eslint-disable no-underscore-dangle */ -import { join, resolve } from 'node:path'; - import type { Plugin } from 'vitest/config'; import { @@ -12,6 +10,8 @@ import { readConfig, vitestTransform } from 'storybook/internal/csf-tools'; import { MainFileMissingError } from 'storybook/internal/server-errors'; import type { StoriesEntry } from 'storybook/internal/types'; +import { join, resolve } from 'pathe'; + import type { InternalOptions, UserOptions } from './types'; const defaultOptions: UserOptions = { @@ -99,6 +99,9 @@ export const storybookTest = (options?: UserOptions): Plugin => { ...config.test.env, // To be accessed by the setup file __STORYBOOK_URL__: storybookUrl, + __VITEST_INCLUDE_TAGS__: finalOptions.tags.include.join(','), + __VITEST_EXCLUDE_TAGS__: finalOptions.tags.exclude.join(','), + __VITEST_SKIP_TAGS__: finalOptions.tags.skip.join(','), }; if (config.test.browser) { @@ -131,6 +134,16 @@ export const storybookTest = (options?: UserOptions): Plugin => { config.test.server.deps.inline.push('@storybook/experimental-addon-test'); } + config.optimizeDeps ??= {}; + config.optimizeDeps = { + ...config.optimizeDeps, + include: [...(config.optimizeDeps.include ?? []), '@storybook/experimental-addon-test/**'], + }; + + if (frameworkName?.includes('react') || frameworkName?.includes('nextjs')) { + config.optimizeDeps.include.push('react-dom/test-utils'); + } + if (frameworkName?.includes('vue3')) { config.define ??= {}; config.define.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = 'false'; diff --git a/code/addons/themes/README.md b/code/addons/themes/README.md index 68309d9054a0..1f58f259485c 100644 --- a/code/addons/themes/README.md +++ b/code/addons/themes/README.md @@ -36,7 +36,7 @@ Don't see your favorite tool listed? Don't worry! That doesn't mean this addon i ### ❗️ Overriding theme -If you want to override your theme for a particular component or story, you can use the `themes.themeOverride` parameter. +If you want to override your theme for a particular component or story, you can use the `globals.theme` parameter. ```js import React from 'react'; diff --git a/code/addons/themes/package.json b/code/addons/themes/package.json index 5fd65ba89a0c..92108206a00e 100644 --- a/code/addons/themes/package.json +++ b/code/addons/themes/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-themes", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Switch between multiple themes for you components in Storybook", "keywords": [ "css", diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json index b99a65fe8cad..3dd5ff474d47 100644 --- a/code/addons/toolbars/package.json +++ b/code/addons/toolbars/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-toolbars", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Create your own toolbar items that control story rendering", "keywords": [ "addon", diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json index 9bcdf2aff652..4f226e29d5c2 100644 --- a/code/addons/viewport/package.json +++ b/code/addons/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-viewport", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Build responsive components by adjusting Storybook’s viewport size and orientation", "keywords": [ "addon", diff --git a/code/addons/viewport/src/components/Tool.tsx b/code/addons/viewport/src/components/Tool.tsx index 52b8713c7919..cf3170a8c48a 100644 --- a/code/addons/viewport/src/components/Tool.tsx +++ b/code/addons/viewport/src/components/Tool.tsx @@ -139,7 +139,7 @@ const Pure = React.memo(function PureTool(props: PureProps) { onHide(); }, })), - ]} + ].flat()} /> )} closeOnOutsideClick diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json index 594e1c57e74e..b69d9f3ecfb1 100644 --- a/code/builders/builder-vite/package.json +++ b/code/builders/builder-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-vite", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "A plugin to run and build Storybooks with Vite", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/builders/builder-vite/#readme", "bugs": { diff --git a/code/builders/builder-webpack5/package.json b/code/builders/builder-webpack5/package.json index 6a122437e617..c2046c53e0b5 100644 --- a/code/builders/builder-webpack5/package.json +++ b/code/builders/builder-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-webpack5", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/core/package.json b/code/core/package.json index 919e462ebd30..adbff71eb3a7 100644 --- a/code/core/package.json +++ b/code/core/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" @@ -37,6 +37,16 @@ "import": "./dist/client-logger/index.js", "require": "./dist/client-logger/index.cjs" }, + "./theming": { + "types": "./dist/theming/index.d.ts", + "import": "./dist/theming/index.js", + "require": "./dist/theming/index.cjs" + }, + "./theming/create": { + "types": "./dist/theming/create.d.ts", + "import": "./dist/theming/create.js", + "require": "./dist/theming/create.cjs" + }, "./core-server": { "types": "./dist/core-server/index.d.ts", "import": "./dist/core-server/index.js", @@ -122,16 +132,6 @@ "import": "./dist/components/index.js", "require": "./dist/components/index.cjs" }, - "./theming": { - "types": "./dist/theming/index.d.ts", - "import": "./dist/theming/index.js", - "require": "./dist/theming/index.cjs" - }, - "./theming/create": { - "types": "./dist/theming/create.d.ts", - "import": "./dist/theming/create.js", - "require": "./dist/theming/create.cjs" - }, "./docs-tools": { "types": "./dist/docs-tools/index.d.ts", "import": "./dist/docs-tools/index.js", @@ -183,6 +183,12 @@ "client-logger": [ "./dist/client-logger/index.d.ts" ], + "theming": [ + "./dist/theming/index.d.ts" + ], + "theming/create": [ + "./dist/theming/create.d.ts" + ], "core-server": [ "./dist/core-server/index.d.ts" ], @@ -237,12 +243,6 @@ "components": [ "./dist/components/index.d.ts" ], - "theming": [ - "./dist/theming/index.d.ts" - ], - "theming/create": [ - "./dist/theming/create.d.ts" - ], "docs-tools": [ "./dist/docs-tools/index.d.ts" ], diff --git a/code/core/scripts/entries.ts b/code/core/scripts/entries.ts index e3b78e483990..bcd1d1b94572 100644 --- a/code/core/scripts/entries.ts +++ b/code/core/scripts/entries.ts @@ -9,6 +9,9 @@ export const getEntries = (cwd: string) => { define('src/node-logger/index.ts', ['node'], true), define('src/client-logger/index.ts', ['browser', 'node'], true), + define('src/theming/index.ts', ['browser', 'node'], true, ['react']), + define('src/theming/create.ts', ['browser', 'node'], true, ['react']), + define('src/core-server/index.ts', ['node'], true), define('src/core-server/presets/common-preset.ts', ['node'], false), define('src/core-server/presets/common-manager.ts', ['browser'], false), @@ -35,8 +38,6 @@ export const getEntries = (cwd: string) => { ['react', 'react-dom'], ['prettier'] // the syntax highlighter uses prettier/standalone to format the code ), - define('src/theming/index.ts', ['browser', 'node'], true, ['react']), - define('src/theming/create.ts', ['browser', 'node'], true, ['react']), define('src/docs-tools/index.ts', ['browser', 'node'], true), define('src/manager/globals-module-info.ts', ['node'], true), diff --git a/code/core/scripts/helpers/generateTypesFiles.ts b/code/core/scripts/helpers/generateTypesFiles.ts index fd7a7eff789d..4c04a20d41c3 100644 --- a/code/core/scripts/helpers/generateTypesFiles.ts +++ b/code/core/scripts/helpers/generateTypesFiles.ts @@ -3,6 +3,7 @@ import { join, relative } from 'node:path'; import { spawn } from '../../../../scripts/prepare/tools'; import { limit, picocolors, process } from '../../../../scripts/prepare/tools'; import type { getEntries } from '../entries'; +import { modifyThemeTypes } from './modifyThemeTypes'; export async function generateTypesFiles( entries: ReturnType, @@ -70,6 +71,11 @@ export async function generateTypesFiles( process.exit(dtsProcess.exitCode || 1); } else { console.log('Generated types for', picocolors.cyan(relative(cwd, dtsEntries[index]))); + + if (dtsEntries[index].includes('src/theming/index')) { + console.log('Modifying theme types'); + await modifyThemeTypes(); + } } }); }) diff --git a/code/core/scripts/helpers/modifyThemeTypes.ts b/code/core/scripts/helpers/modifyThemeTypes.ts index 5b35ca6be329..85d78a2cb07b 100644 --- a/code/core/scripts/helpers/modifyThemeTypes.ts +++ b/code/core/scripts/helpers/modifyThemeTypes.ts @@ -14,7 +14,7 @@ export async function modifyThemeTypes() { const contents = await readFile(target, 'utf-8'); const footer = contents.includes('// auto generated file') - ? `export { StorybookTheme as Theme } from '../src/index';` + ? `export { StorybookTheme as Theme } from '../../src/theming/index';` : dedent` interface Theme extends StorybookTheme {} export type { Theme }; diff --git a/code/core/scripts/prep.ts b/code/core/scripts/prep.ts index f8726e79df48..4d81c65b1d7e 100644 --- a/code/core/scripts/prep.ts +++ b/code/core/scripts/prep.ts @@ -66,7 +66,6 @@ async function run() { await generateTypesMapperFiles(entries); await modifyThemeTypes(); await generateTypesFiles(entries, isOptimized, cwd); - await modifyThemeTypes(); }) ); diff --git a/code/core/src/cli/detect.ts b/code/core/src/cli/detect.ts index 09ef8cae02cf..5b50abee4301 100644 --- a/code/core/src/cli/detect.ts +++ b/code/core/src/cli/detect.ts @@ -130,6 +130,8 @@ export async function detectBuilder(packageManager: JsPackageManager, projectTyp // Fallback to Vite or Webpack based on project type switch (projectType) { + case ProjectType.REACT_NATIVE_WEB: + return CoreBuilder.Vite; case ProjectType.REACT_SCRIPTS: case ProjectType.ANGULAR: case ProjectType.REACT_NATIVE: // technically react native doesn't use webpack, we just want to set something diff --git a/code/core/src/cli/helpers.ts b/code/core/src/cli/helpers.ts index 47df29aba89e..27e91f001ac1 100644 --- a/code/core/src/cli/helpers.ts +++ b/code/core/src/cli/helpers.ts @@ -157,6 +157,7 @@ export const frameworkToDefaultBuilder: Record< 'preact-vite': CoreBuilder.Vite, 'preact-webpack5': CoreBuilder.Webpack5, qwik: CoreBuilder.Vite, + 'react-native-web-vite': CoreBuilder.Vite, 'react-vite': CoreBuilder.Vite, 'react-webpack5': CoreBuilder.Webpack5, 'server-webpack5': CoreBuilder.Webpack5, @@ -193,6 +194,13 @@ export async function getVersionSafe(packageManager: JsPackageManager, packageNa return undefined; } +export const cliStoriesTargetPath = async () => { + if (existsSync('./src')) { + return './src/stories'; + } + return './stories'; +}; + export async function copyTemplateFiles({ packageManager, renderer, @@ -252,14 +260,7 @@ export async function copyTemplateFiles({ throw new Error(`Unsupported renderer: ${renderer} (${baseDir})`); }; - const targetPath = async () => { - if (existsSync('./src')) { - return './src/stories'; - } - return './stories'; - }; - - const destinationPath = destination ?? (await targetPath()); + const destinationPath = destination ?? (await cliStoriesTargetPath()); if (commonAssetsDir) { await cp(commonAssetsDir, destinationPath, { recursive: true, diff --git a/code/core/src/cli/project_types.ts b/code/core/src/cli/project_types.ts index 5d7d4a4d3ead..25148d2bc089 100644 --- a/code/core/src/cli/project_types.ts +++ b/code/core/src/cli/project_types.ts @@ -47,6 +47,7 @@ export enum ProjectType { REACT = 'REACT', REACT_SCRIPTS = 'REACT_SCRIPTS', REACT_NATIVE = 'REACT_NATIVE', + REACT_NATIVE_WEB = 'REACT_NATIVE_WEB', REACT_PROJECT = 'REACT_PROJECT', WEBPACK_REACT = 'WEBPACK_REACT', NEXTJS = 'NEXTJS', diff --git a/code/core/src/common/js-package-manager/JsPackageManagerFactory.ts b/code/core/src/common/js-package-manager/JsPackageManagerFactory.ts index fcd057906057..3f31adbb1c90 100644 --- a/code/core/src/common/js-package-manager/JsPackageManagerFactory.ts +++ b/code/core/src/common/js-package-manager/JsPackageManagerFactory.ts @@ -141,6 +141,7 @@ function hasNPM(cwd?: string) { env: { ...process.env, COREPACK_ENABLE_STRICT: '0', + COREPACK_ENABLE_AUTO_PIN: '0', }, }); return npmVersionCommand.status === 0; @@ -153,6 +154,7 @@ function hasBun(cwd?: string) { env: { ...process.env, COREPACK_ENABLE_STRICT: '0', + COREPACK_ENABLE_AUTO_PIN: '0', }, }); return pnpmVersionCommand.status === 0; @@ -165,6 +167,7 @@ function hasPNPM(cwd?: string) { env: { ...process.env, COREPACK_ENABLE_STRICT: '0', + COREPACK_ENABLE_AUTO_PIN: '0', }, }); return pnpmVersionCommand.status === 0; @@ -177,6 +180,7 @@ function getYarnVersion(cwd?: string): 1 | 2 | undefined { env: { ...process.env, COREPACK_ENABLE_STRICT: '0', + COREPACK_ENABLE_AUTO_PIN: '0', }, }); diff --git a/code/core/src/common/utils/framework-to-renderer.ts b/code/core/src/common/utils/framework-to-renderer.ts index 1dd1fa0b811e..7ae4c3b057a5 100644 --- a/code/core/src/common/utils/framework-to-renderer.ts +++ b/code/core/src/common/utils/framework-to-renderer.ts @@ -32,6 +32,7 @@ export const frameworkToRenderer: Record< html: 'html', preact: 'preact', 'react-native': 'react-native', + 'react-native-web-vite': 'react', react: 'react', server: 'server', svelte: 'svelte', diff --git a/code/core/src/common/versions.ts b/code/core/src/common/versions.ts index 9d0225f6f352..04679850115d 100644 --- a/code/core/src/common/versions.ts +++ b/code/core/src/common/versions.ts @@ -1,87 +1,88 @@ // auto generated file, do not edit export default { - '@storybook/addon-a11y': '8.5.0-alpha.3', - '@storybook/addon-actions': '8.5.0-alpha.3', - '@storybook/addon-backgrounds': '8.5.0-alpha.3', - '@storybook/addon-controls': '8.5.0-alpha.3', - '@storybook/addon-docs': '8.5.0-alpha.3', - '@storybook/addon-essentials': '8.5.0-alpha.3', - '@storybook/addon-mdx-gfm': '8.5.0-alpha.3', - '@storybook/addon-highlight': '8.5.0-alpha.3', - '@storybook/addon-interactions': '8.5.0-alpha.3', - '@storybook/addon-jest': '8.5.0-alpha.3', - '@storybook/addon-links': '8.5.0-alpha.3', - '@storybook/addon-measure': '8.5.0-alpha.3', - '@storybook/addon-onboarding': '8.5.0-alpha.3', - '@storybook/addon-outline': '8.5.0-alpha.3', - '@storybook/addon-storysource': '8.5.0-alpha.3', - '@storybook/experimental-addon-test': '8.5.0-alpha.3', - '@storybook/addon-themes': '8.5.0-alpha.3', - '@storybook/addon-toolbars': '8.5.0-alpha.3', - '@storybook/addon-viewport': '8.5.0-alpha.3', - '@storybook/builder-vite': '8.5.0-alpha.3', - '@storybook/builder-webpack5': '8.5.0-alpha.3', - '@storybook/core': '8.5.0-alpha.3', - '@storybook/builder-manager': '8.5.0-alpha.3', - '@storybook/channels': '8.5.0-alpha.3', - '@storybook/client-logger': '8.5.0-alpha.3', - '@storybook/components': '8.5.0-alpha.3', - '@storybook/core-common': '8.5.0-alpha.3', - '@storybook/core-events': '8.5.0-alpha.3', - '@storybook/core-server': '8.5.0-alpha.3', - '@storybook/csf-tools': '8.5.0-alpha.3', - '@storybook/docs-tools': '8.5.0-alpha.3', - '@storybook/manager': '8.5.0-alpha.3', - '@storybook/manager-api': '8.5.0-alpha.3', - '@storybook/node-logger': '8.5.0-alpha.3', - '@storybook/preview': '8.5.0-alpha.3', - '@storybook/preview-api': '8.5.0-alpha.3', - '@storybook/router': '8.5.0-alpha.3', - '@storybook/telemetry': '8.5.0-alpha.3', - '@storybook/theming': '8.5.0-alpha.3', - '@storybook/types': '8.5.0-alpha.3', - '@storybook/angular': '8.5.0-alpha.3', - '@storybook/ember': '8.5.0-alpha.3', - '@storybook/experimental-nextjs-vite': '8.5.0-alpha.3', - '@storybook/html-vite': '8.5.0-alpha.3', - '@storybook/html-webpack5': '8.5.0-alpha.3', - '@storybook/nextjs': '8.5.0-alpha.3', - '@storybook/preact-vite': '8.5.0-alpha.3', - '@storybook/preact-webpack5': '8.5.0-alpha.3', - '@storybook/react-vite': '8.5.0-alpha.3', - '@storybook/react-webpack5': '8.5.0-alpha.3', - '@storybook/server-webpack5': '8.5.0-alpha.3', - '@storybook/svelte-vite': '8.5.0-alpha.3', - '@storybook/svelte-webpack5': '8.5.0-alpha.3', - '@storybook/sveltekit': '8.5.0-alpha.3', - '@storybook/vue3-vite': '8.5.0-alpha.3', - '@storybook/vue3-webpack5': '8.5.0-alpha.3', - '@storybook/web-components-vite': '8.5.0-alpha.3', - '@storybook/web-components-webpack5': '8.5.0-alpha.3', - '@storybook/blocks': '8.5.0-alpha.3', - storybook: '8.5.0-alpha.3', - sb: '8.5.0-alpha.3', - '@storybook/cli': '8.5.0-alpha.3', - '@storybook/codemod': '8.5.0-alpha.3', - '@storybook/core-webpack': '8.5.0-alpha.3', - 'create-storybook': '8.5.0-alpha.3', - '@storybook/csf-plugin': '8.5.0-alpha.3', - '@storybook/instrumenter': '8.5.0-alpha.3', - '@storybook/react-dom-shim': '8.5.0-alpha.3', - '@storybook/source-loader': '8.5.0-alpha.3', - '@storybook/test': '8.5.0-alpha.3', - '@storybook/preset-create-react-app': '8.5.0-alpha.3', - '@storybook/preset-html-webpack': '8.5.0-alpha.3', - '@storybook/preset-preact-webpack': '8.5.0-alpha.3', - '@storybook/preset-react-webpack': '8.5.0-alpha.3', - '@storybook/preset-server-webpack': '8.5.0-alpha.3', - '@storybook/preset-svelte-webpack': '8.5.0-alpha.3', - '@storybook/preset-vue3-webpack': '8.5.0-alpha.3', - '@storybook/html': '8.5.0-alpha.3', - '@storybook/preact': '8.5.0-alpha.3', - '@storybook/react': '8.5.0-alpha.3', - '@storybook/server': '8.5.0-alpha.3', - '@storybook/svelte': '8.5.0-alpha.3', - '@storybook/vue3': '8.5.0-alpha.3', - '@storybook/web-components': '8.5.0-alpha.3', + '@storybook/addon-a11y': '8.5.0-alpha.10', + '@storybook/addon-actions': '8.5.0-alpha.10', + '@storybook/addon-backgrounds': '8.5.0-alpha.10', + '@storybook/addon-controls': '8.5.0-alpha.10', + '@storybook/addon-docs': '8.5.0-alpha.10', + '@storybook/addon-essentials': '8.5.0-alpha.10', + '@storybook/addon-mdx-gfm': '8.5.0-alpha.10', + '@storybook/addon-highlight': '8.5.0-alpha.10', + '@storybook/addon-interactions': '8.5.0-alpha.10', + '@storybook/addon-jest': '8.5.0-alpha.10', + '@storybook/addon-links': '8.5.0-alpha.10', + '@storybook/addon-measure': '8.5.0-alpha.10', + '@storybook/addon-onboarding': '8.5.0-alpha.10', + '@storybook/addon-outline': '8.5.0-alpha.10', + '@storybook/addon-storysource': '8.5.0-alpha.10', + '@storybook/experimental-addon-test': '8.5.0-alpha.10', + '@storybook/addon-themes': '8.5.0-alpha.10', + '@storybook/addon-toolbars': '8.5.0-alpha.10', + '@storybook/addon-viewport': '8.5.0-alpha.10', + '@storybook/builder-vite': '8.5.0-alpha.10', + '@storybook/builder-webpack5': '8.5.0-alpha.10', + '@storybook/core': '8.5.0-alpha.10', + '@storybook/builder-manager': '8.5.0-alpha.10', + '@storybook/channels': '8.5.0-alpha.10', + '@storybook/client-logger': '8.5.0-alpha.10', + '@storybook/components': '8.5.0-alpha.10', + '@storybook/core-common': '8.5.0-alpha.10', + '@storybook/core-events': '8.5.0-alpha.10', + '@storybook/core-server': '8.5.0-alpha.10', + '@storybook/csf-tools': '8.5.0-alpha.10', + '@storybook/docs-tools': '8.5.0-alpha.10', + '@storybook/manager': '8.5.0-alpha.10', + '@storybook/manager-api': '8.5.0-alpha.10', + '@storybook/node-logger': '8.5.0-alpha.10', + '@storybook/preview': '8.5.0-alpha.10', + '@storybook/preview-api': '8.5.0-alpha.10', + '@storybook/router': '8.5.0-alpha.10', + '@storybook/telemetry': '8.5.0-alpha.10', + '@storybook/theming': '8.5.0-alpha.10', + '@storybook/types': '8.5.0-alpha.10', + '@storybook/angular': '8.5.0-alpha.10', + '@storybook/ember': '8.5.0-alpha.10', + '@storybook/experimental-nextjs-vite': '8.5.0-alpha.10', + '@storybook/html-vite': '8.5.0-alpha.10', + '@storybook/html-webpack5': '8.5.0-alpha.10', + '@storybook/nextjs': '8.5.0-alpha.10', + '@storybook/preact-vite': '8.5.0-alpha.10', + '@storybook/preact-webpack5': '8.5.0-alpha.10', + '@storybook/react-native-web-vite': '8.5.0-alpha.10', + '@storybook/react-vite': '8.5.0-alpha.10', + '@storybook/react-webpack5': '8.5.0-alpha.10', + '@storybook/server-webpack5': '8.5.0-alpha.10', + '@storybook/svelte-vite': '8.5.0-alpha.10', + '@storybook/svelte-webpack5': '8.5.0-alpha.10', + '@storybook/sveltekit': '8.5.0-alpha.10', + '@storybook/vue3-vite': '8.5.0-alpha.10', + '@storybook/vue3-webpack5': '8.5.0-alpha.10', + '@storybook/web-components-vite': '8.5.0-alpha.10', + '@storybook/web-components-webpack5': '8.5.0-alpha.10', + '@storybook/blocks': '8.5.0-alpha.10', + storybook: '8.5.0-alpha.10', + sb: '8.5.0-alpha.10', + '@storybook/cli': '8.5.0-alpha.10', + '@storybook/codemod': '8.5.0-alpha.10', + '@storybook/core-webpack': '8.5.0-alpha.10', + 'create-storybook': '8.5.0-alpha.10', + '@storybook/csf-plugin': '8.5.0-alpha.10', + '@storybook/instrumenter': '8.5.0-alpha.10', + '@storybook/react-dom-shim': '8.5.0-alpha.10', + '@storybook/source-loader': '8.5.0-alpha.10', + '@storybook/test': '8.5.0-alpha.10', + '@storybook/preset-create-react-app': '8.5.0-alpha.10', + '@storybook/preset-html-webpack': '8.5.0-alpha.10', + '@storybook/preset-preact-webpack': '8.5.0-alpha.10', + '@storybook/preset-react-webpack': '8.5.0-alpha.10', + '@storybook/preset-server-webpack': '8.5.0-alpha.10', + '@storybook/preset-svelte-webpack': '8.5.0-alpha.10', + '@storybook/preset-vue3-webpack': '8.5.0-alpha.10', + '@storybook/html': '8.5.0-alpha.10', + '@storybook/preact': '8.5.0-alpha.10', + '@storybook/react': '8.5.0-alpha.10', + '@storybook/server': '8.5.0-alpha.10', + '@storybook/svelte': '8.5.0-alpha.10', + '@storybook/vue3': '8.5.0-alpha.10', + '@storybook/web-components': '8.5.0-alpha.10', }; diff --git a/code/core/src/components/components/tooltip/TooltipLinkList.tsx b/code/core/src/components/components/tooltip/TooltipLinkList.tsx index 263c91d5bfa6..91e86eae71af 100644 --- a/code/core/src/components/components/tooltip/TooltipLinkList.tsx +++ b/code/core/src/components/components/tooltip/TooltipLinkList.tsx @@ -1,5 +1,5 @@ -import type { ComponentProps, SyntheticEvent } from 'react'; -import React, { useCallback } from 'react'; +import type { ComponentProps, ReactNode, SyntheticEvent } from 'react'; +import React, { Fragment, useCallback } from 'react'; import { styled } from '@storybook/core/theming'; @@ -15,7 +15,8 @@ const List = styled.div( }, ({ theme }) => ({ borderRadius: theme.appBorderRadius + 2, - }) + }), + ({ theme }) => (theme.base === 'dark' ? { background: theme.background.content } : {}) ); const Group = styled.div(({ theme }) => ({ @@ -25,7 +26,7 @@ const Group = styled.div(({ theme }) => ({ }, })); -export interface Link extends Omit { +export interface NormalLink extends Omit { id: string; onClick?: ( event: SyntheticEvent, @@ -33,7 +34,18 @@ export interface Link extends Omit { ) => void; } -interface ItemProps extends Link { +export type Link = CustomLink | NormalLink; + +/** + * This is a custom link that can be used in the `TooltipLinkList` component. It allows for custom + * content to be rendered in the list; it does not have to be a link. + */ +interface CustomLink { + id: string; + content: ReactNode; +} + +interface ItemProps extends NormalLink { isIndented?: boolean; } @@ -55,7 +67,7 @@ export interface TooltipLinkListProps extends ComponentProps { export const TooltipLinkList = ({ links, LinkWrapper, ...props }: TooltipLinkListProps) => { const groups = Array.isArray(links[0]) ? (links as Link[][]) : [links as Link[]]; - const isIndented = groups.some((group) => group.some((link) => link.icon)); + const isIndented = groups.some((group) => group.some((link) => 'icon' in link && link.icon)); return ( {groups @@ -63,9 +75,14 @@ export const TooltipLinkList = ({ links, LinkWrapper, ...props }: TooltipLinkLis .map((group, index) => { return ( link.id).join(`~${index}~`)}> - {group.map((link) => ( - - ))} + {group.map((link) => { + if ('content' in link) { + return {link.content}; + } + return ( + + ); + })} ); })} diff --git a/code/core/src/components/components/tooltip/WithTooltip.tsx b/code/core/src/components/components/tooltip/WithTooltip.tsx index ace6ac6ea275..c6bddae93795 100644 --- a/code/core/src/components/components/tooltip/WithTooltip.tsx +++ b/code/core/src/components/components/tooltip/WithTooltip.tsx @@ -121,7 +121,7 @@ const WithTooltipPure = ({ } ); - const tooltipComponent = ( + const tooltipComponent = isVisible ? ( onVisibleChange(false) }) : tooltip} - ); + ) : null; return ( <> diff --git a/code/core/src/core-events/data/testing-module.ts b/code/core/src/core-events/data/testing-module.ts index d9e9640935a1..48544c8669d4 100644 --- a/code/core/src/core-events/data/testing-module.ts +++ b/code/core/src/core-events/data/testing-module.ts @@ -8,22 +8,11 @@ export type TestProviderState = Addon_TestProviderState; export type TestProviders = Record; -export type TestingModuleRunRequestStories = { - id: string; - name: string; -}; - export type TestingModuleRunRequestPayload = { providerId: TestProviderId; - payload: { - stories: TestingModuleRunRequestStories[]; - importPath: string; - componentPath: string; - }[]; -}; - -export type TestingModuleRunAllRequestPayload = { - providerId: TestProviderId; + // TODO: Avoid needing to do a fetch request server-side to retrieve the index + indexUrl: string; // e.g. http://localhost:6006/index.json + storyIds?: string[]; // ['button--primary', 'button--secondary'] }; export type TestingModuleProgressReportPayload = diff --git a/code/core/src/core-events/index.ts b/code/core/src/core-events/index.ts index d5d51eeecdf4..f0b09f946607 100644 --- a/code/core/src/core-events/index.ts +++ b/code/core/src/core-events/index.ts @@ -88,7 +88,6 @@ enum events { TESTING_MODULE_CRASH_REPORT = 'testingModuleCrashReport', TESTING_MODULE_PROGRESS_REPORT = 'testingModuleProgressReport', TESTING_MODULE_RUN_REQUEST = 'testingModuleRunRequest', - TESTING_MODULE_RUN_ALL_REQUEST = 'testingModuleRunAllRequest', TESTING_MODULE_CANCEL_TEST_RUN_REQUEST = 'testingModuleCancelTestRunRequest', TESTING_MODULE_CANCEL_TEST_RUN_RESPONSE = 'testingModuleCancelTestRunResponse', TESTING_MODULE_WATCH_MODE_REQUEST = 'testingModuleWatchModeRequest', @@ -158,7 +157,6 @@ export const { TESTING_MODULE_CRASH_REPORT, TESTING_MODULE_PROGRESS_REPORT, TESTING_MODULE_RUN_REQUEST, - TESTING_MODULE_RUN_ALL_REQUEST, TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, TESTING_MODULE_CANCEL_TEST_RUN_RESPONSE, TESTING_MODULE_WATCH_MODE_REQUEST, diff --git a/code/core/src/csf-tools/vitest-plugin/transformer.ts b/code/core/src/csf-tools/vitest-plugin/transformer.ts index 677235975cb1..c318faa1d29e 100644 --- a/code/core/src/csf-tools/vitest-plugin/transformer.ts +++ b/code/core/src/csf-tools/vitest-plugin/transformer.ts @@ -19,11 +19,14 @@ type TagsFilter = { }; const isValidTest = (storyTags: string[], tagsFilter: TagsFilter) => { - const isIncluded = - tagsFilter?.include.length === 0 || tagsFilter?.include.some((tag) => storyTags.includes(tag)); - const isNotExcluded = tagsFilter?.exclude.every((tag) => !storyTags.includes(tag)); - - return isIncluded && isNotExcluded; + if (tagsFilter.include.length && !tagsFilter.include.some((tag) => storyTags?.includes(tag))) { + return false; + } + if (tagsFilter.exclude.some((tag) => storyTags?.includes(tag))) { + return false; + } + // Skipped tests are intentionally included here + return true; }; /** * TODO: the functionality in this file can be moved back to the vitest plugin itself It can use diff --git a/code/core/src/manager-api/lib/store-setup.ts b/code/core/src/manager-api/lib/store-setup.ts index 291898bede0a..9928ae09c8fc 100644 --- a/code/core/src/manager-api/lib/store-setup.ts +++ b/code/core/src/manager-api/lib/store-setup.ts @@ -4,8 +4,13 @@ import { parse, stringify } from 'telejson'; // setting up the store, overriding set and get to use telejson export default (_: any) => { _.fn('set', function (key: string, data: object) { - // @ts-expect-error('this' implicitly has type 'any') - return _.set(this._area, this._in(key), stringify(data, { maxDepth: 50 })); + return _.set( + // @ts-expect-error('this' implicitly has type 'any') + this._area, + // @ts-expect-error('this' implicitly has type 'any') + this._in(key), + stringify(data, { maxDepth: 50, allowFunction: false }) + ); }); _.fn('get', function (key: string, alt: string) { // @ts-expect-error('this' implicitly has type 'any') diff --git a/code/core/src/manager-api/modules/addons.ts b/code/core/src/manager-api/modules/addons.ts index c620792e4fee..16a35fcfc9ad 100644 --- a/code/core/src/manager-api/modules/addons.ts +++ b/code/core/src/manager-api/modules/addons.ts @@ -30,6 +30,7 @@ export interface SubAPI { | Addon_Types | Addon_TypesEnum.experimental_PAGE | Addon_TypesEnum.experimental_SIDEBAR_BOTTOM + | Addon_TypesEnum.experimental_TEST_PROVIDER | Addon_TypesEnum.experimental_SIDEBAR_TOP = Addon_Types, >( type: T diff --git a/code/core/src/manager-api/modules/experimental_testmodule.ts b/code/core/src/manager-api/modules/experimental_testmodule.ts new file mode 100644 index 000000000000..fd5fb5e724f3 --- /dev/null +++ b/code/core/src/manager-api/modules/experimental_testmodule.ts @@ -0,0 +1,141 @@ +import { Addon_TypesEnum, type StoryId } from '@storybook/core/types'; + +import { + TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, + TESTING_MODULE_RUN_REQUEST, + TESTING_MODULE_WATCH_MODE_REQUEST, + type TestProviderId, + type TestProviderState, + type TestProviders, + type TestingModuleRunRequestPayload, +} from '@storybook/core/core-events'; + +import invariant from 'tiny-invariant'; + +import type { ModuleFn } from '../lib/types'; + +export type SubState = { + testProviders: TestProviders; +}; + +const initialTestProviderState: TestProviderState = { + details: {} as { [key: string]: any }, + cancellable: false, + cancelling: false, + running: false, + watching: false, + failed: false, + crashed: false, +}; + +interface RunOptions { + entryId?: StoryId; +} + +export type SubAPI = { + getTestProviderState(id: string): TestProviderState | undefined; + updateTestProviderState(id: TestProviderId, update: Partial): void; + clearTestProviderState(id: TestProviderId): void; + runTestProvider(id: TestProviderId, options?: RunOptions): () => void; + setTestProviderWatchMode(id: TestProviderId, watchMode: boolean): void; + cancelTestProvider(id: TestProviderId): void; +}; + +export const init: ModuleFn = ({ store, fullAPI }) => { + const state: SubState = { + testProviders: store.getState().testProviders || {}, + }; + + const api: SubAPI = { + getTestProviderState(id) { + const { testProviders } = store.getState(); + + return testProviders?.[id]; + }, + updateTestProviderState(id, update) { + return store.setState( + ({ testProviders }) => { + return { testProviders: { ...testProviders, [id]: { ...testProviders[id], ...update } } }; + }, + { persistence: 'session' } + ); + }, + clearTestProviderState(id) { + const update = { + cancelling: false, + running: true, + failed: false, + crashed: false, + progress: undefined, + }; + return store.setState( + ({ testProviders }) => { + return { testProviders: { ...testProviders, [id]: { ...testProviders[id], ...update } } }; + }, + { persistence: 'session' } + ); + }, + runTestProvider(id, options) { + const index = store.getState().index; + invariant(index, 'The index is currently unavailable'); + + const indexUrl = new URL('index.json', window.location.href).toString(); + + if (!options?.entryId) { + const payload: TestingModuleRunRequestPayload = { + providerId: id, + indexUrl, + }; + fullAPI.emit(TESTING_MODULE_RUN_REQUEST, payload); + return () => api.cancelTestProvider(id); + } + + const entry = index[options.entryId]; + invariant(entry, `No entry found in the index for id '${options.entryId}'`); + + const findStories = (entryId: StoryId, results: StoryId[] = []): StoryId[] => { + const node = index[entryId]; + if (node.type === 'story') { + results.push(node.id); + } else if ('children' in node) { + node.children.forEach((childId) => findStories(childId, results)); + } + return results; + }; + + const payload: TestingModuleRunRequestPayload = { + providerId: id, + indexUrl, + storyIds: findStories(options.entryId), + }; + fullAPI.emit(TESTING_MODULE_RUN_REQUEST, payload); + return () => api.cancelTestProvider(id); + }, + setTestProviderWatchMode(id, watchMode) { + api.updateTestProviderState(id, { watching: watchMode }); + fullAPI.emit(TESTING_MODULE_WATCH_MODE_REQUEST, { providerId: id, watchMode }); + }, + cancelTestProvider(id) { + api.updateTestProviderState(id, { cancelling: true }); + fullAPI.emit(TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, { providerId: id }); + }, + }; + + const initModule = async () => { + const initialState: TestProviders = Object.fromEntries( + Object.entries(fullAPI.getElements(Addon_TypesEnum.experimental_TEST_PROVIDER)).map( + ([id, config]) => [ + id, + { + ...config, + ...initialTestProviderState, + ...(state?.testProviders?.[id] || {}), + } as TestProviders[0], + ] + ) + ); + + store.setState({ testProviders: initialState }, { persistence: 'session' }); + }; + return { init: initModule, state, api }; +}; diff --git a/code/core/src/manager-api/root.tsx b/code/core/src/manager-api/root.tsx index 1c150b47f4b3..c2784329ab8f 100644 --- a/code/core/src/manager-api/root.tsx +++ b/code/core/src/manager-api/root.tsx @@ -50,6 +50,7 @@ import { noArrayMerge } from './lib/merge'; import type { ModuleFn } from './lib/types'; import * as addons from './modules/addons'; import * as channel from './modules/channel'; +import * as testProviders from './modules/experimental_testmodule'; import * as globals from './modules/globals'; import * as layout from './modules/layout'; import * as notifications from './modules/notifications'; @@ -79,6 +80,7 @@ export type State = layout.SubState & stories.SubState & refs.SubState & notifications.SubState & + testProviders.SubState & version.SubState & url.SubState & shortcuts.SubState & @@ -98,6 +100,7 @@ export type API = addons.SubAPI & globals.SubAPI & layout.SubAPI & notifications.SubAPI & + testProviders.SubAPI & shortcuts.SubAPI & settings.SubAPI & version.SubAPI & @@ -178,6 +181,7 @@ class ManagerProvider extends Component { addons, layout, notifications, + testProviders, settings, shortcuts, stories, diff --git a/code/core/src/manager-api/version.ts b/code/core/src/manager-api/version.ts index 238310acedb1..26d454c9f636 100644 --- a/code/core/src/manager-api/version.ts +++ b/code/core/src/manager-api/version.ts @@ -1 +1 @@ -export const version = '8.5.0-alpha.3'; +export const version = '8.5.0-alpha.10'; diff --git a/code/core/src/manager/components/mobile/navigation/MobileNavigation.tsx b/code/core/src/manager/components/mobile/navigation/MobileNavigation.tsx index fdc7de9651db..ddef2c0f2de4 100644 --- a/code/core/src/manager/components/mobile/navigation/MobileNavigation.tsx +++ b/code/core/src/manager/components/mobile/navigation/MobileNavigation.tsx @@ -4,6 +4,7 @@ import React from 'react'; import { IconButton } from '@storybook/core/components'; import { styled } from '@storybook/core/theming'; import { BottomBarToggleIcon, MenuIcon } from '@storybook/icons'; +import type { API_IndexHash, API_Refs } from '@storybook/types'; import { useStorybookApi, useStorybookState } from '@storybook/core/manager-api'; @@ -17,27 +18,46 @@ interface MobileNavigationProps { showPanel: boolean; } +// Function to combine all indexes +function combineIndexes(rootIndex: API_IndexHash | undefined, refs: API_Refs) { + // Create a copy of the root index to avoid mutation + const combinedIndex = { ...(rootIndex || {}) }; // Use an empty object as fallback + + // Traverse refs and merge each nested index with the root index + Object.values(refs).forEach((ref) => { + if (ref.index) { + Object.assign(combinedIndex, ref.index); + } + }); + + return combinedIndex; +} + /** * Walks the tree from the current story to combine story+component+folder names into a single * string */ const useFullStoryName = () => { - const { index } = useStorybookState(); + const { index, refs } = useStorybookState(); const api = useStorybookApi(); const currentStory = api.getCurrentStoryData(); if (!currentStory) { return ''; } - + const combinedIndex = combineIndexes(index, refs || {}); let fullStoryName = currentStory.renderLabel?.(currentStory, api) || currentStory.name; - // @ts-expect-error (non strict) - let node = index[currentStory.id]; - // @ts-expect-error (non strict) - while ('parent' in node && node.parent && index[node.parent] && fullStoryName.length < 24) { - // @ts-expect-error (non strict) - node = index[node.parent]; + let node = combinedIndex[currentStory.id]; + + while ( + node && + 'parent' in node && + node.parent && + combinedIndex[node.parent] && + fullStoryName.length < 24 + ) { + node = combinedIndex[node.parent]; const parentName = node.renderLabel?.(node, api) || node.name; fullStoryName = `${parentName}/${fullStoryName}`; } diff --git a/code/core/src/manager/components/sidebar/ContextMenu.tsx b/code/core/src/manager/components/sidebar/ContextMenu.tsx new file mode 100644 index 000000000000..867ed8da72b7 --- /dev/null +++ b/code/core/src/manager/components/sidebar/ContextMenu.tsx @@ -0,0 +1,121 @@ +import type { ComponentProps, FC, SyntheticEvent } from 'react'; +import React, { useMemo, useState } from 'react'; + +import { TooltipLinkList, WithTooltip } from '@storybook/core/components'; +import { type API_HashEntry, Addon_TypesEnum } from '@storybook/core/types'; +import { EllipsisIcon } from '@storybook/icons'; + +import { type TestProviders } from '@storybook/core/core-events'; +import { useStorybookState } from '@storybook/core/manager-api'; +import type { API } from '@storybook/core/manager-api'; + +import type { Link } from '../../../components/components/tooltip/TooltipLinkList'; +import { StatusButton } from './StatusButton'; +import type { ExcludesNull } from './Tree'; +import { ContextMenu } from './Tree'; + +export const useContextMenu = (context: API_HashEntry, links: Link[], api: API) => { + const [hoverCount, setHoverCount] = useState(0); + const [isOpen, setIsOpen] = useState(false); + + const handlers = useMemo(() => { + return { + onMouseEnter: () => { + setHoverCount((c) => c + 1); + }, + onOpen: (event: SyntheticEvent) => { + event.stopPropagation(); + setIsOpen(true); + }, + onClose: () => { + setIsOpen(false); + }, + }; + }, []); + + /** + * Calculate the providerLinks whenever the user mouses over the container. We use an incrementer, + * instead of a simple boolean to ensure that the links are recalculated + */ + const providerLinks = useMemo(() => { + const testProviders = api.getElements( + Addon_TypesEnum.experimental_TEST_PROVIDER + ) as any as TestProviders; + + if (hoverCount) { + return generateTestProviderLinks(testProviders, context); + } + return []; + }, [api, context, hoverCount]); + + const isRendered = providerLinks.length > 0 || links.length > 0; + + return useMemo(() => { + return { + onMouseEnter: handlers.onMouseEnter, + node: isRendered ? ( + { + if (!visible) { + handlers.onClose(); + } else { + setIsOpen(true); + } + }} + tooltip={({ onHide }) => ( + + )} + > + + + + + ) : null, + }; + }, [context, handlers, isOpen, isRendered, links]); +}; + +/** + * This component re-subscribes to storybook's core state, hence the Live prefix. It is used to + * render the context menu for the sidebar. it self is a tooltip link list that renders the links + * provided to it. In addition to the links, it also renders the test providers. + */ +const LiveContextMenu: FC<{ context: API_HashEntry } & ComponentProps> = ({ + context, + links, + ...rest +}) => { + const { testProviders } = useStorybookState(); + const providerLinks: Link[] = generateTestProviderLinks(testProviders, context); + const groups = Array.isArray(links[0]) ? (links as Link[][]) : [links as Link[]]; + const all = groups.concat([providerLinks]); + + return ; +}; + +export function generateTestProviderLinks( + testProviders: TestProviders, + context: API_HashEntry +): Link[] { + return Object.entries(testProviders) + .map(([testProviderId, state]) => { + if (!state) { + return null; + } + const content = state.sidebarContextMenu?.({ context, state }); + + if (!content) { + return null; + } + + return { + id: testProviderId, + content, + }; + }) + .filter(Boolean as any as ExcludesNull); +} diff --git a/code/core/src/manager/components/sidebar/FileSearchList.stories.tsx b/code/core/src/manager/components/sidebar/FileSearchList.stories.tsx index 2c5ec140ee86..7388bf3cb4ab 100644 --- a/code/core/src/manager/components/sidebar/FileSearchList.stories.tsx +++ b/code/core/src/manager/components/sidebar/FileSearchList.stories.tsx @@ -5,6 +5,7 @@ import { FileSearchList } from './FileSearchList'; const meta = { component: FileSearchList, + title: 'Sidebar/FileSearchList', args: { onNewStory: fn(), }, diff --git a/code/core/src/manager/components/sidebar/FileSearchListSkeleton.stories.tsx b/code/core/src/manager/components/sidebar/FileSearchListSkeleton.stories.tsx index eaeaca9c0f75..d8d38eeb6881 100644 --- a/code/core/src/manager/components/sidebar/FileSearchListSkeleton.stories.tsx +++ b/code/core/src/manager/components/sidebar/FileSearchListSkeleton.stories.tsx @@ -4,6 +4,7 @@ import { FileSearchListLoadingSkeleton } from './FileSearchListSkeleton'; const meta = { component: FileSearchListLoadingSkeleton, + title: 'Sidebar/FileSearchListLoadingSkeleton', } satisfies Meta; export default meta; diff --git a/code/core/src/manager/components/sidebar/FileSearchModal.stories.tsx b/code/core/src/manager/components/sidebar/FileSearchModal.stories.tsx index a2a10005b887..c9e1790ef118 100644 --- a/code/core/src/manager/components/sidebar/FileSearchModal.stories.tsx +++ b/code/core/src/manager/components/sidebar/FileSearchModal.stories.tsx @@ -8,6 +8,7 @@ import { FileSearchModal } from './FileSearchModal'; const meta = { component: FileSearchModal, + title: 'Sidebar/FileSearchModal', args: { open: true, setError: fn(), diff --git a/code/core/src/manager/components/sidebar/FilterToggle.stories.ts b/code/core/src/manager/components/sidebar/FilterToggle.stories.ts index 6710af80c37c..075b8c94dc9a 100644 --- a/code/core/src/manager/components/sidebar/FilterToggle.stories.ts +++ b/code/core/src/manager/components/sidebar/FilterToggle.stories.ts @@ -4,6 +4,7 @@ import { FilterToggle } from './FilterToggle'; export default { component: FilterToggle, + title: 'Sidebar/FilterToggle', args: { active: false, onClick: fn(), diff --git a/code/core/src/manager/components/sidebar/IconSymbols.stories.tsx b/code/core/src/manager/components/sidebar/IconSymbols.stories.tsx index 76136230d3d8..143c08932d37 100644 --- a/code/core/src/manager/components/sidebar/IconSymbols.stories.tsx +++ b/code/core/src/manager/components/sidebar/IconSymbols.stories.tsx @@ -4,6 +4,7 @@ import { IconSymbols } from './IconSymbols'; const meta = { component: IconSymbols, + title: 'Sidebar/IconSymbols', } satisfies Meta; export default meta; diff --git a/code/core/src/manager/components/sidebar/LegacyRender.tsx b/code/core/src/manager/components/sidebar/LegacyRender.tsx new file mode 100644 index 000000000000..f0e74f460219 --- /dev/null +++ b/code/core/src/manager/components/sidebar/LegacyRender.tsx @@ -0,0 +1,89 @@ +import React from 'react'; + +import { Button } from '@storybook/core/components'; +import { styled } from '@storybook/core/theming'; +import { EyeIcon, PlayHollowIcon, StopAltHollowIcon } from '@storybook/icons'; + +import type { TestProviders } from '@storybook/core/core-events'; +import { useStorybookApi } from '@storybook/core/manager-api'; + +const Info = styled.div({ + display: 'flex', + flexDirection: 'column', + marginLeft: 6, +}); + +const Actions = styled.div({ + display: 'flex', + gap: 6, +}); + +const TitleWrapper = styled.div<{ crashed?: boolean }>(({ crashed, theme }) => ({ + fontSize: theme.typography.size.s1, + fontWeight: crashed ? 'bold' : 'normal', + color: crashed ? theme.color.negativeText : theme.color.defaultText, +})); + +const DescriptionWrapper = styled.div(({ theme }) => ({ + fontSize: theme.typography.size.s1, + color: theme.barTextColor, +})); + +export const LegacyRender = ({ ...state }: TestProviders[keyof TestProviders]) => { + const Description = state.description!; + const Title = state.title!; + const api = useStorybookApi(); + + return ( + <> + + + + </TitleWrapper> + <DescriptionWrapper id="testing-module-description"> + <Description {...state} /> + </DescriptionWrapper> + </Info> + + <Actions> + {state.watchable && ( + <Button + aria-label={`${state.watching ? 'Disable' : 'Enable'} watch mode for ${name}`} + variant="ghost" + padding="small" + active={state.watching} + onClick={() => api.setTestProviderWatchMode(state.id, !state.watching)} + disabled={state.crashed || state.running} + > + <EyeIcon /> + </Button> + )} + {state.runnable && ( + <> + {state.running && state.cancellable ? ( + <Button + aria-label={`Stop ${name}`} + variant="ghost" + padding="small" + onClick={() => api.cancelTestProvider(state.id)} + disabled={state.cancelling} + > + <StopAltHollowIcon /> + </Button> + ) : ( + <Button + aria-label={`Start ${state.name}`} + variant="ghost" + padding="small" + onClick={() => api.runTestProvider(state.id)} + disabled={state.crashed || state.running} + > + <PlayHollowIcon /> + </Button> + )} + </> + )} + </Actions> + </> + ); +}; diff --git a/code/core/src/manager/components/sidebar/Menu.tsx b/code/core/src/manager/components/sidebar/Menu.tsx index 583a2b982616..aef385c2de1d 100644 --- a/code/core/src/manager/components/sidebar/Menu.tsx +++ b/code/core/src/manager/components/sidebar/Menu.tsx @@ -1,7 +1,7 @@ import type { ComponentProps, FC } from 'react'; -import React, { useMemo, useState } from 'react'; +import React, { useState } from 'react'; -import type { Button, TooltipLinkListLink } from '@storybook/core/components'; +import type { Button } from '@storybook/core/components'; import { IconButton, TooltipLinkList, WithTooltip } from '@storybook/core/components'; import { styled } from '@storybook/core/theming'; import { CloseIcon, CogIcon } from '@storybook/icons'; @@ -55,28 +55,11 @@ const MenuButtonGroup = styled.div({ gap: 4, }); -type ClickHandler = TooltipLinkListLink['onClick']; - const SidebarMenuList: FC<{ menu: MenuList; - onHide: () => void; -}> = ({ menu, onHide }) => { - const links = useMemo( - () => - menu.map((group) => - group.map(({ onClick, ...rest }) => ({ - ...rest, - onClick: ((event, item) => { - if (onClick) { - onClick(event, item); - } - onHide(); - }) as ClickHandler, - })) - ), - [menu, onHide] - ); - return <TooltipLinkList links={links} />; + onClick: () => void; +}> = ({ menu, onClick }) => { + return <TooltipLinkList links={menu} onClick={onClick} />; }; export interface SidebarMenuProps { @@ -118,7 +101,7 @@ export const SidebarMenu: FC<SidebarMenuProps> = ({ menu, isHighlighted, onClick <WithTooltip placement="top" closeOnOutsideClick - tooltip={({ onHide }) => <SidebarMenuList onHide={onHide} menu={menu} />} + tooltip={({ onHide }) => <SidebarMenuList onClick={onHide} menu={menu} />} onVisibleChange={setIsTooltipVisible} > <SidebarIconButton diff --git a/code/core/src/manager/components/sidebar/RefIndicator.tsx b/code/core/src/manager/components/sidebar/RefIndicator.tsx index a6f01155a3d4..2a2e54b37dfa 100644 --- a/code/core/src/manager/components/sidebar/RefIndicator.tsx +++ b/code/core/src/manager/components/sidebar/RefIndicator.tsx @@ -21,12 +21,13 @@ import { useStorybookApi } from '@storybook/core/manager-api'; import { transparentize } from 'polished'; +import type { NormalLink } from '../../../components/components/tooltip/TooltipLinkList'; import type { getStateType } from '../../utils/tree'; import type { RefType } from './types'; const { document, window: globalWindow } = global; -export type ClickHandler = TooltipLinkListLink['onClick']; +export type ClickHandler = NormalLink['onClick']; export interface IndicatorIconProps { type: ReturnType<typeof getStateType>; } diff --git a/code/core/src/manager/components/sidebar/Refs.stories.tsx b/code/core/src/manager/components/sidebar/Refs.stories.tsx index a26cad976dcb..a042970beadc 100644 --- a/code/core/src/manager/components/sidebar/Refs.stories.tsx +++ b/code/core/src/manager/components/sidebar/Refs.stories.tsx @@ -1,5 +1,7 @@ import React from 'react'; +import { fn } from '@storybook/test'; + import { ManagerContext } from '@storybook/core/manager-api'; import { standardData as standardHeaderData } from './Heading.stories'; @@ -8,6 +10,15 @@ import { Ref } from './Refs'; import { mockDataset } from './mockdata'; import type { RefType } from './types'; +const managerContext = { + state: { docsOptions: {}, testProviders: {} }, + api: { + on: fn().mockName('api::on'), + off: fn().mockName('api::off'), + getElements: fn(() => ({})), + }, +} as any; + export default { component: Ref, title: 'Sidebar/Refs', @@ -16,7 +27,7 @@ export default { globals: { sb_theme: 'side-by-side' }, decorators: [ (storyFn: any) => ( - <ManagerContext.Provider value={{ state: { docsOptions: {} } } as any}> + <ManagerContext.Provider value={managerContext}> <IconSymbols /> {storyFn()} </ManagerContext.Provider> diff --git a/code/core/src/manager/components/sidebar/Sidebar.stories.tsx b/code/core/src/manager/components/sidebar/Sidebar.stories.tsx index dcc6b06096c2..53f22957f17d 100644 --- a/code/core/src/manager/components/sidebar/Sidebar.stories.tsx +++ b/code/core/src/manager/components/sidebar/Sidebar.stories.tsx @@ -33,6 +33,7 @@ const managerContext: any = { autodocs: 'tag', docsMode: false, }, + testProviders: {}, }, api: { emit: fn().mockName('api::emit'), diff --git a/code/core/src/manager/components/sidebar/Sidebar.tsx b/code/core/src/manager/components/sidebar/Sidebar.tsx index bb3be73f425d..d4784cc8c562 100644 --- a/code/core/src/manager/components/sidebar/Sidebar.tsx +++ b/code/core/src/manager/components/sidebar/Sidebar.tsx @@ -24,7 +24,6 @@ import { Search } from './Search'; import { SearchResults } from './SearchResults'; import { SidebarBottom } from './SidebarBottom'; import { TagsFilter } from './TagsFilter'; -import { TEST_PROVIDER_ID } from './Tree'; import type { CombinedDataset, Selection } from './types'; import { useLastViewed } from './useLastViewed'; diff --git a/code/core/src/manager/components/sidebar/SidebarBottom.stories.tsx b/code/core/src/manager/components/sidebar/SidebarBottom.stories.tsx index 8d7d2c42f488..e09d0cafb62b 100644 --- a/code/core/src/manager/components/sidebar/SidebarBottom.stories.tsx +++ b/code/core/src/manager/components/sidebar/SidebarBottom.stories.tsx @@ -1,37 +1,68 @@ +import React from 'react'; + import { Addon_TypesEnum } from '@storybook/core/types'; +import type { Meta } from '@storybook/react'; import { fn } from '@storybook/test'; +import { type API, ManagerContext } from '@storybook/core/manager-api'; + import { SidebarBottomBase } from './SidebarBottom'; +const managerContext: any = { + state: { + docsOptions: { + defaultName: 'Docs', + autodocs: 'tag', + docsMode: false, + }, + testProviders: { + 'component-tests': { + type: Addon_TypesEnum.experimental_TEST_PROVIDER, + id: 'component-tests', + title: () => 'Component tests', + description: () => 'Ran 2 seconds ago', + runnable: true, + watchable: true, + }, + 'visual-tests': { + type: Addon_TypesEnum.experimental_TEST_PROVIDER, + id: 'visual-tests', + title: () => 'Visual tests', + description: () => 'Not run', + runnable: true, + }, + }, + }, + api: { + on: fn().mockName('api::on'), + off: fn().mockName('api::off'), + updateTestProviderState: fn(), + }, +}; + export default { component: SidebarBottomBase, + title: 'Sidebar/SidebarBottom', args: { isDevelopment: true, + api: { + on: fn(), + off: fn(), clearNotification: fn(), + updateTestProviderState: fn(), emit: fn(), experimental_setFilter: fn(), getChannel: fn(), - getElements: fn(() => ({ - 'component-tests': { - type: Addon_TypesEnum.experimental_TEST_PROVIDER, - id: 'component-tests', - title: () => 'Component tests', - description: () => 'Ran 2 seconds ago', - runnable: true, - watchable: true, - }, - 'visual-tests': { - type: Addon_TypesEnum.experimental_TEST_PROVIDER, - id: 'visual-tests', - title: () => 'Visual tests', - description: () => 'Not run', - runnable: true, - }, - })), - }, + getElements: fn(() => ({})), + } as any as API, }, -}; + decorators: [ + (storyFn) => ( + <ManagerContext.Provider value={managerContext}>{storyFn()}</ManagerContext.Provider> + ), + ], +} as Meta<typeof SidebarBottomBase>; export const Errors = { args: { diff --git a/code/core/src/manager/components/sidebar/SidebarBottom.tsx b/code/core/src/manager/components/sidebar/SidebarBottom.tsx index f6aae845bee3..ccad267e2125 100644 --- a/code/core/src/manager/components/sidebar/SidebarBottom.tsx +++ b/code/core/src/manager/components/sidebar/SidebarBottom.tsx @@ -1,17 +1,12 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { styled } from '@storybook/core/theming'; -import { type API_FilterFunction, Addon_TypesEnum } from '@storybook/core/types'; +import { type API_FilterFunction } from '@storybook/core/types'; import { - TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, TESTING_MODULE_CRASH_REPORT, TESTING_MODULE_PROGRESS_REPORT, - TESTING_MODULE_RUN_ALL_REQUEST, - TESTING_MODULE_WATCH_MODE_REQUEST, - type TestProviderId, type TestProviderState, - type TestProviders, type TestingModuleCrashReportPayload, type TestingModuleProgressReportPayload, } from '@storybook/core/core-events'; @@ -105,17 +100,7 @@ export const SidebarBottomBase = ({ const wrapperRef = useRef<HTMLDivElement | null>(null); const [warningsActive, setWarningsActive] = useState(false); const [errorsActive, setErrorsActive] = useState(false); - const [testProviders, setTestProviders] = useState<TestProviders>(() => { - let sessionState: TestProviders = {}; - try { - sessionState = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || '{}'); - } catch (_) {} - return Object.fromEntries( - Object.entries(api.getElements(Addon_TypesEnum.experimental_TEST_PROVIDER)).map( - ([id, config]) => [id, { ...config, ...initialTestProviderState, ...sessionState[id] }] - ) - ); - }); + const { testProviders } = useStorybookState(); const warnings = Object.values(status).filter((statusByAddonId) => Object.values(statusByAddonId).some((value) => value?.status === 'warn') @@ -126,55 +111,6 @@ export const SidebarBottomBase = ({ const hasWarnings = warnings.length > 0; const hasErrors = errors.length > 0; - const updateTestProvider = useCallback( - (id: TestProviderId, update: Partial<TestProviderState>) => - setTestProviders((state) => { - const newValue = { ...state, [id]: { ...state[id], ...update } }; - sessionStorage.setItem(STORAGE_KEY, JSON.stringify(newValue)); - return newValue; - }), - [] - ); - - const clearState = useCallback( - ({ providerId }: { providerId: TestProviderId }) => { - updateTestProvider(providerId, { - cancelling: false, - running: true, - failed: false, - crashed: false, - progress: undefined, - }); - api.experimental_updateStatus(providerId, (state = {}) => - Object.fromEntries(Object.keys(state).map((key) => [key, null])) - ); - }, - [api, updateTestProvider] - ); - - const onRunTests = useCallback( - (id: TestProviderId) => { - api.emit(TESTING_MODULE_RUN_ALL_REQUEST, { providerId: id }); - }, - [api] - ); - - const onCancelTests = useCallback( - (id: TestProviderId) => { - updateTestProvider(id, { cancelling: true }); - api.emit(TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, { providerId: id }); - }, - [api, updateTestProvider] - ); - - const onSetWatchMode = useCallback( - (providerId: string, watchMode: boolean) => { - updateTestProvider(providerId, { watching: watchMode }); - api.emit(TESTING_MODULE_WATCH_MODE_REQUEST, { providerId, watchMode }); - }, - [api, updateTestProvider] - ); - useEffect(() => { const spacer = spacerRef.current; const wrapper = wrapperRef.current; @@ -196,15 +132,20 @@ export const SidebarBottomBase = ({ useEffect(() => { const onCrashReport = ({ providerId, ...details }: TestingModuleCrashReportPayload) => { - updateTestProvider(providerId, { details, running: false, crashed: true, watching: false }); + api.updateTestProviderState(providerId, { + details, + running: false, + crashed: true, + watching: false, + }); }; const onProgressReport = ({ providerId, ...result }: TestingModuleProgressReportPayload) => { if (result.status === 'failed') { - updateTestProvider(providerId, { ...result, running: false, failed: true }); + api.updateTestProviderState(providerId, { ...result, running: false, failed: true }); } else { const update = { ...result, running: result.status === 'pending' }; - updateTestProvider(providerId, update); + api.updateTestProviderState(providerId, update); const { mapStatusUpdate, ...state } = testProviders[providerId]; const statusUpdate = mapStatusUpdate?.({ ...state, ...update }); @@ -214,18 +155,16 @@ export const SidebarBottomBase = ({ } }; - api.getChannel()?.on(TESTING_MODULE_CRASH_REPORT, onCrashReport); - api.getChannel()?.on(TESTING_MODULE_RUN_ALL_REQUEST, clearState); - api.getChannel()?.on(TESTING_MODULE_PROGRESS_REPORT, onProgressReport); + api.on(TESTING_MODULE_CRASH_REPORT, onCrashReport); + api.on(TESTING_MODULE_PROGRESS_REPORT, onProgressReport); return () => { - api.getChannel()?.off(TESTING_MODULE_CRASH_REPORT, onCrashReport); - api.getChannel()?.off(TESTING_MODULE_PROGRESS_REPORT, onProgressReport); - api.getChannel()?.off(TESTING_MODULE_RUN_ALL_REQUEST, clearState); + api.off(TESTING_MODULE_CRASH_REPORT, onCrashReport); + api.off(TESTING_MODULE_PROGRESS_REPORT, onProgressReport); }; - }, [api, testProviders, updateTestProvider, clearState]); + }, [api, testProviders]); - const testProvidersArray = Object.values(testProviders); + const testProvidersArray = Object.values(testProviders || {}); if (!hasWarnings && !hasErrors && !testProvidersArray.length && !notifications.length) { return null; } @@ -244,9 +183,6 @@ export const SidebarBottomBase = ({ warningCount: warnings.length, warningsActive, setWarningsActive, - onRunTests, - onCancelTests, - onSetWatchMode, }} /> )} diff --git a/code/core/src/manager/components/sidebar/StatusContext.tsx b/code/core/src/manager/components/sidebar/StatusContext.tsx index d143a3db9be5..45d57611693c 100644 --- a/code/core/src/manager/components/sidebar/StatusContext.tsx +++ b/code/core/src/manager/components/sidebar/StatusContext.tsx @@ -2,7 +2,8 @@ import { createContext, useContext } from 'react'; import type { API_StatusObject, API_StatusState, API_StatusValue, StoryId } from '@storybook/types'; -import type { StoriesHash } from '../../../manager-api'; +import type { StoriesHash } from '@storybook/core/manager-api'; + import type { Item } from '../../container/Sidebar'; import { getDescendantIds } from '../../utils/tree'; diff --git a/code/core/src/manager/components/sidebar/TagsFilter.stories.tsx b/code/core/src/manager/components/sidebar/TagsFilter.stories.tsx index 4050986a91f1..89236acda68a 100644 --- a/code/core/src/manager/components/sidebar/TagsFilter.stories.tsx +++ b/code/core/src/manager/components/sidebar/TagsFilter.stories.tsx @@ -5,6 +5,7 @@ import { TagsFilter } from './TagsFilter'; const meta = { component: TagsFilter, + title: 'Sidebar/TagsFilter', tags: ['haha'], args: { api: { diff --git a/code/core/src/manager/components/sidebar/TagsFilterPanel.stories.tsx b/code/core/src/manager/components/sidebar/TagsFilterPanel.stories.tsx index 999c5f3fdb04..0602d0ed7a43 100644 --- a/code/core/src/manager/components/sidebar/TagsFilterPanel.stories.tsx +++ b/code/core/src/manager/components/sidebar/TagsFilterPanel.stories.tsx @@ -5,6 +5,7 @@ import { TagsFilterPanel } from './TagsFilterPanel'; const meta = { component: TagsFilterPanel, + title: 'Sidebar/TagsFilterPanel', args: { toggleTag: fn(), api: { diff --git a/code/core/src/manager/components/sidebar/TestingModule.stories.tsx b/code/core/src/manager/components/sidebar/TestingModule.stories.tsx index bd24177ebefb..a13e4ccbad5d 100644 --- a/code/core/src/manager/components/sidebar/TestingModule.stories.tsx +++ b/code/core/src/manager/components/sidebar/TestingModule.stories.tsx @@ -5,6 +5,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { fn, userEvent } from '@storybook/test'; import type { TestProviders } from '@storybook/core/core-events'; +import { ManagerContext } from '@storybook/core/manager-api'; import { TestingModule } from './TestingModule'; @@ -23,8 +24,13 @@ const testProviders: TestProviders[keyof TestProviders][] = [ type: Addon_TypesEnum.experimental_TEST_PROVIDER, id: 'component-tests', name: 'Component tests', - title: () => 'Component tests', - description: () => 'Ran 2 seconds ago', + render: () => ( + <> + Component tests + <br /> + Ran 2 seconds ago + </> + ), runnable: true, watchable: true, ...baseState, @@ -33,8 +39,13 @@ const testProviders: TestProviders[keyof TestProviders][] = [ type: Addon_TypesEnum.experimental_TEST_PROVIDER, id: 'visual-tests', name: 'Visual tests', - title: () => 'Visual tests', - description: () => 'Not run', + render: () => ( + <> + Visual tests + <br /> + Not run + </> + ), runnable: true, ...baseState, }, @@ -42,15 +53,30 @@ const testProviders: TestProviders[keyof TestProviders][] = [ type: Addon_TypesEnum.experimental_TEST_PROVIDER, id: 'linting', name: 'Linting', - title: () => 'Linting', - description: () => 'Watching for changes', + render: () => ( + <> + Linting + <br /> + Watching for changes + </> + ), ...baseState, watching: true, }, ]; +const managerContext: any = { + api: { + runTestProvider: fn().mockName('api::runTestProvider'), + cancelTestProvider: fn().mockName('api::cancelTestProvider'), + updateTestProviderState: fn().mockName('api::updateTestProviderState'), + setTestProviderWatchMode: fn().mockName('api::setTestProviderWatchMode'), + }, +}; + const meta = { component: TestingModule, + title: 'Sidebar/TestingModule', args: { testProviders, errorCount: 0, @@ -59,11 +85,11 @@ const meta = { warningCount: 0, warningsActive: false, setWarningsActive: fn(), - onRunTests: fn(), - onCancelTests: fn(), - onSetWatchMode: fn(), }, decorators: [ + (storyFn) => ( + <ManagerContext.Provider value={managerContext}>{storyFn()}</ManagerContext.Provider> + ), (StoryFn) => ( <div style={{ maxWidth: 232 }}> <StoryFn /> @@ -180,8 +206,13 @@ export const Crashed: Story = { testProviders: [ { ...testProviders[0], - title: () => "Component tests didn't complete", - description: () => 'Problems!', + render: () => ( + <> + Component tests didn't complete + <br /> + Problems! + </> + ), crashed: true, }, ...testProviders.slice(1), diff --git a/code/core/src/manager/components/sidebar/TestingModule.tsx b/code/core/src/manager/components/sidebar/TestingModule.tsx index c020ebe53f09..a28a338857b8 100644 --- a/code/core/src/manager/components/sidebar/TestingModule.tsx +++ b/code/core/src/manager/components/sidebar/TestingModule.tsx @@ -1,18 +1,14 @@ import React, { type SyntheticEvent, useEffect, useRef, useState } from 'react'; import { Button, TooltipNote } from '@storybook/core/components'; +import { WithTooltip } from '@storybook/core/components'; import { keyframes, styled } from '@storybook/core/theming'; -import { - ChevronSmallUpIcon, - EyeIcon, - PlayAllHollowIcon, - PlayHollowIcon, - StopAltHollowIcon, -} from '@storybook/icons'; +import { ChevronSmallUpIcon, PlayAllHollowIcon } from '@storybook/icons'; import type { TestProviders } from '@storybook/core/core-events'; +import { useStorybookApi } from '@storybook/core/manager-api'; -import { WithTooltip } from '../../../components/components/tooltip/WithTooltip'; +import { LegacyRender } from './LegacyRender'; const DEFAULT_HEIGHT = 500; @@ -148,43 +144,6 @@ const TestProvider = styled.div({ gap: 6, }); -const Info = styled.div({ - display: 'flex', - flexDirection: 'column', - marginLeft: 6, -}); - -const Actions = styled.div({ - display: 'flex', - gap: 6, -}); - -const TitleWrapper = styled.div<{ crashed?: boolean }>(({ crashed, theme }) => ({ - fontSize: theme.typography.size.s1, - fontWeight: crashed ? 'bold' : 'normal', - color: crashed ? theme.color.negativeText : theme.color.defaultText, -})); - -const DescriptionWrapper = styled.div(({ theme }) => ({ - fontSize: theme.typography.size.s1, - color: theme.barTextColor, -})); - -const DynamicInfo = ({ state }: { state: TestProviders[keyof TestProviders] }) => { - const Description = state.description; - const Title = state.title; - return ( - <Info> - <TitleWrapper crashed={state.crashed}> - <Title {...state} /> - </TitleWrapper> - <DescriptionWrapper> - <Description {...state} /> - </DescriptionWrapper> - </Info> - ); -}; - interface TestingModuleProps { testProviders: TestProviders[keyof TestProviders][]; errorCount: number; @@ -193,9 +152,6 @@ interface TestingModuleProps { warningCount: number; warningsActive: boolean; setWarningsActive: (active: boolean) => void; - onRunTests: (providerId: string) => void; - onCancelTests: (providerId: string) => void; - onSetWatchMode: (providerId: string, watchMode: boolean) => void; } export const TestingModule = ({ @@ -206,10 +162,8 @@ export const TestingModule = ({ warningCount, warningsActive, setWarningsActive, - onRunTests, - onCancelTests, - onSetWatchMode, }: TestingModuleProps) => { + const api = useStorybookApi(); const contentRef = useRef<HTMLDivElement>(null); const [collapsed, setCollapsed] = useState(false); const [maxHeight, setMaxHeight] = useState(DEFAULT_HEIGHT); @@ -243,50 +197,14 @@ export const TestingModule = ({ }} > <Content ref={contentRef}> - {testProviders.map((state) => ( - <TestProvider key={state.id}> - <DynamicInfo state={state} /> - <Actions> - {state.watchable && ( - <Button - aria-label={`${state.watching ? 'Disable' : 'Enable'} watch mode for ${state.name}`} - variant="ghost" - padding="small" - active={state.watching} - onClick={() => onSetWatchMode(state.id, !state.watching)} - disabled={state.crashed || state.running} - > - <EyeIcon /> - </Button> - )} - {state.runnable && ( - <> - {state.running && state.cancellable ? ( - <Button - aria-label={`Stop ${state.name}`} - variant="ghost" - padding="small" - onClick={() => onCancelTests(state.id)} - disabled={state.cancelling} - > - <StopAltHollowIcon /> - </Button> - ) : ( - <Button - aria-label={`Start ${state.name}`} - variant="ghost" - padding="small" - onClick={() => onRunTests(state.id)} - disabled={state.crashed || state.running} - > - <PlayHollowIcon /> - </Button> - )} - </> - )} - </Actions> - </TestProvider> - ))} + {testProviders.map((state) => { + const { render: Render } = state; + return ( + <TestProvider key={state.id} data-module-id={state.id}> + {Render ? <Render {...state} /> : <LegacyRender {...state} />} + </TestProvider> + ); + })} </Content> </Collapsible> @@ -299,7 +217,7 @@ export const TestingModule = ({ e.stopPropagation(); testProviders .filter((state) => !state.crashed && !state.running && state.runnable) - .forEach(({ id }) => onRunTests(id)); + .forEach(({ id }) => api.runTestProvider(id)); }} disabled={running} > diff --git a/code/core/src/manager/components/sidebar/Tree.stories.tsx b/code/core/src/manager/components/sidebar/Tree.stories.tsx index a8f3a227b2dc..baadd2e60fec 100644 --- a/code/core/src/manager/components/sidebar/Tree.stories.tsx +++ b/code/core/src/manager/components/sidebar/Tree.stories.tsx @@ -2,9 +2,9 @@ import React, { useState } from 'react'; import type { Meta, StoryObj } from '@storybook/react'; -import { expect, within } from '@storybook/test'; +import { expect, fn, userEvent, within } from '@storybook/test'; -import type { ComponentEntry, IndexHash } from '@storybook/core/manager-api'; +import { type ComponentEntry, type IndexHash, ManagerContext } from '@storybook/core/manager-api'; import { action } from '@storybook/addon-actions'; @@ -12,6 +12,55 @@ import { DEFAULT_REF_ID } from './Sidebar'; import { Tree } from './Tree'; import { index } from './mockdata.large'; +const managerContext: any = { + state: { + docsOptions: { + defaultName: 'Docs', + autodocs: 'tag', + docsMode: false, + }, + testProviders: { + 'component-tests': { + type: 'experimental_TEST_PROVIDER', + id: 'component-tests', + render: () => 'Component tests', + sidebarContextMenu: () => <div>TEST_PROVIDER_CONTEXT_CONTENT</div>, + runnable: true, + watchable: true, + }, + 'visual-tests': { + type: 'experimental_TEST_PROVIDER', + id: 'visual-tests', + render: () => 'Visual tests', + sidebarContextMenu: () => null, + runnable: true, + }, + }, + }, + api: { + on: fn().mockName('api::on'), + off: fn().mockName('api::off'), + emit: fn().mockName('api::emit'), + getElements: fn(() => ({ + 'component-tests': { + type: 'experimental_TEST_PROVIDER', + id: 'component-tests', + render: () => 'Component tests', + sidebarContextMenu: () => <div>TEST_PROVIDER_CONTEXT_CONTENT</div>, + runnable: true, + watchable: true, + }, + 'visual-tests': { + type: 'experimental_TEST_PROVIDER', + id: 'visual-tests', + render: () => 'Visual tests', + sidebarContextMenu: () => null, + runnable: true, + }, + })), + }, +}; + const meta = { component: Tree, title: 'Sidebar/Tree', @@ -35,6 +84,11 @@ const meta = { }, chromatic: { viewports: [380] }, }, + decorators: [ + (storyFn) => ( + <ManagerContext.Provider value={managerContext}>{storyFn()}</ManagerContext.Provider> + ), + ], } as Meta<typeof Tree>; export default meta; @@ -233,3 +287,41 @@ export const SkipToCanvasLinkFocused: Story = { await expect(link).toBeVisible(); }, }; + +// SkipToCanvas Link only shows on desktop widths +export const WithContextContent: Story = { + ...DocsOnlySingleStoryComponents, + parameters: { + chromatic: { viewports: [1280] }, + viewport: { + options: { + desktop: { + name: 'Desktop', + styles: { + width: '100%', + height: '100%', + }, + }, + }, + }, + }, + globals: { + viewport: { value: 'desktop' }, + }, + play: async ({ canvasElement }) => { + const screen = await within(canvasElement); + + const link = await screen.findByText('TooltipBuildList'); + await userEvent.hover(link); + + const contextButton = await screen.findByTestId('context-menu'); + await userEvent.click(contextButton); + + const body = await within(document.body); + + const tooltip = await body.findByTestId('tooltip'); + + await expect(tooltip).toBeVisible(); + expect(tooltip).toHaveTextContent('TEST_PROVIDER_CONTEXT_CONTENT'); + }, +}; diff --git a/code/core/src/manager/components/sidebar/Tree.tsx b/code/core/src/manager/components/sidebar/Tree.tsx index da9267f6caa4..38f1e7449118 100644 --- a/code/core/src/manager/components/sidebar/Tree.tsx +++ b/code/core/src/manager/components/sidebar/Tree.tsx @@ -1,8 +1,9 @@ -import type { ComponentProps, MutableRefObject } from 'react'; +import type { ComponentProps, FC, MutableRefObject } from 'react'; import React, { useCallback, useMemo, useRef } from 'react'; -import { Button, IconButton, TooltipLinkList, WithTooltip } from '@storybook/core/components'; +import { Button, IconButton, ListItem } from '@storybook/core/components'; import { styled, useTheme } from '@storybook/core/theming'; +import { type API_HashEntry, type API_StatusValue, type StoryId } from '@storybook/core/types'; import { CollapseIcon as CollapseIconSvg, ExpandAltIcon, @@ -11,7 +12,6 @@ import { StatusWarnIcon, SyncIcon, } from '@storybook/icons'; -import type { API_HashEntry, API_StatusValue, StoryId } from '@storybook/types'; import { PRELOAD_ENTRIES } from '@storybook/core/core-events'; import { useStorybookApi } from '@storybook/core/manager-api'; @@ -26,6 +26,7 @@ import type { import { transparentize } from 'polished'; +import type { Link } from '../../../components/components/tooltip/TooltipLinkList'; import { getGroupStatus, getHighestStatus, statusMapping } from '../../utils/status'; import { createId, @@ -35,6 +36,7 @@ import { isStoryHoistable, } from '../../utils/tree'; import { useLayout } from '../layout/LayoutProvider'; +import { useContextMenu } from './ContextMenu'; import { IconSymbols, UseSymbol } from './IconSymbols'; import { StatusButton } from './StatusButton'; import { StatusContext, useStatusSummary } from './StatusContext'; @@ -44,8 +46,7 @@ import type { Highlight, Item } from './types'; import type { ExpandAction, ExpandedState } from './useExpanded'; import { useExpanded } from './useExpanded'; -export const TEST_ADDON_ID = 'storybook/test'; -export const TEST_PROVIDER_ID = `${TEST_ADDON_ID}/test-provider`; +export type ExcludesNull = <T>(x: T | null) => x is T; const Container = styled.div<{ hasOrphans: boolean }>((props) => ({ marginTop: props.hasOrphans ? 20 : 0, @@ -84,6 +85,22 @@ export const LeafNodeStyleWrapper = styled.div(({ theme }) => ({ outline: 'none', }, + '& [data-displayed="off"]': { + visibility: 'hidden', + }, + + '&:hover [data-displayed="off"]': { + visibility: 'visible', + }, + + '& [data-displayed="on"] + *': { + display: 'none', + }, + + '&:hover [data-displayed="off"] + *': { + display: 'none', + }, + '&[data-selected="true"]': { color: theme.color.lightest, background: theme.color.secondary, @@ -139,6 +156,40 @@ interface NodeProps { collapsedData: Record<string, API_HashEntry>; } +const SuccessStatusIcon: FC<ComponentProps<typeof StatusPassIcon>> = (props) => { + const theme = useTheme(); + return <StatusPassIcon {...props} color={theme.color.positive} />; +}; + +const ErrorStatusIcon: FC<ComponentProps<typeof StatusFailIcon>> = (props) => { + const theme = useTheme(); + return <StatusFailIcon {...props} color={theme.color.negative} />; +}; + +const WarnStatusIcon: FC<ComponentProps<typeof StatusWarnIcon>> = (props) => { + const theme = useTheme(); + return <StatusWarnIcon {...props} color={theme.color.warning} />; +}; + +const PendingStatusIcon: FC<ComponentProps<typeof SyncIcon>> = (props) => { + const theme = useTheme(); + return <SyncIcon {...props} size={12} color={theme.color.defaultText} />; +}; + +const StatusIconMap = { + success: <SuccessStatusIcon />, + error: <ErrorStatusIcon />, + warn: <WarnStatusIcon />, + pending: <PendingStatusIcon />, + unknown: null, +}; + +export const ContextMenu = { + ListItem, +}; + +const statusOrder: API_StatusValue[] = ['success', 'error', 'warn', 'pending', 'unknown']; + const Node = React.memo<NodeProps>(function Node({ item, status, @@ -153,26 +204,82 @@ const Node = React.memo<NodeProps>(function Node({ isExpanded, setExpanded, onSelectStoryId, - collapsedData, api, }) { const { isDesktop, isMobile, setMobileMenuOpen } = useLayout(); - const theme = useTheme(); const { counts, statuses } = useStatusSummary(item); if (!isDisplayed) { return null; } + const statusLinks = useMemo<Link[]>(() => { + if (item.type === 'story' || item.type === 'docs') { + return Object.entries(status || {}) + .sort((a, b) => statusOrder.indexOf(a[1].status) - statusOrder.indexOf(b[1].status)) + .map(([addonId, value]) => ({ + id: addonId, + title: value.title, + description: value.description, + 'aria-label': `Test status for ${value.title}: ${value.status}`, + icon: StatusIconMap[value.status], + onClick: () => { + onSelectStoryId(item.id); + value.onClick?.(); + }, + })); + } + + if (item.type === 'component' || item.type === 'group') { + const links: Link[] = []; + if (counts.error) { + links.push({ + id: 'errors', + icon: StatusIconMap.error, + title: `${counts.error} ${counts.error === 1 ? 'story' : 'stories'} with errors`, + onClick: () => { + const [firstStoryId, [firstError]] = Object.entries(statuses.error)[0]; + onSelectStoryId(firstStoryId); + firstError.onClick?.(); + }, + }); + } + if (counts.warn) { + links.push({ + id: 'warnings', + icon: StatusIconMap.warn, + title: `${counts.warn} ${counts.warn === 1 ? 'story' : 'stories'} with warnings`, + onClick: () => { + const [firstStoryId, [firstWarning]] = Object.entries(statuses.warn)[0]; + onSelectStoryId(firstStoryId); + firstWarning.onClick?.(); + }, + }); + } + return links; + } + + return []; + }, [ + counts.error, + counts.warn, + item.id, + item.type, + onSelectStoryId, + status, + statuses.error, + statuses.warn, + ]); + const id = createId(item.id, refId); + const contextMenu = useContextMenu(item, statusLinks, api); + if (item.type === 'story' || item.type === 'docs') { const LeafNode = item.type === 'docs' ? DocumentNode : StoryNode; const statusValue = getHighestStatus(Object.values(status || {}).map((s) => s.status)); const [icon, textColor] = statusMapping[statusValue]; - const statusOrder: API_StatusValue[] = ['success', 'error', 'warn', 'pending', 'unknown']; - return ( <LeafNodeStyleWrapper key={id} @@ -183,6 +290,7 @@ const Node = React.memo<NodeProps>(function Node({ data-parent-id={item.parent} data-nodetype={item.type === 'docs' ? 'document' : 'story'} data-highlightable={isDisplayed} + onMouseEnter={contextMenu.onMouseEnter} > <LeafNode // @ts-expect-error (non strict) @@ -208,49 +316,17 @@ const Node = React.memo<NodeProps>(function Node({ <a href="#storybook-preview-wrapper">Skip to canvas</a> </SkipToContentLink> )} + {contextMenu.node} {icon ? ( - <WithTooltip - closeOnOutsideClick - closeOnTriggerHidden - onClick={(event) => event.stopPropagation()} - placement="bottom" - tooltip={({ onHide }) => ( - <TooltipLinkList - links={Object.entries(status || {}) - .sort( - (a, b) => statusOrder.indexOf(a[1].status) - statusOrder.indexOf(b[1].status) - ) - .map(([addonId, value]) => ({ - id: addonId, - title: value.title, - description: value.description, - 'aria-label': `Test status for ${value.title}: ${value.status}`, - icon: { - success: <StatusPassIcon color={theme.color.positive} />, - error: <StatusFailIcon color={theme.color.negative} />, - warn: <StatusWarnIcon color={theme.color.warning} />, - pending: <SyncIcon size={12} color={theme.color.defaultText} />, - unknown: null, - }[value.status], - onClick: () => { - onSelectStoryId(item.id); - value.onClick?.(); - onHide(); - }, - }))} - /> - )} + <StatusButton + aria-label={`Test status: ${statusValue}`} + role="status" + type="button" + status={statusValue} + selectedItem={isSelected} > - <StatusButton - aria-label={`Test status: ${statusValue}`} - role="status" - type="button" - status={statusValue} - selectedItem={isSelected} - > - {icon} - </StatusButton> - </WithTooltip> + {icon} + </StatusButton> ) : null} </LeafNodeStyleWrapper> ); @@ -302,39 +378,6 @@ const Node = React.memo<NodeProps>(function Node({ const color = itemStatus ? statusMapping[itemStatus][1] : null; const BranchNode = item.type === 'component' ? ComponentNode : GroupNode; - const createLinks: (onHide: () => void) => ComponentProps<typeof TooltipLinkList>['links'] = ( - onHide - ) => { - const links = []; - if (counts.error) { - links.push({ - id: 'errors', - icon: <StatusFailIcon color={theme.color.negative} />, - title: `${counts.error} ${counts.error === 1 ? 'story' : 'stories'} with errors`, - onClick: () => { - const [firstStoryId, [firstError]] = Object.entries(statuses.error)[0]; - onSelectStoryId(firstStoryId); - firstError.onClick?.(); - onHide(); - }, - }); - } - if (counts.warn) { - links.push({ - id: 'warnings', - icon: <StatusWarnIcon color={theme.color.gold} />, - title: `${counts.warn} ${counts.warn === 1 ? 'story' : 'stories'} with warnings`, - onClick: () => { - const [firstStoryId, [firstWarning]] = Object.entries(statuses.warn)[0]; - onSelectStoryId(firstStoryId); - firstWarning.onClick?.(); - onHide(); - }, - }); - } - return links; - }; - return ( <LeafNodeStyleWrapper key={id} @@ -342,8 +385,9 @@ const Node = React.memo<NodeProps>(function Node({ data-ref-id={refId} data-item-id={item.id} data-parent-id={item.parent} - data-nodetype={item.type === 'component' ? 'component' : 'group'} + data-nodetype={item.type} data-highlightable={isDisplayed} + onMouseEnter={contextMenu.onMouseEnter} > <BranchNode id={id} @@ -374,19 +418,13 @@ const Node = React.memo<NodeProps>(function Node({ {(item.renderLabel as (i: typeof item, api: API) => React.ReactNode)?.(item, api) || item.name} </BranchNode> + {contextMenu.node} {['error', 'warn'].includes(itemStatus) && ( - <WithTooltip - closeOnOutsideClick - onClick={(event) => event.stopPropagation()} - placement="bottom" - tooltip={({ onHide }) => <TooltipLinkList links={createLinks(onHide)} />} - > - <StatusButton type="button" status={itemStatus}> - <svg key="icon" viewBox="0 0 6 6" width="6" height="6" type="dot"> - <UseSymbol type="dot" /> - </svg> - </StatusButton> - </WithTooltip> + <StatusButton type="button" status={itemStatus}> + <svg key="icon" viewBox="0 0 6 6" width="6" height="6" type="dot"> + <UseSymbol type="dot" /> + </svg> + </StatusButton> )} </LeafNodeStyleWrapper> ); @@ -593,6 +631,10 @@ export const Tree = React.memo<{ const isDisplayed = !item.parent || ancestry[itemId].every((a: string) => expanded[a]); + if (isDisplayed === false) { + return null; + } + return ( <Node api={api} diff --git a/code/core/src/manager/components/upgrade/UpgradeBlock.tsx b/code/core/src/manager/components/upgrade/UpgradeBlock.tsx index 207b9fcef6b1..f7371abc2e63 100644 --- a/code/core/src/manager/components/upgrade/UpgradeBlock.tsx +++ b/code/core/src/manager/components/upgrade/UpgradeBlock.tsx @@ -14,7 +14,7 @@ interface UpgradeBlockProps { export const UpgradeBlock: FC<UpgradeBlockProps> = ({ onNavigateToWhatsNew }) => { const api = useStorybookApi(); - const [activeTab, setActiveTab] = useState<'npm' | 'pnpm'>('npm'); + const [activeTab, setActiveTab] = useState<'npm' | 'yarn' | 'pnpm'>('npm'); return ( <Container> @@ -24,12 +24,17 @@ export const UpgradeBlock: FC<UpgradeBlockProps> = ({ onNavigateToWhatsNew }) => <ButtonTab active={activeTab === 'npm'} onClick={() => setActiveTab('npm')}> npm </ButtonTab> + <ButtonTab active={activeTab === 'yarn'} onClick={() => setActiveTab('yarn')}> + yarn + </ButtonTab> <ButtonTab active={activeTab === 'pnpm'} onClick={() => setActiveTab('pnpm')}> pnpm </ButtonTab> </Tabs> <Code> - {activeTab === 'npm' ? 'npx storybook@latest upgrade' : 'pnpm dlx storybook@latest upgrade'} + {activeTab === 'npm' + ? 'npx storybook@latest upgrade' + : `${activeTab} dlx storybook@latest upgrade`} </Code> {onNavigateToWhatsNew && ( // eslint-disable-next-line jsx-a11y/anchor-is-valid diff --git a/code/core/src/manager/globals/exports.ts b/code/core/src/manager/globals/exports.ts index b9141e853f95..dc0b4b6139d9 100644 --- a/code/core/src/manager/globals/exports.ts +++ b/code/core/src/manager/globals/exports.ts @@ -811,7 +811,6 @@ export default { 'TESTING_MODULE_CANCEL_TEST_RUN_RESPONSE', 'TESTING_MODULE_CRASH_REPORT', 'TESTING_MODULE_PROGRESS_REPORT', - 'TESTING_MODULE_RUN_ALL_REQUEST', 'TESTING_MODULE_RUN_REQUEST', 'TESTING_MODULE_WATCH_MODE_REQUEST', 'TOGGLE_WHATS_NEW_NOTIFICATIONS', @@ -875,7 +874,6 @@ export default { 'TESTING_MODULE_CANCEL_TEST_RUN_RESPONSE', 'TESTING_MODULE_CRASH_REPORT', 'TESTING_MODULE_PROGRESS_REPORT', - 'TESTING_MODULE_RUN_ALL_REQUEST', 'TESTING_MODULE_RUN_REQUEST', 'TESTING_MODULE_WATCH_MODE_REQUEST', 'TOGGLE_WHATS_NEW_NOTIFICATIONS', @@ -939,7 +937,6 @@ export default { 'TESTING_MODULE_CANCEL_TEST_RUN_RESPONSE', 'TESTING_MODULE_CRASH_REPORT', 'TESTING_MODULE_PROGRESS_REPORT', - 'TESTING_MODULE_RUN_ALL_REQUEST', 'TESTING_MODULE_RUN_REQUEST', 'TESTING_MODULE_WATCH_MODE_REQUEST', 'TOGGLE_WHATS_NEW_NOTIFICATIONS', diff --git a/code/core/src/manager/settings/defaultShortcuts.tsx b/code/core/src/manager/settings/defaultShortcuts.tsx index 525d85decb71..ed8ad0fd9135 100644 --- a/code/core/src/manager/settings/defaultShortcuts.tsx +++ b/code/core/src/manager/settings/defaultShortcuts.tsx @@ -1,4 +1,4 @@ -import type { State } from '../../manager-api/root'; +import type { State } from '@storybook/core/manager-api'; export const defaultShortcuts: State['shortcuts'] = { fullScreen: ['F'], diff --git a/code/core/src/types/modules/addons.ts b/code/core/src/types/modules/addons.ts index 2c995322b09d..1f9649cfd405 100644 --- a/code/core/src/types/modules/addons.ts +++ b/code/core/src/types/modules/addons.ts @@ -1,11 +1,12 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { FC, PropsWithChildren, ReactElement, ReactNode } from 'react'; -import type { TestingModuleProgressReportProgress } from '../../core-events'; +import type { ListItem } from '../../components'; +import type { TestProviderConfig, TestingModuleProgressReportProgress } from '../../core-events'; import type { RenderData as RouterData } from '../../router/types'; import type { ThemeVars } from '../../theming/types'; import type { API_SidebarOptions } from './api'; -import type { API_StatusState, API_StatusUpdate } from './api-stories'; +import type { API_HashEntry, API_StatusState, API_StatusUpdate } from './api-stories'; import type { Args, ArgsStoryFn as ArgsStoryFnForFramework, @@ -28,6 +29,7 @@ export type Addon_Types = Exclude< Addon_TypesEnum, | Addon_TypesEnum.experimental_PAGE | Addon_TypesEnum.experimental_SIDEBAR_BOTTOM + | Addon_TypesEnum.experimental_TEST_PROVIDER | Addon_TypesEnum.experimental_SIDEBAR_TOP >; @@ -329,7 +331,7 @@ export type Addon_Type = | Addon_WrapperType | Addon_SidebarBottomType | Addon_SidebarTopType - | Addon_TestProviderType; + | Addon_TestProviderType<Addon_TestProviderState>; export interface Addon_BaseType { /** * The title of the addon. This can be a simple string, but it can also be a @@ -472,8 +474,15 @@ export interface Addon_TestProviderType< /** The unique id of the test provider. */ id: string; name: string; - title: (state: Addon_TestProviderState<Details>) => ReactNode; - description: (state: Addon_TestProviderState<Details>) => ReactNode; + /** @deprecated Use render instead */ + title?: (state: TestProviderConfig & Addon_TestProviderState<Details>) => ReactNode; + /** @deprecated Use render instead */ + description?: (state: TestProviderConfig & Addon_TestProviderState<Details>) => ReactNode; + render?: (state: TestProviderConfig & Addon_TestProviderState<Details>) => ReactNode; + sidebarContextMenu?: (options: { + context: API_HashEntry; + state: Addon_TestProviderState<Details>; + }) => ReactNode; mapStatusUpdate?: ( state: Addon_TestProviderState<Details> ) => API_StatusUpdate | ((state: API_StatusState) => API_StatusUpdate); @@ -511,7 +520,7 @@ export interface Addon_TypesMapping extends Record<Addon_TypeBaseNames, Addon_Ba [Addon_TypesEnum.experimental_PAGE]: Addon_PageType; [Addon_TypesEnum.experimental_SIDEBAR_BOTTOM]: Addon_SidebarBottomType; [Addon_TypesEnum.experimental_SIDEBAR_TOP]: Addon_SidebarTopType; - [Addon_TypesEnum.experimental_TEST_PROVIDER]: Addon_TestProviderType; + [Addon_TypesEnum.experimental_TEST_PROVIDER]: Addon_TestProviderType<Addon_TestProviderState>; } export type Addon_Loader<API> = (api: API) => void; diff --git a/code/core/src/types/modules/frameworks.ts b/code/core/src/types/modules/frameworks.ts index 2f2028db810b..e3e1b6383a7f 100644 --- a/code/core/src/types/modules/frameworks.ts +++ b/code/core/src/types/modules/frameworks.ts @@ -8,6 +8,7 @@ export type SupportedFrameworks = | 'nextjs' | 'preact-vite' | 'preact-webpack5' + | 'react-native-web-vite' | 'react-vite' | 'react-webpack5' | 'server-webpack5' diff --git a/code/deprecated/builder-manager/package.json b/code/deprecated/builder-manager/package.json index 4ad08c09b4a3..786a41e4661f 100644 --- a/code/deprecated/builder-manager/package.json +++ b/code/deprecated/builder-manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-manager", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook manager builder", "keywords": [ "storybook" diff --git a/code/deprecated/channels/package.json b/code/deprecated/channels/package.json index 688873156e9e..1ac33ceac79e 100644 --- a/code/deprecated/channels/package.json +++ b/code/deprecated/channels/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/channels", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/client-logger/package.json b/code/deprecated/client-logger/package.json index 384ad1432a6a..c46a1669ad77 100644 --- a/code/deprecated/client-logger/package.json +++ b/code/deprecated/client-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/client-logger", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/components/package.json b/code/deprecated/components/package.json index d1750b8c4f81..e300d80a06d4 100644 --- a/code/deprecated/components/package.json +++ b/code/deprecated/components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/components", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Core Storybook Components", "keywords": [ "storybook" diff --git a/code/deprecated/core-common/package.json b/code/deprecated/core-common/package.json index d5818575ff0f..b0e8d351c25e 100644 --- a/code/deprecated/core-common/package.json +++ b/code/deprecated/core-common/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-common", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/deprecated/core-events/package.json b/code/deprecated/core-events/package.json index de869d70f4aa..24bd6f5e6c8c 100644 --- a/code/deprecated/core-events/package.json +++ b/code/deprecated/core-events/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-events", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Event names used in storybook core", "keywords": [ "storybook" diff --git a/code/deprecated/core-server/package.json b/code/deprecated/core-server/package.json index e3ec83f93258..a53342756276 100644 --- a/code/deprecated/core-server/package.json +++ b/code/deprecated/core-server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-server", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/deprecated/csf-tools/package.json b/code/deprecated/csf-tools/package.json index bace85c54878..4b4e4a3fd66a 100644 --- a/code/deprecated/csf-tools/package.json +++ b/code/deprecated/csf-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-tools", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Parse and manipulate CSF and Storybook config files", "keywords": [ "storybook" diff --git a/code/deprecated/docs-tools/package.json b/code/deprecated/docs-tools/package.json index 9ab05de3b587..47dcae7b60de 100644 --- a/code/deprecated/docs-tools/package.json +++ b/code/deprecated/docs-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/docs-tools", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Shared utility functions for frameworks to implement docs", "keywords": [ "storybook" diff --git a/code/deprecated/manager-api/package.json b/code/deprecated/manager-api/package.json index f7c8cf3a6a61..8ee87740c2eb 100644 --- a/code/deprecated/manager-api/package.json +++ b/code/deprecated/manager-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager-api", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Core Storybook Manager API & Context", "keywords": [ "storybook" diff --git a/code/deprecated/manager/package.json b/code/deprecated/manager/package.json index 83213deaa9e1..9af62f203453 100644 --- a/code/deprecated/manager/package.json +++ b/code/deprecated/manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Core Storybook UI", "keywords": [ "storybook" diff --git a/code/deprecated/node-logger/package.json b/code/deprecated/node-logger/package.json index 9c151e1d8bdf..25f39dbfc79c 100644 --- a/code/deprecated/node-logger/package.json +++ b/code/deprecated/node-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/node-logger", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/preview-api/package.json b/code/deprecated/preview-api/package.json index 528f533d8c30..23f20c814c90 100644 --- a/code/deprecated/preview-api/package.json +++ b/code/deprecated/preview-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preview-api", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/preview/package.json b/code/deprecated/preview/package.json index a2d6f5c49da8..768f9de351bd 100644 --- a/code/deprecated/preview/package.json +++ b/code/deprecated/preview/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preview", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/router/package.json b/code/deprecated/router/package.json index 9550874baceb..3a749c9f1a2b 100644 --- a/code/deprecated/router/package.json +++ b/code/deprecated/router/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/router", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Core Storybook Router", "keywords": [ "storybook" diff --git a/code/deprecated/telemetry/package.json b/code/deprecated/telemetry/package.json index 320be1c21042..028a96834cc6 100644 --- a/code/deprecated/telemetry/package.json +++ b/code/deprecated/telemetry/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/telemetry", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Telemetry logging for crash reports and usage statistics", "keywords": [ "storybook" diff --git a/code/deprecated/theming/package.json b/code/deprecated/theming/package.json index e47ea4acac35..9cd0f6b1afa3 100644 --- a/code/deprecated/theming/package.json +++ b/code/deprecated/theming/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/theming", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Core Storybook Components", "keywords": [ "storybook" diff --git a/code/deprecated/types/package.json b/code/deprecated/types/package.json index 906b18452bce..97547c3571b9 100644 --- a/code/deprecated/types/package.json +++ b/code/deprecated/types/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/types", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Core Storybook TS Types", "keywords": [ "storybook" diff --git a/code/e2e-tests/addon-actions.spec.ts b/code/e2e-tests/addon-actions.spec.ts index 861a392070b7..f049cbe3060a 100644 --- a/code/e2e-tests/addon-actions.spec.ts +++ b/code/e2e-tests/addon-actions.spec.ts @@ -12,6 +12,10 @@ test.describe('addon-actions', () => { templateName.includes('svelte') && templateName.includes('prerelease'), 'Svelte 5 prerelase does not support automatic actions with our current example components yet' ); + test.skip( + templateName.includes('react-native-web'), + 'React Native uses onPress rather than onClick' + ); await page.goto(storybookUrl); const sbPage = new SbPage(page, expect); sbPage.waitUntilLoaded(); diff --git a/code/e2e-tests/addon-controls.spec.ts b/code/e2e-tests/addon-controls.spec.ts index 23909fd707d0..6ba84552b81e 100644 --- a/code/e2e-tests/addon-controls.spec.ts +++ b/code/e2e-tests/addon-controls.spec.ts @@ -4,9 +4,12 @@ import process from 'process'; import { SbPage } from './util'; const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001'; +const templateName = process.env.STORYBOOK_TEMPLATE_NAME || ''; test.describe('addon-controls', () => { test('should change component when changing controls', async ({ page }) => { + test.skip(templateName.includes('react-native-web'), 'React Native CSS behaves differently'); + await page.goto(storybookUrl); const sbPage = new SbPage(page, expect); await sbPage.waitUntilLoaded(); diff --git a/code/e2e-tests/addon-docs.spec.ts b/code/e2e-tests/addon-docs.spec.ts index 94548af7b3f9..54c046a8aec7 100644 --- a/code/e2e-tests/addon-docs.spec.ts +++ b/code/e2e-tests/addon-docs.spec.ts @@ -123,6 +123,7 @@ test.describe('addon-docs', () => { // - template: https://638db567ed97c3fb3e21cc22-ulhjwkqzzj.chromatic.com/?path=/docs/addons-docs-docspage-basic--docs // - real: https://638db567ed97c3fb3e21cc22-ulhjwkqzzj.chromatic.com/?path=/docs/example-button--docs 'lit-vite', + 'react-native-web', ]; test.skip( new RegExp(`^${skipped.join('|')}`, 'i').test(`${templateName}`), @@ -189,6 +190,10 @@ test.describe('addon-docs', () => { }); test('should resolve react to the correct version', async ({ page }) => { + test.skip( + templateName?.includes('nextjs'), + 'TODO: remove this once sandboxes are synced (SOON!!)' + ); // Arrange - Navigate to MDX docs const sbPage = new SbPage(page, expect); await sbPage.navigateToStory('addons/docs/docs2/resolvedreact', 'mdx', 'docs'); @@ -201,6 +206,7 @@ test.describe('addon-docs', () => { } else if (templateName.includes('react16')) { expectedReactVersionRange = /^16/; } else if ( + templateName.includes('nextjs/default-ts') || templateName.includes('nextjs/prerelease') || templateName.includes('react-vite/prerelease') || templateName.includes('react-webpack/prerelease') diff --git a/code/e2e-tests/addon-interactions.spec.ts b/code/e2e-tests/addon-interactions.spec.ts index b5a703e2d1e8..b1cb9ea9884a 100644 --- a/code/e2e-tests/addon-interactions.spec.ts +++ b/code/e2e-tests/addon-interactions.spec.ts @@ -23,6 +23,10 @@ test.describe('addon-interactions', () => { /^(lit)/i.test(`${templateName}`), `Skipping ${templateName}, which does not support addon-interactions` ); + test.skip( + templateName.includes('react-native-web'), + 'React Native does not use className locators' + ); const sbPage = new SbPage(page, expect); diff --git a/code/e2e-tests/composition.spec.ts b/code/e2e-tests/composition.spec.ts index 8e50987675b5..15bc6c4c4ed9 100644 --- a/code/e2e-tests/composition.spec.ts +++ b/code/e2e-tests/composition.spec.ts @@ -11,12 +11,10 @@ test.describe('composition', () => { 'Slow, framework independent test, so only run it on in react-vite/default-ts' ); - test.beforeEach(async ({ page }) => { + test('should filter and render composed stories', async ({ page }) => { await page.goto(storybookUrl); await new SbPage(page, expect).waitUntilLoaded(); - }); - test('should correctly filter composed stories', async ({ page }) => { // Expect that composed Storybooks are visible await expect(page.getByTitle('Storybook 8.0.0')).toBeVisible(); await expect(page.getByTitle('Storybook 7.6.18')).toBeVisible(); @@ -35,10 +33,64 @@ test.describe('composition', () => { // Expect composed stories `to be available in the search await page.getByPlaceholder('Find components').fill('Button'); await expect( - page.getByRole('option', { name: 'Button Storybook 8.0.0 / @blocks / examples' }) + page.getByRole('option', { name: 'Button Storybook 7.6.18 / @blocks / examples' }) ).toBeVisible(); + + const buttonStory = page.getByRole('option', { + name: 'Button Storybook 8.0.0 / @blocks / examples', + }); + await expect(buttonStory).toBeVisible(); + await buttonStory.click(); + + // Note: this could potentially be flaky due to it accessing a hosted Storybook + await expect( + page + .locator('iframe[title="storybook-ref-storybook\\@8\\.0\\.0"]') + .contentFrame() + .getByRole('heading', { name: 'Example button component' }) + ).toBeVisible({ timeout: 15000 }); + }); + + test('should filter and render composed stories on mobile', async ({ page }) => { + page.setViewportSize({ width: 320, height: 800 }); + await page.goto(storybookUrl); + await new SbPage(page, expect).waitUntilLoaded(); + + await page.click('button[title="Open navigation menu"]'); + + // Expect that composed Storybooks are visible + await expect(page.getByTitle('Storybook 8.0.0')).toBeVisible(); + await expect(page.getByTitle('Storybook 7.6.18')).toBeVisible(); + + // Expect composed stories to be available in the sidebar + await page.locator('[id="storybook\\@8\\.0\\.0_components-badge"]').click(); + await expect( + page.locator('[id="storybook\\@8\\.0\\.0_components-badge--default"]') + ).toBeVisible(); + + await page.locator('[id="storybook\\@7\\.6\\.18_components-badge"]').click(); + await expect( + page.locator('[id="storybook\\@7\\.6\\.18_components-badge--default"]') + ).toBeVisible(); + + // Expect composed stories `to be available in the search + await page.getByPlaceholder('Find components').fill('Button'); await expect( page.getByRole('option', { name: 'Button Storybook 7.6.18 / @blocks / examples' }) ).toBeVisible(); + + const buttonStory = page.getByRole('option', { + name: 'Button Storybook 8.0.0 / @blocks / examples', + }); + await expect(buttonStory).toBeVisible(); + await buttonStory.click(); + + // Note: this could potentially be flaky due to it accessing a hosted Storybook + await expect( + page + .locator('iframe[title="storybook-ref-storybook\\@8\\.0\\.0"]') + .contentFrame() + .getByRole('heading', { name: 'Example button component' }) + ).toBeVisible({ timeout: 15000 }); }); }); diff --git a/code/e2e-tests/framework-nextjs.spec.ts b/code/e2e-tests/framework-nextjs.spec.ts index 27d7ab16ac43..9e426e26709b 100644 --- a/code/e2e-tests/framework-nextjs.spec.ts +++ b/code/e2e-tests/framework-nextjs.spec.ts @@ -53,10 +53,7 @@ test.describe('Next.js', () => { test.beforeEach(async ({ page }) => { sbPage = new SbPage(page, expect); - await sbPage.navigateToStory( - 'stories/frameworks/nextjs-nextjs-default-ts/Navigation', - 'default' - ); + await sbPage.navigateToStory('stories/frameworks/nextjs/Navigation', 'default'); root = sbPage.previewRoot(); }); @@ -88,7 +85,7 @@ test.describe('Next.js', () => { test.beforeEach(async ({ page }) => { sbPage = new SbPage(page, expect); - await sbPage.navigateToStory('stories/frameworks/nextjs-nextjs-default-ts/Router', 'default'); + await sbPage.navigateToStory('stories/frameworks/nextjs/Router', 'default'); root = sbPage.previewRoot(); }); diff --git a/code/frameworks/angular/package.json b/code/frameworks/angular/package.json index 58cd68aceb7f..e150fded5744 100644 --- a/code/frameworks/angular/package.json +++ b/code/frameworks/angular/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/angular", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.", "keywords": [ "storybook", @@ -81,17 +81,17 @@ "zone.js": "^0.14.2" }, "peerDependencies": { - "@angular-devkit/architect": ">=0.1500.0 < 0.1900.0", - "@angular-devkit/build-angular": ">=15.0.0 < 19.0.0", - "@angular-devkit/core": ">=15.0.0 < 19.0.0", - "@angular/cli": ">=15.0.0 < 19.0.0", - "@angular/common": ">=15.0.0 < 19.0.0", - "@angular/compiler": ">=15.0.0 < 19.0.0", - "@angular/compiler-cli": ">=15.0.0 < 19.0.0", - "@angular/core": ">=15.0.0 < 19.0.0", - "@angular/forms": ">=15.0.0 < 19.0.0", - "@angular/platform-browser": ">=15.0.0 < 19.0.0", - "@angular/platform-browser-dynamic": ">=15.0.0 < 19.0.0", + "@angular-devkit/architect": ">=0.1500.0 < 0.2000.0", + "@angular-devkit/build-angular": ">=15.0.0 < 20.0.0", + "@angular-devkit/core": ">=15.0.0 < 20.0.0", + "@angular/cli": ">=15.0.0 < 20.0.0", + "@angular/common": ">=15.0.0 < 20.0.0", + "@angular/compiler": ">=15.0.0 < 20.0.0", + "@angular/compiler-cli": ">=15.0.0 < 20.0.0", + "@angular/core": ">=15.0.0 < 20.0.0", + "@angular/forms": ">=15.0.0 < 20.0.0", + "@angular/platform-browser": ">=15.0.0 < 20.0.0", + "@angular/platform-browser-dynamic": ">=15.0.0 < 20.0.0", "rxjs": "^6.0.0 || ^7.4.0", "storybook": "workspace:^", "typescript": "^4.0.0 || ^5.0.0", diff --git a/code/frameworks/angular/src/client/angular-beta/utils/PropertyExtractor.ts b/code/frameworks/angular/src/client/angular-beta/utils/PropertyExtractor.ts index dc12b820879c..1859bb9ca249 100644 --- a/code/frameworks/angular/src/client/angular-beta/utils/PropertyExtractor.ts +++ b/code/frameworks/angular/src/client/angular-beta/utils/PropertyExtractor.ts @@ -11,6 +11,7 @@ import { Provider, ɵReflectionCapabilities as ReflectionCapabilities, importProvidersFrom, + VERSION, } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { @@ -176,15 +177,20 @@ export class PropertyExtractor implements NgModuleMetadata { const isDeclarable = isComponent || isDirective || isPipe; // Check if the hierarchically lowest Component or Directive decorator (the only relevant for importing dependencies) is standalone. - const isStandalone = !!( + + let isStandalone = (isComponent || isDirective) && [...decorators] .reverse() // reflectionCapabilities returns decorators in a hierarchically top-down order .find( (d) => this.isDecoratorInstanceOf(d, 'Component') || this.isDecoratorInstanceOf(d, 'Directive') - )?.standalone - ); + )?.standalone; + + //Starting in Angular 19 the default (in case it's undefined) value for standalone is true + if (isStandalone === undefined) { + isStandalone = !!(VERSION.major && Number(VERSION.major) >= 19); + } return { isDeclarable, isStandalone }; }; diff --git a/code/frameworks/angular/template/components/button.component.ts b/code/frameworks/angular/template/components/button.component.ts index 7a0fc8e8408a..4407ead9b050 100644 --- a/code/frameworks/angular/template/components/button.component.ts +++ b/code/frameworks/angular/template/components/button.component.ts @@ -1,6 +1,7 @@ import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ + standalone: false, // Needs to be a different name to the CLI template button selector: 'storybook-framework-button', template: ` <button diff --git a/code/frameworks/angular/template/components/form.component.ts b/code/frameworks/angular/template/components/form.component.ts index 697aef1d68d6..272e79eebf7f 100644 --- a/code/frameworks/angular/template/components/form.component.ts +++ b/code/frameworks/angular/template/components/form.component.ts @@ -1,6 +1,7 @@ import { Component, Output, EventEmitter } from '@angular/core'; @Component({ + standalone: false, selector: 'storybook-form', template: ` <form id="interaction-test-form" (submit)="handleSubmit($event)"> diff --git a/code/frameworks/angular/template/components/html.component.ts b/code/frameworks/angular/template/components/html.component.ts index 7efcf9770e6e..fc3e8235387f 100644 --- a/code/frameworks/angular/template/components/html.component.ts +++ b/code/frameworks/angular/template/components/html.component.ts @@ -2,6 +2,7 @@ import { Component, Input } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; @Component({ + standalone: false, selector: 'storybook-html', template: `<div [innerHTML]="safeContent"></div>`, }) diff --git a/code/frameworks/angular/template/components/pre.component.ts b/code/frameworks/angular/template/components/pre.component.ts index df714c936931..0fdecbec545b 100644 --- a/code/frameworks/angular/template/components/pre.component.ts +++ b/code/frameworks/angular/template/components/pre.component.ts @@ -1,6 +1,7 @@ import { Component, Input } from '@angular/core'; @Component({ + standalone: false, selector: 'storybook-pre', template: `<pre data-testid="pre" [ngStyle]="style">{{ finalText }}</pre>`, }) diff --git a/code/frameworks/angular/template/stories/argTypes/doc-button/doc-button.component.ts b/code/frameworks/angular/template/stories/argTypes/doc-button/doc-button.component.ts index 503dc358e22c..37852f7fe2e2 100644 --- a/code/frameworks/angular/template/stories/argTypes/doc-button/doc-button.component.ts +++ b/code/frameworks/angular/template/stories/argTypes/doc-button/doc-button.component.ts @@ -38,6 +38,7 @@ export enum ButtonAccent { * @html <span class="badge">aaa</span> */ @Component({ + standalone: false, selector: 'my-button', templateUrl: './doc-button.component.html', styleUrls: ['./doc-button.component.scss'], diff --git a/code/frameworks/angular/template/stories/argTypes/doc-directive/doc-directive.directive.ts b/code/frameworks/angular/template/stories/argTypes/doc-directive/doc-directive.directive.ts index 566ad55a992f..66c4b6681528 100644 --- a/code/frameworks/angular/template/stories/argTypes/doc-directive/doc-directive.directive.ts +++ b/code/frameworks/angular/template/stories/argTypes/doc-directive/doc-directive.directive.ts @@ -2,6 +2,7 @@ import { ElementRef, AfterViewInit, Directive, Input } from '@angular/core'; /** This is an Angular Directive example that has a Prop Table. */ @Directive({ + standalone: false, selector: '[docDirective]', }) export class DocDirective implements AfterViewInit { diff --git a/code/frameworks/angular/template/stories/argTypes/doc-pipe/doc-pipe.pipe.ts b/code/frameworks/angular/template/stories/argTypes/doc-pipe/doc-pipe.pipe.ts index 2964a6ef68c2..2bf9539e935b 100644 --- a/code/frameworks/angular/template/stories/argTypes/doc-pipe/doc-pipe.pipe.ts +++ b/code/frameworks/angular/template/stories/argTypes/doc-pipe/doc-pipe.pipe.ts @@ -2,6 +2,7 @@ import { PipeTransform, Pipe } from '@angular/core'; /** This is an Angular Pipe example that has a Prop Table. */ @Pipe({ + standalone: false, name: 'docPipe', }) export class DocPipe implements PipeTransform { diff --git a/code/frameworks/angular/template/stories/basics/angular-forms/customControlValueAccessor/custom-cva.component.ts b/code/frameworks/angular/template/stories/basics/angular-forms/customControlValueAccessor/custom-cva.component.ts index cf05f53fff56..00a23c4fe74e 100644 --- a/code/frameworks/angular/template/stories/basics/angular-forms/customControlValueAccessor/custom-cva.component.ts +++ b/code/frameworks/angular/template/stories/basics/angular-forms/customControlValueAccessor/custom-cva.component.ts @@ -4,6 +4,7 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; const NOOP = () => {}; @Component({ + standalone: false, selector: 'storybook-custom-cva-component', template: ` <div>{{ value }}</div> <input type="text" [(ngModel)]="value" /> `, diff --git a/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/attribute-selector.component.ts b/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/attribute-selector.component.ts index 3b1eebacb1bc..6a3f6215b158 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/attribute-selector.component.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/attribute-selector.component.ts @@ -1,6 +1,7 @@ import { ComponentFactoryResolver, ElementRef, Component } from '@angular/core'; @Component({ + standalone: false, selector: 'storybook-attribute-selector[foo=bar]', template: `<h3>Attribute selector</h3> Selector: {{ selectors }} <br /> diff --git a/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/class-selector.component.ts b/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/class-selector.component.ts index b1fa65859db9..2c60a3488b70 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/class-selector.component.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/class-selector.component.ts @@ -1,6 +1,7 @@ import { ComponentFactoryResolver, ElementRef, Component } from '@angular/core'; @Component({ + standalone: false, selector: 'storybook-class-selector.foo, storybook-class-selector.bar', template: `<h3>Class selector</h3> Selector: {{ selectors }} <br /> diff --git a/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/multiple-selector.component.ts b/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/multiple-selector.component.ts index 5a12fc7ffe5a..255d4d51a689 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/multiple-selector.component.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-complex-selectors/multiple-selector.component.ts @@ -1,6 +1,7 @@ import { ComponentFactoryResolver, ElementRef, Component } from '@angular/core'; @Component({ + standalone: false, selector: 'storybook-multiple-selector, storybook-multiple-selector2', template: `<h3>Multiple selector</h3> Selector: {{ selectors }} <br /> @@ -22,6 +23,7 @@ export class MultipleSelectorComponent { } @Component({ + standalone: false, selector: 'storybook-button, button[foo], .button[foo], button[baz]', template: `<h3>Multiple selector</h3> Selector: {{ selectors }} <br /> diff --git a/code/frameworks/angular/template/stories/basics/component-with-enums/enums.component.ts b/code/frameworks/angular/template/stories/basics/component-with-enums/enums.component.ts index 492f575b69f1..171e4ff51d0e 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-enums/enums.component.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-enums/enums.component.ts @@ -2,6 +2,7 @@ import { Component, Input } from '@angular/core'; /** This component is used for testing the various forms of enum types */ @Component({ + standalone: false, selector: 'app-enums', templateUrl: './enums.component.html', }) diff --git a/code/frameworks/angular/template/stories/basics/component-with-inheritance/base-button.component.ts b/code/frameworks/angular/template/stories/basics/component-with-inheritance/base-button.component.ts index 0cd694506d50..b1d8111cef2a 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-inheritance/base-button.component.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-inheritance/base-button.component.ts @@ -1,6 +1,7 @@ import { Component, Input } from '@angular/core'; @Component({ + standalone: false, selector: `storybook-base-button`, template: ` <button>{{ label }}</button> `, }) diff --git a/code/frameworks/angular/template/stories/basics/component-with-inheritance/icon-button.component.ts b/code/frameworks/angular/template/stories/basics/component-with-inheritance/icon-button.component.ts index 3994a3de2a97..4dfc63e09c8a 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-inheritance/icon-button.component.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-inheritance/icon-button.component.ts @@ -2,6 +2,7 @@ import { Component, Input } from '@angular/core'; import { BaseButtonComponent } from './base-button.component'; @Component({ + standalone: false, selector: `storybook-icon-button`, template: ` <button>{{ label }} - {{ icon }}</button> `, }) diff --git a/code/frameworks/angular/template/stories/basics/component-with-ng-content/ng-content-about-parent.stories.ts b/code/frameworks/angular/template/stories/basics/component-with-ng-content/ng-content-about-parent.stories.ts index f8185f8eb80a..9f54986c6cc5 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-ng-content/ng-content-about-parent.stories.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-ng-content/ng-content-about-parent.stories.ts @@ -2,6 +2,7 @@ import { Component, Input } from '@angular/core'; import { componentWrapperDecorator, Meta, StoryObj } from '@storybook/angular'; @Component({ + standalone: false, selector: 'sb-button', template: `<button [style.background-color]="color"><ng-content></ng-content></button>`, styles: [ diff --git a/code/frameworks/angular/template/stories/basics/component-with-ng-content/ng-content-simple.stories.ts b/code/frameworks/angular/template/stories/basics/component-with-ng-content/ng-content-simple.stories.ts index cc6bd1ccf6e2..775a895aa5dc 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-ng-content/ng-content-simple.stories.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-ng-content/ng-content-simple.stories.ts @@ -3,6 +3,7 @@ import { Component } from '@angular/core'; import { Meta, StoryObj } from '@storybook/angular'; @Component({ + standalone: false, selector: 'storybook-with-ng-content', template: `Content value: <div style="color: #1e88e5"><ng-content></ng-content></div>`, diff --git a/code/frameworks/angular/template/stories/basics/component-with-ng-on-destroy/component-with-on-destroy.stories.ts b/code/frameworks/angular/template/stories/basics/component-with-ng-on-destroy/component-with-on-destroy.stories.ts index 24edd068f7f1..8ccc180b991b 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-ng-on-destroy/component-with-on-destroy.stories.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-ng-on-destroy/component-with-on-destroy.stories.ts @@ -2,6 +2,7 @@ import { OnDestroy, OnInit, Component } from '@angular/core'; import { Meta, StoryObj } from '@storybook/angular'; @Component({ + standalone: false, selector: 'on-destroy', template: `Current time: {{ time }} <br /> 📝 The current time in console should no longer display after a change of story`, diff --git a/code/frameworks/angular/template/stories/basics/component-with-on-push/on-push-box.component.ts b/code/frameworks/angular/template/stories/basics/component-with-on-push/on-push-box.component.ts index b6bf293f1b0e..9d8a86aa67fb 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-on-push/on-push-box.component.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-on-push/on-push-box.component.ts @@ -1,6 +1,7 @@ import { Component, Input, ChangeDetectionStrategy, HostBinding } from '@angular/core'; @Component({ + standalone: false, selector: 'storybook-on-push-box', template: ` Word of the day: {{ word }} `, styles: [ diff --git a/code/frameworks/angular/template/stories/basics/component-with-pipe/custom-pipes.stories.ts b/code/frameworks/angular/template/stories/basics/component-with-pipe/custom-pipes.stories.ts index 1c83974691d0..9a4a8e53c577 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-pipe/custom-pipes.stories.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-pipe/custom-pipes.stories.ts @@ -11,8 +11,6 @@ const meta: Meta<WithPipeComponent> = { declarations: [CustomPipePipe], }), ], - tags: ['!test', '!vitest'], - parameters: { chromatic: { disable: true } }, }; export default meta; diff --git a/code/frameworks/angular/template/stories/basics/component-with-pipe/custom.pipe.ts b/code/frameworks/angular/template/stories/basics/component-with-pipe/custom.pipe.ts index 0038bd609241..e588751b936e 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-pipe/custom.pipe.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-pipe/custom.pipe.ts @@ -1,6 +1,7 @@ import { PipeTransform, Pipe } from '@angular/core'; @Pipe({ + standalone: false, name: 'customPipe', }) export class CustomPipePipe implements PipeTransform { diff --git a/code/frameworks/angular/template/stories/basics/component-with-pipe/with-pipe.component.ts b/code/frameworks/angular/template/stories/basics/component-with-pipe/with-pipe.component.ts index 4582170ecf73..12ec82171649 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-pipe/with-pipe.component.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-pipe/with-pipe.component.ts @@ -1,6 +1,7 @@ import { Component, Input } from '@angular/core'; @Component({ + standalone: false, selector: 'storybook-with-pipe', template: ` <h1>{{ field | customPipe }}</h1> `, }) diff --git a/code/frameworks/angular/template/stories/basics/component-with-provider/di.component.ts b/code/frameworks/angular/template/stories/basics/component-with-provider/di.component.ts index e3e8a28ac18f..c840bf64a4a6 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-provider/di.component.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-provider/di.component.ts @@ -4,6 +4,7 @@ import { stringify } from 'telejson'; export const TEST_TOKEN = new InjectionToken<string>('test'); @Component({ + standalone: false, selector: 'storybook-di-component', templateUrl: './di.component.html', providers: [{ provide: TEST_TOKEN, useValue: 123 }], diff --git a/code/frameworks/angular/template/stories/basics/component-with-style/styled.component.ts b/code/frameworks/angular/template/stories/basics/component-with-style/styled.component.ts index 6cdb0a9a627b..63ac3c56b07e 100644 --- a/code/frameworks/angular/template/stories/basics/component-with-style/styled.component.ts +++ b/code/frameworks/angular/template/stories/basics/component-with-style/styled.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; @Component({ + standalone: false, selector: 'storybook-styled-component', templateUrl: './styled.component.html', styleUrls: ['./styled.component.css', './styled.component.scss'], diff --git a/code/frameworks/angular/template/stories/basics/component-without-selector/without-selector-ng-component-outlet.stories.ts b/code/frameworks/angular/template/stories/basics/component-without-selector/without-selector-ng-component-outlet.stories.ts index 5518e437763e..64347d989fc1 100644 --- a/code/frameworks/angular/template/stories/basics/component-without-selector/without-selector-ng-component-outlet.stories.ts +++ b/code/frameworks/angular/template/stories/basics/component-without-selector/without-selector-ng-component-outlet.stories.ts @@ -19,6 +19,7 @@ type Story = StoryObj<WithoutSelectorComponent>; // Advanced example with custom *ngComponentOutlet @Component({ + standalone: false, selector: 'ng-component-outlet-wrapper', template: `<ng-container *ngComponentOutlet="componentOutlet; injector: componentInjector; content: componentContent" diff --git a/code/frameworks/angular/template/stories/basics/component-without-selector/without-selector.component.ts b/code/frameworks/angular/template/stories/basics/component-without-selector/without-selector.component.ts index 6e9ed12eff34..9d0b0d428690 100644 --- a/code/frameworks/angular/template/stories/basics/component-without-selector/without-selector.component.ts +++ b/code/frameworks/angular/template/stories/basics/component-without-selector/without-selector.component.ts @@ -5,6 +5,7 @@ export const WITHOUT_SELECTOR_DATA = new InjectionToken<{ color: string; name: s ); @Component({ + standalone: false, template: `My name in color : <div [style.color]="color">{{ name }}</div> <ng-content></ng-content> <ng-content></ng-content>`, diff --git a/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chip-text.pipe.ts b/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chip-text.pipe.ts index 0d628239d07b..9c6f1745063a 100644 --- a/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chip-text.pipe.ts +++ b/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chip-text.pipe.ts @@ -1,6 +1,7 @@ import { PipeTransform, Pipe } from '@angular/core'; @Pipe({ + standalone: false, name: 'chipText', }) export class ChipTextPipe implements PipeTransform { diff --git a/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chip.component.ts b/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chip.component.ts index 52546084465a..7804fe73fbd7 100644 --- a/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chip.component.ts +++ b/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chip.component.ts @@ -2,6 +2,7 @@ import { Component, Input, Output, EventEmitter, Inject, HostBinding } from '@an import { CHIP_COLOR } from './chip-color.token'; @Component({ + standalone: false, selector: 'storybook-chip', template: ` <span class="text">{{ displayText | chipText }}</span> diff --git a/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chips-group.component.ts b/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chips-group.component.ts index 98131407a01c..fa56aca48860 100644 --- a/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chips-group.component.ts +++ b/code/frameworks/angular/template/stories/basics/ng-module/angular-src/chips-group.component.ts @@ -1,6 +1,7 @@ import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ + standalone: false, selector: 'storybook-chips-group', template: ` <storybook-chip diff --git a/code/frameworks/angular/template/stories/basics/ng-module/import-module-chip.stories.ts b/code/frameworks/angular/template/stories/basics/ng-module/import-module-chip.stories.ts index c31db80a8dfa..e1a53bb49cf6 100644 --- a/code/frameworks/angular/template/stories/basics/ng-module/import-module-chip.stories.ts +++ b/code/frameworks/angular/template/stories/basics/ng-module/import-module-chip.stories.ts @@ -10,8 +10,6 @@ const meta: Meta<ChipComponent> = { imports: [ChipsModule], }), ], - tags: ['!test', '!vitest'], - parameters: { chromatic: { disable: true } }, }; export default meta; diff --git a/code/frameworks/angular/template/stories/basics/ng-module/import-module-for-root.stories.ts b/code/frameworks/angular/template/stories/basics/ng-module/import-module-for-root.stories.ts index f3768cc7d3da..73ef9915d437 100644 --- a/code/frameworks/angular/template/stories/basics/ng-module/import-module-for-root.stories.ts +++ b/code/frameworks/angular/template/stories/basics/ng-module/import-module-for-root.stories.ts @@ -28,8 +28,6 @@ const meta: Meta<ChipsGroupComponent> = { removeChipClick: { action: 'Remove chip' }, removeAllChipsClick: { action: 'Remove all chips clicked' }, }, - tags: ['!test', '!vitest'], - parameters: { chromatic: { disable: true } }, }; export default meta; diff --git a/code/frameworks/angular/template/stories/basics/ng-module/import-module.stories.ts b/code/frameworks/angular/template/stories/basics/ng-module/import-module.stories.ts index e13c48a43389..b82541424db0 100644 --- a/code/frameworks/angular/template/stories/basics/ng-module/import-module.stories.ts +++ b/code/frameworks/angular/template/stories/basics/ng-module/import-module.stories.ts @@ -11,8 +11,6 @@ const meta: Meta<ChipsGroupComponent> = { imports: [ChipsModule], }), ], - tags: ['!test', '!vitest'], - parameters: { chromatic: { disable: true } }, }; export default meta; diff --git a/code/frameworks/angular/template/stories/button.component.ts b/code/frameworks/angular/template/stories/button.component.ts index 3617f8c59935..0d675ad1a609 100644 --- a/code/frameworks/angular/template/stories/button.component.ts +++ b/code/frameworks/angular/template/stories/button.component.ts @@ -1,6 +1,7 @@ import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ + standalone: false, selector: 'storybook-button-component', template: ` <button (click)="onClick.emit($event)">{{ text }}</button> `, styles: [ diff --git a/code/frameworks/angular/template/stories/core/decorators/componentWrapperDecorator/child.component.ts b/code/frameworks/angular/template/stories/core/decorators/componentWrapperDecorator/child.component.ts index 5caf5db9cb20..3ac601cf8e86 100644 --- a/code/frameworks/angular/template/stories/core/decorators/componentWrapperDecorator/child.component.ts +++ b/code/frameworks/angular/template/stories/core/decorators/componentWrapperDecorator/child.component.ts @@ -1,6 +1,7 @@ import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ + standalone: false, selector: 'child-component', template: ` Child<br /> diff --git a/code/frameworks/angular/template/stories/core/decorators/componentWrapperDecorator/parent.component.ts b/code/frameworks/angular/template/stories/core/decorators/componentWrapperDecorator/parent.component.ts index 20a4447636b5..b32984ebb99a 100644 --- a/code/frameworks/angular/template/stories/core/decorators/componentWrapperDecorator/parent.component.ts +++ b/code/frameworks/angular/template/stories/core/decorators/componentWrapperDecorator/parent.component.ts @@ -1,6 +1,7 @@ import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ + standalone: false, selector: 'parent-component', template: ` Parent<br /> diff --git a/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/custom.pipe.ts b/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/custom.pipe.ts index 0038bd609241..e588751b936e 100644 --- a/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/custom.pipe.ts +++ b/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/custom.pipe.ts @@ -1,6 +1,7 @@ import { PipeTransform, Pipe } from '@angular/core'; @Pipe({ + standalone: false, name: 'customPipe', }) export class CustomPipePipe implements PipeTransform { diff --git a/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/open-close-component/open-close.component.ts b/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/open-close-component/open-close.component.ts index db630db4d4b0..4982f166e2a2 100644 --- a/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/open-close-component/open-close.component.ts +++ b/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/open-close-component/open-close.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; import { trigger, state, style, transition, animate } from '@angular/animations'; @Component({ + standalone: false, selector: 'app-open-close', animations: [ trigger('openClose', [ diff --git a/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/service.component.ts b/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/service.component.ts index 6e84cb430447..736c6cbff923 100644 --- a/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/service.component.ts +++ b/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/service.component.ts @@ -2,6 +2,7 @@ import { OnInit, Component, Input } from '@angular/core'; import { DummyService } from './dummy.service'; @Component({ + standalone: false, selector: 'storybook-simple-service-component', template: `<p>{{ name }}:</p> <ul> diff --git a/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/token.component.ts b/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/token.component.ts index 8268bceaf3c0..df1c85925aac 100644 --- a/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/token.component.ts +++ b/code/frameworks/angular/template/stories/core/moduleMetadata/angular-src/token.component.ts @@ -4,6 +4,7 @@ export const ITEMS = new InjectionToken<string[]>('TokenComponent.Items'); export const DEFAULT_NAME = new InjectionToken<string>('TokenComponent.DefaultName'); @Component({ + standalone: false, selector: 'storybook-simple-token-component', template: ` <h3>{{ name }}</h3> diff --git a/code/frameworks/angular/template/stories/core/parameters/bootstrap-options.stories.ts b/code/frameworks/angular/template/stories/core/parameters/bootstrap-options.stories.ts index f3cebdb807ad..b5c4d1d9725a 100644 --- a/code/frameworks/angular/template/stories/core/parameters/bootstrap-options.stories.ts +++ b/code/frameworks/angular/template/stories/core/parameters/bootstrap-options.stories.ts @@ -2,6 +2,7 @@ import { Meta, StoryObj } from '@storybook/angular'; import { Component } from '@angular/core'; @Component({ + standalone: false, selector: 'component-with-whitespace', preserveWhitespaces: true, template: ` <div> diff --git a/code/frameworks/angular/template/stories_angular-cli-default-ts/signal/button.component.ts b/code/frameworks/angular/template/stories_angular-cli-default-ts/signal/button.component.ts index a471debefafa..d0513056aea1 100644 --- a/code/frameworks/angular/template/stories_angular-cli-default-ts/signal/button.component.ts +++ b/code/frameworks/angular/template/stories_angular-cli-default-ts/signal/button.component.ts @@ -1,6 +1,7 @@ import { Component, Input, input, output } from '@angular/core'; @Component({ + standalone: false, // Needs to be a different name to the CLI template button selector: 'storybook-signal-button', template: ` <button diff --git a/code/frameworks/angular/template/stories_angular-cli-prerelease/signal/button.component.ts b/code/frameworks/angular/template/stories_angular-cli-prerelease/signal/button.component.ts index a471debefafa..d0513056aea1 100644 --- a/code/frameworks/angular/template/stories_angular-cli-prerelease/signal/button.component.ts +++ b/code/frameworks/angular/template/stories_angular-cli-prerelease/signal/button.component.ts @@ -1,6 +1,7 @@ import { Component, Input, input, output } from '@angular/core'; @Component({ + standalone: false, // Needs to be a different name to the CLI template button selector: 'storybook-signal-button', template: ` <button diff --git a/code/frameworks/ember/package.json b/code/frameworks/ember/package.json index fa337ddf6016..4d0e5a64d58e 100644 --- a/code/frameworks/ember/package.json +++ b/code/frameworks/ember/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/ember", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/ember", "bugs": { diff --git a/code/frameworks/experimental-nextjs-vite/package.json b/code/frameworks/experimental-nextjs-vite/package.json index b7e1d2dc4d1e..17b6bda9bfd3 100644 --- a/code/frameworks/experimental-nextjs-vite/package.json +++ b/code/frameworks/experimental-nextjs-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/experimental-nextjs-vite", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Next.js and Vite", "keywords": [ "storybook", @@ -99,16 +99,16 @@ "@storybook/react": "workspace:*", "@storybook/test": "workspace:*", "styled-jsx": "5.1.6", - "vite-plugin-storybook-nextjs": "^1.0.11" + "vite-plugin-storybook-nextjs": "^1.1.0" }, "devDependencies": { "@types/node": "^18.0.0", - "next": "^14.2.5", + "next": "^15.0.3", "typescript": "^5.3.2" }, "peerDependencies": { "@storybook/test": "workspace:*", - "next": "^14.1.0", + "next": "^14.1.0 || ^15.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "storybook": "workspace:^", @@ -141,7 +141,8 @@ "./src/images/decorator.tsx" ], "externals": [ - "sb-original/image-context" + "sb-original/image-context", + "sb-original/default-loader" ], "platform": "node" }, diff --git a/code/frameworks/experimental-nextjs-vite/src/export-mocks/compatibility/draft-mode.compat.ts b/code/frameworks/experimental-nextjs-vite/src/export-mocks/compatibility/draft-mode.compat.ts new file mode 100644 index 000000000000..cdcaf63bbf1a --- /dev/null +++ b/code/frameworks/experimental-nextjs-vite/src/export-mocks/compatibility/draft-mode.compat.ts @@ -0,0 +1,2 @@ +// @ts-expect-error Compatibility for Next 14 +export { draftMode } from 'next/dist/client/components/headers'; diff --git a/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/index.ts b/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/index.ts index 1797d4ccaf57..1c903963ba2d 100644 --- a/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/index.ts +++ b/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/index.ts @@ -1,14 +1,15 @@ import { fn } from '@storybook/test'; -import * as originalHeaders from 'next/dist/client/components/headers'; +import { draftMode as originalDraftMode } from 'next/dist/server/request/draft-mode'; +import * as headers from 'next/dist/server/request/headers'; // re-exports of the actual module -export * from 'next/dist/client/components/headers'; +export * from 'next/dist/server/request/headers'; // mock utilities/overrides (as of Next v14.2.0) export { headers } from './headers'; export { cookies } from './cookies'; // passthrough mocks - keep original implementation but allow for spying -const draftMode = fn(originalHeaders.draftMode).mockName('draftMode'); +const draftMode = fn(originalDraftMode ?? (headers as any).draftMode).mockName('draftMode'); export { draftMode }; diff --git a/code/frameworks/experimental-nextjs-vite/src/routing/app-router-provider.tsx b/code/frameworks/experimental-nextjs-vite/src/routing/app-router-provider.tsx index 99269e569075..68e01381948c 100644 --- a/code/frameworks/experimental-nextjs-vite/src/routing/app-router-provider.tsx +++ b/code/frameworks/experimental-nextjs-vite/src/routing/app-router-provider.tsx @@ -18,11 +18,14 @@ import { PathnameContext, SearchParamsContext, } from 'next/dist/shared/lib/hooks-client-context.shared-runtime'; -import { type Params } from 'next/dist/shared/lib/router/utils/route-matcher'; import { PAGE_SEGMENT_KEY } from 'next/dist/shared/lib/segment'; import type { RouteParams } from './types'; +// Using an inline type so we can support Next 14 and lower +// from https://github.com/vercel/next.js/blob/v15.0.3/packages/next/src/server/request/params.ts#L25 +type Params = Record<string, string | Array<string> | undefined>; + type AppRouterProviderProps = { routeParams: RouteParams; }; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/Head.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/Head.stories.tsx index db1b747bf78d..0d344078868f 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/Head.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/Head.stories.tsx @@ -33,8 +33,8 @@ export const Default: Story = { play: async () => { await waitFor(() => expect(document.title).toEqual('Next.js Head Title')); await expect(document.querySelectorAll('meta[property="og:title"]')).toHaveLength(1); - await expect((document.querySelector('meta[property="og:title"]') as any).content).toEqual( - 'My new title' - ); + await expect( + (document.querySelector('meta[property="og:title"]') as HTMLMetaElement)?.content + ).toEqual('My new title'); }, }; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/ImageLegacy.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/ImageLegacy.stories.tsx index 61e61b916cbe..5e8852c2fb38 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/ImageLegacy.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/ImageLegacy.stories.tsx @@ -1,5 +1,7 @@ import React from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + import Image from 'next/legacy/image'; import Accessibility from '../../assets/accessibility.svg'; @@ -10,17 +12,19 @@ export default { src: Accessibility, alt: 'Accessibility', }, -}; +} as Meta<typeof Image>; + +type Story = StoryObj<typeof Image>; -export const Default = {}; +export const Default: Story = {}; -export const BlurredPlaceholder = { +export const BlurredPlaceholder: Story = { args: { placeholder: 'blur', }, }; -export const BlurredAbsolutePlaceholder = { +export const BlurredAbsolutePlaceholder: Story = { args: { src: 'https://storybook.js.org/images/placeholders/50x50.png', width: 50, diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/Link.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/Link.stories.tsx index 7c1aa2073ab6..d071539c57a5 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/Link.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/Link.stories.tsx @@ -76,9 +76,11 @@ export default { component: Component, } as Meta<typeof Component>; -export const Default: StoryObj<typeof Component> = {}; +type Story = StoryObj<typeof Component>; -export const InAppDir: StoryObj<typeof Component> = { +export const Default: Story = {}; + +export const InAppDir: Story = { parameters: { nextjs: { appDirectory: true, diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/Navigation.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/Navigation.stories.tsx index d50ed5174d25..4b9b49904de0 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/Navigation.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/Navigation.stories.tsx @@ -109,7 +109,7 @@ export default { }, } as Meta<typeof Component>; -export const Default: StoryObj<typeof Component> = { +export const Default: Story = { play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); const routerMock = getRouter(); diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.stories.tsx index 178aea8c3ac8..1d31006f63e7 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.stories.tsx @@ -8,7 +8,11 @@ import NextHeader from './NextHeader'; export default { component: NextHeader, - parameters: { react: { rsc: true } }, + parameters: { + react: { + rsc: true, + }, + }, } as Meta<typeof NextHeader>; type Story = StoryObj<typeof NextHeader>; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.tsx index 6189f84baa62..eca7197ed79a 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.tsx @@ -5,25 +5,23 @@ import { cookies, headers } from 'next/headers'; export default async function Component() { async function handleClick() { 'use server'; - cookies().set('user-id', 'encrypted-id'); + (await cookies()).set('user-id', 'encrypted-id'); } return ( <> <h3>Cookies:</h3> - {cookies() - .getAll() - .map(({ name, value }) => { - return ( - <p key={name} style={{ display: 'flex', flexDirection: 'row', gap: 8 }}> - <strong>Name:</strong> <span>{name}</span> - <strong>Value:</strong> <span>{value}</span> - </p> - ); - })} + {(await cookies()).getAll().map(({ name, value }) => { + return ( + <p key={name} style={{ display: 'flex', flexDirection: 'row', gap: 8 }}> + <strong>Name:</strong> <span>{name}</span> + <strong>Value:</strong> <span>{value}</span> + </p> + ); + })} <h3>Headers:</h3> - {Array.from(headers().entries()).map(([name, value]: [string, string]) => { + {Array.from((await headers()).entries()).map(([name, value]: [string, string]) => { return ( <p key={name} style={{ display: 'flex', flexDirection: 'row', gap: 8 }}> <strong>Name:</strong> <span>{name}</span> diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/RSC.jsx b/code/frameworks/experimental-nextjs-vite/template/stories/RSC.jsx deleted file mode 100644 index a5771a6a9202..000000000000 --- a/code/frameworks/experimental-nextjs-vite/template/stories/RSC.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; - -import 'server-only'; - -export const RSC = async ({ label }) => <>RSC {label}</>; - -export const Nested = async ({ children }) => <>Nested {children}</>; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/RSC.stories.jsx b/code/frameworks/experimental-nextjs-vite/template/stories/RSC.stories.tsx similarity index 62% rename from code/frameworks/experimental-nextjs-vite/template/stories/RSC.stories.jsx rename to code/frameworks/experimental-nextjs-vite/template/stories/RSC.stories.tsx index f5520448bd61..655a5f1a93e4 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/RSC.stories.jsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/RSC.stories.tsx @@ -1,5 +1,8 @@ +/* eslint-disable local-rules/no-uncategorized-errors */ import React from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + import { Nested, RSC } from './RSC'; export default { @@ -10,11 +13,13 @@ export default { rsc: true, }, }, -}; +} as Meta<typeof RSC>; + +type Story = StoryObj<typeof RSC>; -export const Default = {}; +export const Default: Story = {}; -export const DisableRSC = { +export const DisableRSC: Story = { tags: ['!test'], parameters: { chromatic: { disable: true }, @@ -22,7 +27,7 @@ export const DisableRSC = { }, }; -export const Error = { +export const Errored: Story = { tags: ['!test', '!vitest'], parameters: { chromatic: { disable: true }, @@ -32,7 +37,7 @@ export const Error = { }, }; -export const NestedRSC = { +export const NestedRSC: Story = { render: (args) => ( <Nested> <RSC {...args} /> diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/RSC.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/RSC.tsx new file mode 100644 index 000000000000..24655728ff46 --- /dev/null +++ b/code/frameworks/experimental-nextjs-vite/template/stories/RSC.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +import 'server-only'; + +export const RSC = async ({ label }: { label: string }) => <>RSC {label}</>; + +export const Nested = async ({ children }: any) => <>Nested {children}</>; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.stories.tsx index 944bc42d8667..0844293c34f3 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.stories.tsx @@ -59,7 +59,9 @@ export default { }, } as Meta<typeof Component>; -export const ProtectedWhileLoggedOut: StoryObj<typeof Component> = { +type Story = StoryObj<typeof Component>; + +export const ProtectedWhileLoggedOut: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); await userEvent.click(canvas.getByText('Access protected route')); @@ -71,7 +73,7 @@ export const ProtectedWhileLoggedOut: StoryObj<typeof Component> = { }, }; -export const ProtectedWhileLoggedIn: StoryObj<typeof Component> = { +export const ProtectedWhileLoggedIn: Story = { beforeEach() { cookies().set('user', 'storybookjs'); }, @@ -87,7 +89,7 @@ export const ProtectedWhileLoggedIn: StoryObj<typeof Component> = { }, }; -export const Logout: StoryObj<typeof Component> = { +export const Logout: Story = { beforeEach() { cookies().set('user', 'storybookjs'); }, @@ -103,7 +105,7 @@ export const Logout: StoryObj<typeof Component> = { }, }; -export const Login: StoryObj<typeof Component> = { +export const Login: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); await userEvent.click(canvas.getByText('Login')); diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.tsx index 5e1b3c7227dc..6244f78d2472 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.tsx @@ -5,7 +5,7 @@ import { cookies } from 'next/headers'; import { redirect } from 'next/navigation'; export async function accessRoute() { - const user = cookies().get('user'); + const user = (await cookies()).get('user'); if (!user) { redirect('/'); @@ -16,13 +16,13 @@ export async function accessRoute() { } export async function logout() { - cookies().delete('user'); + (await cookies()).delete('user'); revalidatePath('/'); redirect('/'); } export async function login() { - cookies().set('user', 'storybookjs'); + (await cookies()).set('user', 'storybookjs'); revalidatePath('/'); redirect('/'); } diff --git a/code/frameworks/nextjs/template/stories/StyledJsx.stories.jsx b/code/frameworks/experimental-nextjs-vite/template/stories/StyledJsx.stories.tsx similarity index 66% rename from code/frameworks/nextjs/template/stories/StyledJsx.stories.jsx rename to code/frameworks/experimental-nextjs-vite/template/stories/StyledJsx.stories.tsx index 5a0c586e232c..31adea42456c 100644 --- a/code/frameworks/nextjs/template/stories/StyledJsx.stories.jsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/StyledJsx.stories.tsx @@ -1,5 +1,7 @@ import React from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + const Component = () => ( <div> <style jsx>{` @@ -15,6 +17,6 @@ const Component = () => ( export default { component: Component, -}; +} as Meta<typeof Component>; -export const Default = {}; +export const Default: StoryObj<typeof Component> = {}; diff --git a/code/frameworks/html-vite/package.json b/code/frameworks/html-vite/package.json index 1d2c28e55d49..849c3b051fe4 100644 --- a/code/frameworks/html-vite/package.json +++ b/code/frameworks/html-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-vite", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for HTML and Vite: Develop HTML in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/html-webpack5/package.json b/code/frameworks/html-webpack5/package.json index c906836614ac..932893dca882 100644 --- a/code/frameworks/html-webpack5/package.json +++ b/code/frameworks/html-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-webpack5", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json index 79bc3f6613ee..616789440b51 100644 --- a/code/frameworks/nextjs/package.json +++ b/code/frameworks/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/nextjs", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Next.js", "keywords": [ "storybook", @@ -57,6 +57,11 @@ "import": "./dist/compatibility/redirect-status-code.compat.mjs", "require": "./dist/compatibility/redirect-status-code.compat.js" }, + "./dist/compatibility/draft-mode.compat": { + "types": "./dist/compatibility/draft-mode.compat.d.ts", + "import": "./dist/compatibility/draft-mode.compat.mjs", + "require": "./dist/compatibility/draft-mode.compat.js" + }, "./export-mocks": { "types": "./dist/export-mocks/index.d.ts", "import": "./dist/export-mocks/index.mjs", @@ -171,12 +176,12 @@ "@types/babel__preset-env": "^7", "@types/loader-utils": "^2.0.5", "@types/react-refresh": "^0", - "next": "^14.1.0", + "next": "^15.0.3", "typescript": "^5.3.2", "webpack": "^5.65.0" }, "peerDependencies": { - "next": "^13.5.0 || ^14.0.0", + "next": "^13.5.0 || ^14.0.0 || ^15.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "storybook": "workspace:^", @@ -212,6 +217,7 @@ "./src/export-mocks/navigation/index.ts", "./src/compatibility/segment.compat.ts", "./src/compatibility/redirect-status-code.compat.ts", + "./src/compatibility/draft-mode.compat.ts", "./src/next-image-loader-stub.ts", "./src/images/decorator.tsx", "./src/images/next-legacy-image.tsx", diff --git a/code/frameworks/nextjs/src/aliases/webpack.ts b/code/frameworks/nextjs/src/aliases/webpack.ts index ceacfa541a29..b5a9715505f4 100644 --- a/code/frameworks/nextjs/src/aliases/webpack.ts +++ b/code/frameworks/nextjs/src/aliases/webpack.ts @@ -1,6 +1,12 @@ import type { Configuration as WebpackConfig } from 'webpack'; +import { configureCompatibilityAliases } from '../compatibility/compatibility-map'; +import { configureNextExportMocks } from '../export-mocks/webpack'; + export const configureAliases = (baseConfig: WebpackConfig): void => { + configureNextExportMocks(baseConfig); + configureCompatibilityAliases(baseConfig); + baseConfig.resolve = { ...(baseConfig.resolve ?? {}), alias: { @@ -8,4 +14,12 @@ export const configureAliases = (baseConfig: WebpackConfig): void => { '@opentelemetry/api': 'next/dist/compiled/@opentelemetry/api', }, }; + + // remove warnings regarding compatibility paths + baseConfig.ignoreWarnings = [ + ...(baseConfig.ignoreWarnings ?? []), + (warning) => + warning.message.includes("export 'draftMode'") && + warning.message.includes('next/dist/server/request/headers'), + ]; }; diff --git a/code/frameworks/nextjs/src/compatibility/compatibility-map.ts b/code/frameworks/nextjs/src/compatibility/compatibility-map.ts index 7f17cf10edc8..4cfb5e92f0b3 100644 --- a/code/frameworks/nextjs/src/compatibility/compatibility-map.ts +++ b/code/frameworks/nextjs/src/compatibility/compatibility-map.ts @@ -1,9 +1,9 @@ import semver from 'semver'; import type { Configuration as WebpackConfig } from 'webpack'; -import { addScopedAlias, getNextjsVersion } from '../utils'; +import { addScopedAlias, getNextjsVersion, setAlias } from '../utils'; -const mapping: Record<string, Record<string, string>> = { +const mapping: Record<string, Record<string, string | boolean>> = { '<14.1.0': { // https://github.com/vercel/next.js/blob/v14.1.0/packages/next/src/shared/lib/segment.ts 'next/dist/shared/lib/segment': '@storybook/nextjs/dist/compatibility/segment.compat', @@ -13,6 +13,11 @@ const mapping: Record<string, Record<string, string>> = { 'next/dist/client/components/redirect-status-code': '@storybook/nextjs/dist/compatibility/redirect-status-code.compat', }, + '<15.0.0': { + 'next/dist/server/request/headers': 'next/dist/client/components/headers', + // this path only exists from Next 15 onwards + 'next/dist/server/request/draft-mode': '@storybook/nextjs/dist/compatibility/draft-mode.compat', + }, }; export const getCompatibilityAliases = () => { @@ -32,6 +37,10 @@ export const configureCompatibilityAliases = (baseConfig: WebpackConfig): void = const aliases = getCompatibilityAliases(); Object.entries(aliases).forEach(([name, alias]) => { - addScopedAlias(baseConfig, name, alias); + if (typeof alias === 'string') { + addScopedAlias(baseConfig, name, alias); + } else { + setAlias(baseConfig, name, alias); + } }); }; diff --git a/code/frameworks/nextjs/src/compatibility/draft-mode.compat.ts b/code/frameworks/nextjs/src/compatibility/draft-mode.compat.ts new file mode 100644 index 000000000000..cdcaf63bbf1a --- /dev/null +++ b/code/frameworks/nextjs/src/compatibility/draft-mode.compat.ts @@ -0,0 +1,2 @@ +// @ts-expect-error Compatibility for Next 14 +export { draftMode } from 'next/dist/client/components/headers'; diff --git a/code/frameworks/nextjs/src/export-mocks/headers/index.ts b/code/frameworks/nextjs/src/export-mocks/headers/index.ts index 1797d4ccaf57..1c903963ba2d 100644 --- a/code/frameworks/nextjs/src/export-mocks/headers/index.ts +++ b/code/frameworks/nextjs/src/export-mocks/headers/index.ts @@ -1,14 +1,15 @@ import { fn } from '@storybook/test'; -import * as originalHeaders from 'next/dist/client/components/headers'; +import { draftMode as originalDraftMode } from 'next/dist/server/request/draft-mode'; +import * as headers from 'next/dist/server/request/headers'; // re-exports of the actual module -export * from 'next/dist/client/components/headers'; +export * from 'next/dist/server/request/headers'; // mock utilities/overrides (as of Next v14.2.0) export { headers } from './headers'; export { cookies } from './cookies'; // passthrough mocks - keep original implementation but allow for spying -const draftMode = fn(originalHeaders.draftMode).mockName('draftMode'); +const draftMode = fn(originalDraftMode ?? (headers as any).draftMode).mockName('draftMode'); export { draftMode }; diff --git a/code/frameworks/nextjs/src/export-mocks/webpack.ts b/code/frameworks/nextjs/src/export-mocks/webpack.ts index 3d054d114ed2..4f7376770588 100644 --- a/code/frameworks/nextjs/src/export-mocks/webpack.ts +++ b/code/frameworks/nextjs/src/export-mocks/webpack.ts @@ -23,14 +23,14 @@ export const getPackageAliases = ({ useESM = false }: { useESM?: boolean } = {}) const packageLocation = dirname(require.resolve('@storybook/nextjs/package.json')); const getFullPath = (path: string) => - join(packageLocation, path.replace('@storybook/nextjs', '')); + path.startsWith('next') ? path : join(packageLocation, path.replace('@storybook/nextjs', '')); const aliases = Object.fromEntries( Object.entries(mapping).map(([originalPath, aliasedPath]) => [ originalPath, // Use paths for both next/xyz and @storybook/nextjs/xyz imports // to make sure they all serve the MJS/CJS version of the file - getFullPath(`${aliasedPath}.${extension}`), + typeof aliasedPath === 'string' ? getFullPath(`${aliasedPath}.${extension}`) : aliasedPath, ]) ); diff --git a/code/frameworks/nextjs/src/preset.ts b/code/frameworks/nextjs/src/preset.ts index 1956b978a37a..3463910175e1 100644 --- a/code/frameworks/nextjs/src/preset.ts +++ b/code/frameworks/nextjs/src/preset.ts @@ -162,8 +162,6 @@ export const webpackFinal: StorybookConfig['webpackFinal'] = async (baseConfig, configureStyledJsx(baseConfig); configureNodePolyfills(baseConfig); configureAliases(baseConfig); - configureCompatibilityAliases(baseConfig); - configureNextExportMocks(baseConfig); if (isDevelopment) { configureFastRefresh(baseConfig); diff --git a/code/frameworks/nextjs/src/routing/app-router-provider.tsx b/code/frameworks/nextjs/src/routing/app-router-provider.tsx index 881bb98a172f..36e980b1a5fe 100644 --- a/code/frameworks/nextjs/src/routing/app-router-provider.tsx +++ b/code/frameworks/nextjs/src/routing/app-router-provider.tsx @@ -18,11 +18,14 @@ import { PathnameContext, SearchParamsContext, } from 'next/dist/shared/lib/hooks-client-context.shared-runtime'; -import { type Params } from 'next/dist/shared/lib/router/utils/route-matcher'; import { PAGE_SEGMENT_KEY } from 'next/dist/shared/lib/segment'; import type { RouteParams } from './types'; +// Using an inline type so we can support Next 14 and lower +// from https://github.com/vercel/next.js/blob/v15.0.3/packages/next/src/server/request/params.ts#L25 +type Params = Record<string, string | Array<string> | undefined>; + type AppRouterProviderProps = { routeParams: RouteParams; }; diff --git a/code/frameworks/nextjs/template/stories/DynamicImport.stories.jsx b/code/frameworks/nextjs/template/stories/DynamicImport.stories.tsx similarity index 70% rename from code/frameworks/nextjs/template/stories/DynamicImport.stories.jsx rename to code/frameworks/nextjs/template/stories/DynamicImport.stories.tsx index e9efbd0f7080..b71430f72544 100644 --- a/code/frameworks/nextjs/template/stories/DynamicImport.stories.jsx +++ b/code/frameworks/nextjs/template/stories/DynamicImport.stories.tsx @@ -1,5 +1,7 @@ import React, { Suspense } from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + import dynamic from 'next/dynamic'; const DynamicComponent = dynamic(() => import('./dynamic-component'), { @@ -16,6 +18,6 @@ function Component() { export default { component: Component, -}; +} as Meta<typeof Component>; -export const Default = {}; +export const Default: StoryObj<typeof Component> = {}; diff --git a/code/frameworks/nextjs/template/stories/Font.stories.tsx b/code/frameworks/nextjs/template/stories/Font.stories.tsx new file mode 100644 index 000000000000..0e078409da0b --- /dev/null +++ b/code/frameworks/nextjs/template/stories/Font.stories.tsx @@ -0,0 +1,27 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import Font from './Font'; + +export default { + component: Font, +} as Meta<typeof Font>; + +type Story = StoryObj<typeof Font>; + +export const WithClassName: Story = { + args: { + variant: 'className', + }, +}; + +export const WithStyle: Story = { + args: { + variant: 'style', + }, +}; + +export const WithVariable: Story = { + args: { + variant: 'variable', + }, +}; diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-js/Font.jsx b/code/frameworks/nextjs/template/stories/Font.tsx similarity index 94% rename from code/frameworks/nextjs/template/stories_nextjs-default-js/Font.jsx rename to code/frameworks/nextjs/template/stories/Font.tsx index f7509914db0c..5c7779fa60b4 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-js/Font.jsx +++ b/code/frameworks/nextjs/template/stories/Font.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types */ import React from 'react'; import { Rubik_Puddles } from 'next/font/google'; @@ -15,7 +14,7 @@ export const localRubikStorm = localFont({ variable: '--font-rubik-storm', }); -export default function Font({ variant }) { +export default function Font({ variant }: { variant: 'className' | 'style' | 'variable' }) { switch (variant) { case 'className': return ( diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-js/Head.stories.jsx b/code/frameworks/nextjs/template/stories/Head.stories.tsx similarity index 71% rename from code/frameworks/nextjs/template/stories_nextjs-default-js/Head.stories.jsx rename to code/frameworks/nextjs/template/stories/Head.stories.tsx index 7b86941b0073..540d0e04dc3d 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-js/Head.stories.jsx +++ b/code/frameworks/nextjs/template/stories/Head.stories.tsx @@ -1,5 +1,6 @@ import React from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; import { expect, waitFor } from '@storybook/test'; import Head from 'next/head'; @@ -21,14 +22,14 @@ function Component() { export default { component: Component, -}; +} as Meta<typeof Component>; -export const Default = { +export const Default: StoryObj<typeof Component> = { play: async () => { await waitFor(() => expect(document.title).toEqual('Next.js Head Title')); await expect(document.querySelectorAll('meta[property="og:title"]')).toHaveLength(1); - await expect(document.querySelector('meta[property="og:title"]').content).toEqual( - 'My new title' - ); + await expect( + (document.querySelector('meta[property="og:title"]') as HTMLMetaElement)?.content + ).toEqual('My new title'); }, }; diff --git a/code/frameworks/nextjs/template/stories/Image.stories.jsx b/code/frameworks/nextjs/template/stories/Image.stories.tsx similarity index 83% rename from code/frameworks/nextjs/template/stories/Image.stories.jsx rename to code/frameworks/nextjs/template/stories/Image.stories.tsx index 47f28711224e..ebceacaf1300 100644 --- a/code/frameworks/nextjs/template/stories/Image.stories.jsx +++ b/code/frameworks/nextjs/template/stories/Image.stories.tsx @@ -1,4 +1,6 @@ -import React, { useRef, useState } from 'react'; +import React, { useState } from 'react'; + +import type { Meta, StoryObj } from '@storybook/react'; import Image from 'next/image'; @@ -11,24 +13,26 @@ export default { src: Accessibility, alt: 'Accessibility', }, -}; +} as Meta<typeof Image>; + +type Story = StoryObj<typeof Image>; -export const Default = {}; +export const Default: Story = {}; -export const Avif = { +export const Avif: Story = { args: { src: AvifImage, alt: 'Avif Test Image', }, }; -export const BlurredPlaceholder = { +export const BlurredPlaceholder: Story = { args: { placeholder: 'blur', }, }; -export const BlurredAbsolutePlaceholder = { +export const BlurredAbsolutePlaceholder: Story = { args: { src: 'https://storybook.js.org/images/placeholders/50x50.png', width: 50, @@ -44,26 +48,26 @@ export const BlurredAbsolutePlaceholder = { }, }; -export const FilledParent = { +export const FilledParent: Story = { args: { fill: true, }, - decorator: [ + decorators: [ (Story) => <div style={{ width: 500, height: 500, position: 'relative' }}>{Story()}</div>, ], }; -export const Sized = { +export const Sized: Story = { args: { fill: true, sizes: '(max-width: 600px) 100vw, 600px', - decorator: [ - (Story) => <div style={{ width: 800, height: 800, position: 'relative' }}>{Story()}</div>, - ], }, + decorators: [ + (Story) => <div style={{ width: 800, height: 800, position: 'relative' }}>{Story()}</div>, + ], }; -export const Lazy = { +export const Lazy: Story = { args: { src: 'https://storybook.js.org/images/placeholders/50x50.png', width: 50, @@ -79,7 +83,7 @@ export const Lazy = { ], }; -export const Eager = { +export const Eager: Story = { ...Lazy, parameters: { nextjs: { @@ -90,9 +94,9 @@ export const Eager = { }, }; -export const WithRef = { +export const WithRef: Story = { render() { - const [ref, setRef] = useState(null); + const [ref, setRef] = useState<HTMLImageElement | null>(null); return ( <div> diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-js/ImageLegacy.stories.jsx b/code/frameworks/nextjs/template/stories/ImageLegacy.stories.tsx similarity index 90% rename from code/frameworks/nextjs/template/stories_nextjs-default-js/ImageLegacy.stories.jsx rename to code/frameworks/nextjs/template/stories/ImageLegacy.stories.tsx index 61e61b916cbe..954bc36a260f 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-js/ImageLegacy.stories.jsx +++ b/code/frameworks/nextjs/template/stories/ImageLegacy.stories.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; import Image from 'next/legacy/image'; @@ -10,17 +10,19 @@ export default { src: Accessibility, alt: 'Accessibility', }, -}; +} as Meta<typeof Image>; + +type Story = StoryObj<typeof Image>; -export const Default = {}; +export const Default: Story = {}; -export const BlurredPlaceholder = { +export const BlurredPlaceholder: Story = { args: { placeholder: 'blur', }, }; -export const BlurredAbsolutePlaceholder = { +export const BlurredAbsolutePlaceholder: Story = { args: { src: 'https://storybook.js.org/images/placeholders/50x50.png', width: 50, diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-js/Link.stories.module.css b/code/frameworks/nextjs/template/stories/Link.stories.module.css similarity index 100% rename from code/frameworks/nextjs/template/stories_nextjs-default-js/Link.stories.module.css rename to code/frameworks/nextjs/template/stories/Link.stories.module.css diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Link.stories.tsx b/code/frameworks/nextjs/template/stories/Link.stories.tsx similarity index 94% rename from code/frameworks/nextjs/template/stories_nextjs-default-ts/Link.stories.tsx rename to code/frameworks/nextjs/template/stories/Link.stories.tsx index 7c1aa2073ab6..d071539c57a5 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Link.stories.tsx +++ b/code/frameworks/nextjs/template/stories/Link.stories.tsx @@ -76,9 +76,11 @@ export default { component: Component, } as Meta<typeof Component>; -export const Default: StoryObj<typeof Component> = {}; +type Story = StoryObj<typeof Component>; -export const InAppDir: StoryObj<typeof Component> = { +export const Default: Story = {}; + +export const InAppDir: Story = { parameters: { nextjs: { appDirectory: true, diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Navigation.stories.tsx b/code/frameworks/nextjs/template/stories/Navigation.stories.tsx similarity index 98% rename from code/frameworks/nextjs/template/stories_nextjs-default-ts/Navigation.stories.tsx rename to code/frameworks/nextjs/template/stories/Navigation.stories.tsx index 58dd07548841..5c4872d1ac31 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Navigation.stories.tsx +++ b/code/frameworks/nextjs/template/stories/Navigation.stories.tsx @@ -108,7 +108,7 @@ export default { }, } as Meta<typeof Component>; -export const Default: StoryObj<typeof Component> = { +export const Default: Story = { play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); const routerMock = getRouter(); diff --git a/code/frameworks/nextjs/template/stories/RSC.jsx b/code/frameworks/nextjs/template/stories/RSC.jsx deleted file mode 100644 index a5771a6a9202..000000000000 --- a/code/frameworks/nextjs/template/stories/RSC.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; - -import 'server-only'; - -export const RSC = async ({ label }) => <>RSC {label}</>; - -export const Nested = async ({ children }) => <>Nested {children}</>; diff --git a/code/frameworks/nextjs/template/stories/RSC.stories.jsx b/code/frameworks/nextjs/template/stories/RSC.stories.tsx similarity index 59% rename from code/frameworks/nextjs/template/stories/RSC.stories.jsx rename to code/frameworks/nextjs/template/stories/RSC.stories.tsx index 774e129cbd58..655a5f1a93e4 100644 --- a/code/frameworks/nextjs/template/stories/RSC.stories.jsx +++ b/code/frameworks/nextjs/template/stories/RSC.stories.tsx @@ -1,5 +1,8 @@ +/* eslint-disable local-rules/no-uncategorized-errors */ import React from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + import { Nested, RSC } from './RSC'; export default { @@ -10,11 +13,13 @@ export default { rsc: true, }, }, -}; +} as Meta<typeof RSC>; -export const Default = {}; +type Story = StoryObj<typeof RSC>; -export const DisableRSC = { +export const Default: Story = {}; + +export const DisableRSC: Story = { tags: ['!test'], parameters: { chromatic: { disable: true }, @@ -22,8 +27,8 @@ export const DisableRSC = { }, }; -export const Error = { - tags: ['!test'], +export const Errored: Story = { + tags: ['!test', '!vitest'], parameters: { chromatic: { disable: true }, }, @@ -32,7 +37,7 @@ export const Error = { }, }; -export const NestedRSC = { +export const NestedRSC: Story = { render: (args) => ( <Nested> <RSC {...args} /> diff --git a/code/frameworks/nextjs/template/stories/RSC.tsx b/code/frameworks/nextjs/template/stories/RSC.tsx new file mode 100644 index 000000000000..24655728ff46 --- /dev/null +++ b/code/frameworks/nextjs/template/stories/RSC.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +import 'server-only'; + +export const RSC = async ({ label }: { label: string }) => <>RSC {label}</>; + +export const Nested = async ({ children }: any) => <>Nested {children}</>; diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Router.stories.tsx b/code/frameworks/nextjs/template/stories/Router.stories.tsx similarity index 100% rename from code/frameworks/nextjs/template/stories_nextjs-default-ts/Router.stories.tsx rename to code/frameworks/nextjs/template/stories/Router.stories.tsx diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/StyledJsx.stories.jsx b/code/frameworks/nextjs/template/stories/StyledJsx.stories.tsx similarity index 66% rename from code/frameworks/experimental-nextjs-vite/template/stories/StyledJsx.stories.jsx rename to code/frameworks/nextjs/template/stories/StyledJsx.stories.tsx index 5a0c586e232c..31adea42456c 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/StyledJsx.stories.jsx +++ b/code/frameworks/nextjs/template/stories/StyledJsx.stories.tsx @@ -1,5 +1,7 @@ import React from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + const Component = () => ( <div> <style jsx>{` @@ -15,6 +17,6 @@ const Component = () => ( export default { component: Component, -}; +} as Meta<typeof Component>; -export const Default = {}; +export const Default: StoryObj<typeof Component> = {}; diff --git a/code/frameworks/nextjs/template/stories/dynamic-component.jsx b/code/frameworks/nextjs/template/stories/dynamic-component.tsx similarity index 100% rename from code/frameworks/nextjs/template/stories/dynamic-component.jsx rename to code/frameworks/nextjs/template/stories/dynamic-component.tsx diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-js/fonts/OFL.txt b/code/frameworks/nextjs/template/stories/fonts/OFL.txt similarity index 100% rename from code/frameworks/nextjs/template/stories_nextjs-default-js/fonts/OFL.txt rename to code/frameworks/nextjs/template/stories/fonts/OFL.txt diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-js/fonts/RubikStorm-Regular.ttf b/code/frameworks/nextjs/template/stories/fonts/RubikStorm-Regular.ttf similarity index 100% rename from code/frameworks/nextjs/template/stories_nextjs-default-js/fonts/RubikStorm-Regular.ttf rename to code/frameworks/nextjs/template/stories/fonts/RubikStorm-Regular.ttf diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-js/Font.stories.jsx b/code/frameworks/nextjs/template/stories_nextjs-default-js/Font.stories.jsx deleted file mode 100644 index b851661dd436..000000000000 --- a/code/frameworks/nextjs/template/stories_nextjs-default-js/Font.stories.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import Font from './Font'; - -export default { - component: Font, -}; - -export const WithClassName = { - args: { - variant: 'className', - }, -}; - -export const WithStyle = { - args: { - variant: 'style', - }, -}; - -export const WithVariable = { - args: { - variant: 'variable', - }, -}; diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-js/Link.stories.jsx b/code/frameworks/nextjs/template/stories_nextjs-default-js/Link.stories.jsx deleted file mode 100644 index 14aa9d6805c6..000000000000 --- a/code/frameworks/nextjs/template/stories_nextjs-default-js/Link.stories.jsx +++ /dev/null @@ -1,83 +0,0 @@ -/* eslint-disable react/prop-types */ -import React from 'react'; - -import Link from 'next/link'; - -import style from './Link.stories.module.css'; - -// `onClick`, `href`, and `ref` need to be passed to the DOM element -// for proper handling -const MyButton = React.forwardRef(function Button({ onClick, href, children }, ref) { - return ( - <a href={href} onClick={onClick} ref={ref}> - {children} - </a> - ); -}); - -const Component = () => ( - <ul> - <li> - <Link href="/">Normal Link</Link> - </li> - <li> - <Link - href={{ - pathname: '/with-url-object', - query: { name: 'test' }, - }} - > - With URL Object - </Link> - </li> - <li> - <Link href="/replace-url" replace> - Replace the URL instead of push - </Link> - </li> - <li> - <Link href="/legacy-behaviour" legacyBehavior> - <a>Legacy behavior</a> - </Link> - </li> - <li> - <Link href="/child-is-functional-component" passHref legacyBehavior> - <MyButton>child is a functional component</MyButton> - </Link> - </li> - <li> - <Link href="/#hashid" scroll={false}> - Disables scrolling to the top - </Link> - </li> - <li> - <Link href="/no-prefetch" prefetch={false}> - No Prefetching - </Link> - </li> - <li> - <Link style={{ color: 'red' }} href="/with-style"> - With style - </Link> - </li> - <li> - <Link className={style.link} href="/with-classname"> - With className - </Link> - </li> - </ul> -); - -export default { - component: Component, -}; - -export const Default = {}; - -export const InAppDir = { - parameters: { - nextjs: { - appDirectory: true, - }, - }, -}; diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-js/GetImageProps.stories.jsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx similarity index 83% rename from code/frameworks/nextjs/template/stories_nextjs-default-js/GetImageProps.stories.jsx rename to code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx index f3e7c0b7462b..aefc27f54cfd 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-js/GetImageProps.stories.jsx +++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx @@ -1,12 +1,14 @@ import React from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + import { getImageProps } from 'next/image'; import Accessibility from '../../assets/accessibility.svg'; import Testing from '../../assets/testing.png'; // referenced from https://nextjs.org/docs/pages/api-reference/components/image#theme-detection-picture -const Component = (props) => { +const Component = (props: any) => { const { props: { srcSet: dark }, } = getImageProps({ src: Accessibility, ...props }); @@ -29,6 +31,6 @@ export default { args: { alt: 'getImageProps Example', }, -}; +} as Meta<typeof Component>; -export const Default = {}; +export const Default: StoryObj<typeof Component> = {}; diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Link.stories.module.css b/code/frameworks/nextjs/template/stories_nextjs-default-ts/Link.stories.module.css deleted file mode 100644 index 9edb616226d0..000000000000 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Link.stories.module.css +++ /dev/null @@ -1,3 +0,0 @@ -.link { - color: green; -} diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx index 059bcbcff7b7..f5e83ef867f6 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx @@ -1,6 +1,5 @@ import { cookies, headers } from '@storybook/nextjs/headers.mock'; -import type { Meta } from '@storybook/react'; -import type { StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react'; import { expect, userEvent, within } from '@storybook/test'; import NextHeader from './NextHeader'; diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.tsx index 6189f84baa62..eca7197ed79a 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.tsx @@ -5,25 +5,23 @@ import { cookies, headers } from 'next/headers'; export default async function Component() { async function handleClick() { 'use server'; - cookies().set('user-id', 'encrypted-id'); + (await cookies()).set('user-id', 'encrypted-id'); } return ( <> <h3>Cookies:</h3> - {cookies() - .getAll() - .map(({ name, value }) => { - return ( - <p key={name} style={{ display: 'flex', flexDirection: 'row', gap: 8 }}> - <strong>Name:</strong> <span>{name}</span> - <strong>Value:</strong> <span>{value}</span> - </p> - ); - })} + {(await cookies()).getAll().map(({ name, value }) => { + return ( + <p key={name} style={{ display: 'flex', flexDirection: 'row', gap: 8 }}> + <strong>Name:</strong> <span>{name}</span> + <strong>Value:</strong> <span>{value}</span> + </p> + ); + })} <h3>Headers:</h3> - {Array.from(headers().entries()).map(([name, value]: [string, string]) => { + {Array.from((await headers()).entries()).map(([name, value]: [string, string]) => { return ( <p key={name} style={{ display: 'flex', flexDirection: 'row', gap: 8 }}> <strong>Name:</strong> <span>{name}</span> diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx index 018c4d33b54f..f1a9ad762eed 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx @@ -58,7 +58,9 @@ export default { }, } as Meta<typeof Component>; -export const ProtectedWhileLoggedOut: StoryObj<typeof Component> = { +type Story = StoryObj<typeof Component>; + +export const ProtectedWhileLoggedOut: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); await userEvent.click(canvas.getByText('Access protected route')); @@ -70,7 +72,7 @@ export const ProtectedWhileLoggedOut: StoryObj<typeof Component> = { }, }; -export const ProtectedWhileLoggedIn: StoryObj<typeof Component> = { +export const ProtectedWhileLoggedIn: Story = { beforeEach() { cookies().set('user', 'storybookjs'); }, @@ -86,7 +88,7 @@ export const ProtectedWhileLoggedIn: StoryObj<typeof Component> = { }, }; -export const Logout: StoryObj<typeof Component> = { +export const Logout: Story = { beforeEach() { cookies().set('user', 'storybookjs'); }, @@ -102,7 +104,7 @@ export const Logout: StoryObj<typeof Component> = { }, }; -export const Login: StoryObj<typeof Component> = { +export const Login: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); await userEvent.click(canvas.getByText('Login')); diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/server-actions.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/server-actions.tsx index 5e1b3c7227dc..6244f78d2472 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/server-actions.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/server-actions.tsx @@ -5,7 +5,7 @@ import { cookies } from 'next/headers'; import { redirect } from 'next/navigation'; export async function accessRoute() { - const user = cookies().get('user'); + const user = (await cookies()).get('user'); if (!user) { redirect('/'); @@ -16,13 +16,13 @@ export async function accessRoute() { } export async function logout() { - cookies().delete('user'); + (await cookies()).delete('user'); revalidatePath('/'); redirect('/'); } export async function login() { - cookies().set('user', 'storybookjs'); + (await cookies()).set('user', 'storybookjs'); revalidatePath('/'); redirect('/'); } diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx new file mode 100644 index 000000000000..aefc27f54cfd --- /dev/null +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx @@ -0,0 +1,36 @@ +import React from 'react'; + +import type { Meta, StoryObj } from '@storybook/react'; + +import { getImageProps } from 'next/image'; + +import Accessibility from '../../assets/accessibility.svg'; +import Testing from '../../assets/testing.png'; + +// referenced from https://nextjs.org/docs/pages/api-reference/components/image#theme-detection-picture +const Component = (props: any) => { + const { + props: { srcSet: dark }, + } = getImageProps({ src: Accessibility, ...props }); + const { + // capture rest on one to spread to img as default; it doesn't matter which barring art direction + props: { srcSet: light, ...rest }, + } = getImageProps({ src: Testing, ...props }); + + return ( + <picture> + <source media="(prefers-color-scheme: dark)" srcSet={dark} /> + <source media="(prefers-color-scheme: light)" srcSet={light} /> + <img {...rest} /> + </picture> + ); +}; + +export default { + component: Component, + args: { + alt: 'getImageProps Example', + }, +} as Meta<typeof Component>; + +export const Default: StoryObj<typeof Component> = {}; diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx new file mode 100644 index 000000000000..f5e83ef867f6 --- /dev/null +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx @@ -0,0 +1,51 @@ +import { cookies, headers } from '@storybook/nextjs/headers.mock'; +import type { Meta, StoryObj } from '@storybook/react'; +import { expect, userEvent, within } from '@storybook/test'; + +import NextHeader from './NextHeader'; + +export default { + component: NextHeader, + parameters: { + react: { + rsc: true, + }, + }, +} as Meta<typeof NextHeader>; + +type Story = StoryObj<typeof NextHeader>; + +export const Default: Story = { + loaders: async () => { + cookies().set('firstName', 'Jane'); + cookies().set({ + name: 'lastName', + value: 'Doe', + }); + headers().set('timezone', 'Central European Summer Time'); + }, + play: async ({ canvasElement, step }) => { + const canvas = within(canvasElement); + const headersMock = headers(); + const cookiesMock = cookies(); + await step('Cookie and header store apis are called upon rendering', async () => { + await expect(cookiesMock.getAll).toHaveBeenCalled(); + await expect(headersMock.entries).toHaveBeenCalled(); + }); + + await step('Upon clicking on submit, the user-id cookie is set', async () => { + const submitButton = await canvas.findByRole('button'); + await userEvent.click(submitButton); + + await expect(cookiesMock.set).toHaveBeenCalledWith('user-id', 'encrypted-id'); + }); + + await step('The user-id cookie is available in cookie and header stores', async () => { + await expect(headersMock.get('cookie')).toContain('user-id=encrypted-id'); + await expect(cookiesMock.get('user-id')).toEqual({ + name: 'user-id', + value: 'encrypted-id', + }); + }); + }, +}; diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.tsx new file mode 100644 index 000000000000..eca7197ed79a --- /dev/null +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.tsx @@ -0,0 +1,38 @@ +import React from 'react'; + +import { cookies, headers } from 'next/headers'; + +export default async function Component() { + async function handleClick() { + 'use server'; + (await cookies()).set('user-id', 'encrypted-id'); + } + + return ( + <> + <h3>Cookies:</h3> + {(await cookies()).getAll().map(({ name, value }) => { + return ( + <p key={name} style={{ display: 'flex', flexDirection: 'row', gap: 8 }}> + <strong>Name:</strong> <span>{name}</span> + <strong>Value:</strong> <span>{value}</span> + </p> + ); + })} + + <h3>Headers:</h3> + {Array.from((await headers()).entries()).map(([name, value]: [string, string]) => { + return ( + <p key={name} style={{ display: 'flex', flexDirection: 'row', gap: 8 }}> + <strong>Name:</strong> <span>{name}</span> + <strong>Value:</strong> <span>{value}</span> + </p> + ); + })} + + <form action={handleClick}> + <button>add user-id cookie</button> + </form> + </> + ); +} diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx new file mode 100644 index 000000000000..3c5980b79757 --- /dev/null +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx @@ -0,0 +1,57 @@ +import React from 'react'; + +import type { Meta, StoryObj } from '@storybook/react'; +import { userEvent, within } from '@storybook/test'; + +import { redirect } from 'next/navigation'; + +let state = 'Bug! Not invalidated'; + +export default { + render() { + return ( + <div> + <div>{state}</div> + <form + action={() => { + state = 'State is invalidated successfully.'; + redirect('/'); + }} + > + <button>Submit</button> + </form> + </div> + ); + }, + parameters: { + test: { + // This is needed until Next will update to the React 19 beta: https://github.com/vercel/next.js/pull/65058 + // In the React 19 beta ErrorBoundary errors (such as redirect) are only logged, and not thrown. + // We will also suspress console.error logs for re the console.error logs for redirect in the next framework. + // Using the onCaughtError react root option: + // react: { + // rootOptions: { + // onCaughtError(error: unknown) { + // if (isNextRouterError(error)) return; + // console.error(error); + // }, + // }, + // See: code/frameworks/nextjs/src/preview.tsx + dangerouslyIgnoreUnhandledErrors: true, + }, + nextjs: { + appDirectory: true, + navigation: { + pathname: '/', + }, + }, + }, + tags: ['!test'], +} as Meta; + +export const SingletonStateGetsInvalidatedAfterRedirecting: StoryObj = { + play: async ({ canvasElement, step }) => { + const canvas = within(canvasElement); + await userEvent.click(canvas.getByRole('button')); + }, +}; diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/ServerActions.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/ServerActions.stories.tsx new file mode 100644 index 000000000000..f1a9ad762eed --- /dev/null +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/ServerActions.stories.tsx @@ -0,0 +1,118 @@ +import React from 'react'; + +import { revalidatePath } from '@storybook/nextjs/cache.mock'; +import { cookies } from '@storybook/nextjs/headers.mock'; +import { getRouter, redirect } from '@storybook/nextjs/navigation.mock'; +import type { Meta, StoryObj } from '@storybook/react'; +import { expect, userEvent, waitFor, within } from '@storybook/test'; + +import { accessRoute, login, logout } from './server-actions'; + +function Component() { + return ( + <div style={{ display: 'flex', gap: 8 }}> + <form> + <button type="submit" formAction={login}> + Login + </button> + </form> + <form> + <button type="submit" formAction={logout}> + Logout + </button> + </form> + <form> + <button type="submit" formAction={accessRoute}> + Access protected route + </button> + </form> + </div> + ); +} + +export default { + component: Component, + tags: ['!test'], + parameters: { + nextjs: { + appDirectory: true, + navigation: { + pathname: '/', + }, + }, + test: { + // This is needed until Next will update to the React 19 beta: https://github.com/vercel/next.js/pull/65058 + // In the React 19 beta ErrorBoundary errors (such as redirect) are only logged, and not thrown. + // We will also suspress console.error logs for re the console.error logs for redirect in the next framework. + // Using the onCaughtError react root option: + // react: { + // rootOptions: { + // onCaughtError(error: unknown) { + // if (isNextRouterError(error)) return; + // console.error(error); + // }, + // }, + // See: code/frameworks/nextjs/src/preview.tsx + dangerouslyIgnoreUnhandledErrors: true, + }, + }, +} as Meta<typeof Component>; + +type Story = StoryObj<typeof Component>; + +export const ProtectedWhileLoggedOut: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await userEvent.click(canvas.getByText('Access protected route')); + + await expect(cookies().get).toHaveBeenCalledWith('user'); + await expect(redirect).toHaveBeenCalledWith('/'); + + await waitFor(() => expect(getRouter().push).toHaveBeenCalled()); + }, +}; + +export const ProtectedWhileLoggedIn: Story = { + beforeEach() { + cookies().set('user', 'storybookjs'); + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await userEvent.click(canvas.getByText('Access protected route')); + + await expect(cookies().get).toHaveBeenLastCalledWith('user'); + await expect(revalidatePath).toHaveBeenLastCalledWith('/'); + await expect(redirect).toHaveBeenLastCalledWith('/protected'); + + await waitFor(() => expect(getRouter().push).toHaveBeenCalled()); + }, +}; + +export const Logout: Story = { + beforeEach() { + cookies().set('user', 'storybookjs'); + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.click(canvas.getByText('Logout')); + await expect(cookies().delete).toHaveBeenCalled(); + await expect(revalidatePath).toHaveBeenCalledWith('/'); + await expect(redirect).toHaveBeenCalledWith('/'); + + await waitFor(() => expect(getRouter().push).toHaveBeenCalled()); + }, +}; + +export const Login: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await userEvent.click(canvas.getByText('Login')); + + await expect(cookies().set).toHaveBeenCalledWith('user', 'storybookjs'); + await expect(revalidatePath).toHaveBeenCalledWith('/'); + await expect(redirect).toHaveBeenCalledWith('/'); + + await waitFor(() => expect(getRouter().push).toHaveBeenCalled()); + }, +}; diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/server-actions.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/server-actions.tsx new file mode 100644 index 000000000000..6244f78d2472 --- /dev/null +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/server-actions.tsx @@ -0,0 +1,28 @@ +'use server'; + +import { revalidatePath } from 'next/cache'; +import { cookies } from 'next/headers'; +import { redirect } from 'next/navigation'; + +export async function accessRoute() { + const user = (await cookies()).get('user'); + + if (!user) { + redirect('/'); + } + + revalidatePath('/'); + redirect(`/protected`); +} + +export async function logout() { + (await cookies()).delete('user'); + revalidatePath('/'); + redirect('/'); +} + +export async function login() { + (await cookies()).set('user', 'storybookjs'); + revalidatePath('/'); + redirect('/'); +} diff --git a/code/frameworks/nextjs/template/typings.d.ts b/code/frameworks/nextjs/template/typings.d.ts new file mode 100644 index 000000000000..b8b55169fef8 --- /dev/null +++ b/code/frameworks/nextjs/template/typings.d.ts @@ -0,0 +1,14 @@ +declare module '*.svg' { + const content: string; + export default content; +} + +declare module '*.avif' { + const content: string; + export default content; +} + +declare module '*.png' { + const content: string; + export default content; +} diff --git a/code/frameworks/preact-vite/package.json b/code/frameworks/preact-vite/package.json index 59b22b6fdb4f..2a8bcf542371 100644 --- a/code/frameworks/preact-vite/package.json +++ b/code/frameworks/preact-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-vite", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Preact and Vite: Develop Preact components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/preact-webpack5/package.json b/code/frameworks/preact-webpack5/package.json index 9876abb7e945..3bb196d1dfbf 100644 --- a/code/frameworks/preact-webpack5/package.json +++ b/code/frameworks/preact-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-webpack5", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/frameworks/react-native-web-vite/README.md b/code/frameworks/react-native-web-vite/README.md new file mode 100644 index 000000000000..5bdae8f819c0 --- /dev/null +++ b/code/frameworks/react-native-web-vite/README.md @@ -0,0 +1,3 @@ +# Storybook for React Native Web & Vite + +See [documentation](https://storybook.js.org/docs/get-started/frameworks/react-native-web-vite?renderer=react-native-web) for installation instructions, usage examples, APIs, and more. diff --git a/code/frameworks/react-native-web-vite/package.json b/code/frameworks/react-native-web-vite/package.json new file mode 100644 index 000000000000..01c75647ee4b --- /dev/null +++ b/code/frameworks/react-native-web-vite/package.json @@ -0,0 +1,89 @@ +{ + "name": "@storybook/react-native-web-vite", + "version": "8.5.0-alpha.10", + "description": "Develop react-native components an isolated web environment with hot reloading.", + "keywords": [ + "storybook" + ], + "homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/react-native-web-vite", + "bugs": { + "url": "https://github.com/storybookjs/storybook/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/storybookjs/storybook.git", + "directory": "code/frameworks/react-native-web-vite" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "license": "MIT", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "node": "./dist/index.js", + "import": "./dist/index.mjs", + "require": "./dist/index.js" + }, + "./preset": { + "types": "./dist/preset.d.ts", + "require": "./dist/preset.js" + }, + "./vite-plugin": { + "types": "./dist/vite-plugin.d.ts", + "import": "./dist/vite-plugin.mjs", + "require": "./dist/vite-plugin.js" + }, + "./package.json": "./package.json" + }, + "main": "dist/index.js", + "module": "dist/index.mjs", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "template/cli/**/*", + "README.md", + "*.js", + "*.d.ts", + "!src/**/*" + ], + "scripts": { + "check": "jiti ../../../scripts/prepare/check.ts", + "prep": "jiti ../../../scripts/prepare/bundle.ts" + }, + "dependencies": { + "@joshwooding/vite-plugin-react-docgen-typescript": "0.3.0", + "@storybook/builder-vite": "workspace:*", + "@storybook/react": "workspace:*", + "@storybook/react-vite": "workspace:*", + "@vitejs/plugin-react": "^4.3.2" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "typescript": "^5.3.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-native": ">=0.74.5", + "react-native-web": "^0.19.12", + "storybook": "workspace:^", + "vite": "^5.0.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "publishConfig": { + "access": "public" + }, + "bundler": { + "entries": [ + "./src/index.ts", + "./src/preset.ts", + "./src/vite-plugin.ts" + ], + "platform": "node" + }, + "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae16" +} diff --git a/code/frameworks/react-native-web-vite/preset.js b/code/frameworks/react-native-web-vite/preset.js new file mode 100644 index 000000000000..a83f95279e7f --- /dev/null +++ b/code/frameworks/react-native-web-vite/preset.js @@ -0,0 +1 @@ +module.exports = require('./dist/preset'); diff --git a/code/frameworks/react-native-web-vite/project.json b/code/frameworks/react-native-web-vite/project.json new file mode 100644 index 000000000000..219e9c00077d --- /dev/null +++ b/code/frameworks/react-native-web-vite/project.json @@ -0,0 +1,8 @@ +{ + "name": "react-native-web-vite", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "targets": { + "build": {} + } +} diff --git a/code/frameworks/react-native-web-vite/src/index.ts b/code/frameworks/react-native-web-vite/src/index.ts new file mode 100644 index 000000000000..1855ad61a70b --- /dev/null +++ b/code/frameworks/react-native-web-vite/src/index.ts @@ -0,0 +1 @@ +export type { FrameworkOptions, StorybookConfig } from './types'; diff --git a/code/frameworks/react-native-web-vite/src/preset.ts b/code/frameworks/react-native-web-vite/src/preset.ts new file mode 100644 index 000000000000..852d69af2ce3 --- /dev/null +++ b/code/frameworks/react-native-web-vite/src/preset.ts @@ -0,0 +1,88 @@ +// @ts-expect-error FIXME +import { viteFinal as reactViteFinal } from '@storybook/react-vite/preset'; + +import react from '@vitejs/plugin-react'; +import type { PluginOption } from 'vite'; + +import type { FrameworkOptions, StorybookConfig } from './types'; + +export function reactNativeWeb(): PluginOption { + return { + name: 'vite:react-native-web', + config(_userConfig, env) { + return { + define: { + // reanimated support + 'global.__x': {}, + _frameTimestamp: undefined, + _WORKLET: false, + __DEV__: `${env.mode === 'development'}`, + 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || env.mode), + }, + optimizeDeps: { + include: [], + esbuildOptions: { + jsx: 'transform', + resolveExtensions: [ + '.web.js', + '.web.ts', + '.web.tsx', + '.js', + '.jsx', + '.json', + '.ts', + '.tsx', + '.mjs', + ], + loader: { + '.js': 'jsx', + }, + }, + }, + resolve: { + extensions: [ + '.web.js', + '.web.ts', + '.web.tsx', + '.js', + '.jsx', + '.json', + '.ts', + '.tsx', + '.mjs', + ], + alias: { + 'react-native': 'react-native-web', + }, + }, + }; + }, + }; +} + +export const viteFinal: StorybookConfig['viteFinal'] = async (config, options) => { + const { pluginReactOptions = {} } = + await options.presets.apply<FrameworkOptions>('frameworkOptions'); + + const reactConfig = await reactViteFinal(config, options); + const { plugins = [] } = reactConfig; + + plugins.unshift( + react({ + babel: { + babelrc: false, + configFile: false, + }, + jsxRuntime: 'automatic', + ...pluginReactOptions, + }) + ); + plugins.push(reactNativeWeb()); + + return reactConfig; +}; + +export const core = { + builder: '@storybook/builder-vite', + renderer: '@storybook/react', +}; diff --git a/code/frameworks/react-native-web-vite/src/types.ts b/code/frameworks/react-native-web-vite/src/types.ts new file mode 100644 index 000000000000..c82c79771a1b --- /dev/null +++ b/code/frameworks/react-native-web-vite/src/types.ts @@ -0,0 +1,24 @@ +import type { CompatibleString } from 'storybook/internal/types'; + +import type { + FrameworkOptions as FrameworkOptionsBase, + StorybookConfig as StorybookConfigBase, +} from '@storybook/react-vite'; + +import type { BabelOptions, Options as ReactOptions } from '@vitejs/plugin-react'; + +export type FrameworkOptions = FrameworkOptionsBase & { + pluginReactOptions?: Omit<ReactOptions, 'babel'> & { babel?: BabelOptions }; +}; + +type FrameworkName = CompatibleString<'@storybook/react-native-web-vite'>; + +/** The interface for Storybook configuration in `main.ts` files. */ +export type StorybookConfig = Omit<StorybookConfigBase, 'framework'> & { + framework: + | FrameworkName + | { + name: FrameworkName; + options: FrameworkOptions; + }; +}; diff --git a/code/frameworks/react-native-web-vite/src/vite-plugin.ts b/code/frameworks/react-native-web-vite/src/vite-plugin.ts new file mode 100644 index 000000000000..9b162509fefb --- /dev/null +++ b/code/frameworks/react-native-web-vite/src/vite-plugin.ts @@ -0,0 +1,16 @@ +import react from '@vitejs/plugin-react'; + +import { reactNativeWeb } from './preset'; + +export const storybookReactNativeWeb = () => { + return [ + react({ + babel: { + babelrc: false, + configFile: false, + }, + jsxRuntime: 'automatic', + }), + reactNativeWeb(), + ]; +}; diff --git a/code/frameworks/react-native-web-vite/template/cli/.eslintrc.json b/code/frameworks/react-native-web-vite/template/cli/.eslintrc.json new file mode 100644 index 000000000000..3715384e9511 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/.eslintrc.json @@ -0,0 +1,7 @@ +{ + "rules": { + "import/extensions": "off", + "react/no-unknown-property": "off", + "react/react-in-jsx-scope": "off" + } +} diff --git a/code/frameworks/react-native-web-vite/template/cli/js/Button.jsx b/code/frameworks/react-native-web-vite/template/cli/js/Button.jsx new file mode 100644 index 000000000000..4d87b6e2c4ea --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/js/Button.jsx @@ -0,0 +1,109 @@ +import PropTypes from 'prop-types'; +import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; + +/** Primary UI component for user interaction */ +export const Button = ({ + primary = false, + size = 'medium', + backgroundColor, + label, + style, + onPress, +}) => { + const modeStyle = primary ? styles.primary : styles.secondary; + const textModeStyle = primary ? styles.primaryText : styles.secondaryText; + + const sizeStyle = styles[size]; + const textSizeStyle = textSizeStyles[size]; + + return ( + <TouchableOpacity accessibilityRole="button" activeOpacity={0.6} onPress={onPress}> + <View + style={[ + styles.button, + modeStyle, + sizeStyle, + style, + !!backgroundColor && { backgroundColor }, + { borderColor: 'black' }, + ]} + > + <Text style={[textModeStyle, textSizeStyle]}>{label}</Text> + </View> + </TouchableOpacity> + ); +}; + +const styles = StyleSheet.create({ + button: { + borderWidth: 0, + borderRadius: 48, + }, + buttonText: { + fontWeight: '700', + lineHeight: 1, + }, + primary: { + backgroundColor: '#1ea7fd', + }, + primaryText: { + color: 'white', + }, + secondary: { + backgroundColor: 'transparent', + borderColor: 'rgba(0, 0, 0, 0.15)', + borderWidth: 1, + }, + secondaryText: { + color: '#333', + }, + small: { + paddingVertical: 10, + paddingHorizontal: 16, + }, + smallText: { + fontSize: 12, + }, + medium: { + paddingVertical: 11, + paddingHorizontal: 20, + }, + mediumText: { + fontSize: 14, + }, + large: { + paddingVertical: 12, + paddingHorizontal: 24, + }, + largeText: { + fontSize: 16, + }, +}); + +const textSizeStyles = { + small: styles.smallText, + medium: styles.mediumText, + large: styles.largeText, +}; + +Button.propTypes = { + /** Is this the principal call to action on the page? */ + primary: PropTypes.bool, + /** What background color to use */ + backgroundColor: PropTypes.string, + /** How large should the button be? */ + size: PropTypes.oneOf(['small', 'medium', 'large']), + /** Button contents */ + label: PropTypes.string.isRequired, + /** Optional click handler */ + onPress: PropTypes.func, + /** Optional extra styles */ + style: PropTypes.object, +}; + +Button.defaultProps = { + backgroundColor: null, + primary: false, + size: 'medium', + onClick: undefined, +}; diff --git a/code/frameworks/react-native-web-vite/template/cli/js/Button.stories.jsx b/code/frameworks/react-native-web-vite/template/cli/js/Button.stories.jsx new file mode 100644 index 000000000000..b7136fd8ae67 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/js/Button.stories.jsx @@ -0,0 +1,50 @@ +import { fn } from '@storybook/test'; + +import { View } from 'react-native'; + +import { Button } from './Button'; + +const meta = { + title: 'Example/Button', + component: Button, + decorators: [ + (Story) => ( + <View style={{ flex: 1, alignItems: 'flex-start' }}> + <Story /> + </View> + ), + ], + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + // Use `fn` to spy on the onPress arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args + args: { onPress: fn() }, +}; + +export default meta; + +export const Primary = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary = { + args: { + label: 'Button', + }, +}; + +export const Large = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/react-native-web-vite/template/cli/js/Header.jsx b/code/frameworks/react-native-web-vite/template/cli/js/Header.jsx new file mode 100644 index 000000000000..ebc34b85ea4f --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/js/Header.jsx @@ -0,0 +1,84 @@ +import PropTypes from 'prop-types'; +import { StyleSheet, Text, View } from 'react-native'; + +import { Button } from './Button'; + +export const Header = ({ user, onLogin, onLogout, onCreateAccount }) => ( + <View> + <View style={styles.wrapper}> + <View style={styles.logoContainer}> + <Text style={styles.h1}>Acme</Text> + </View> + + <View style={styles.buttonContainer}> + {user ? ( + <> + <> + <Text>Welcome, </Text> + <Text style={styles.userName}>{user.name}!</Text> + </> + <Button style={styles.button} size="small" onPress={onLogout} label="Log out" /> + </> + ) : ( + <> + <Button style={styles.button} size="small" onPress={onLogin} label="Log in" /> + <Button + style={styles.button} + primary + size="small" + onPress={onCreateAccount} + label="Sign up" + /> + </> + )} + </View> + </View> + </View> +); + +const styles = StyleSheet.create({ + wrapper: { + borderBottomWidth: 1, + borderBottomColor: 'rgba(0, 0, 0, 0.1)', + paddingVertical: 15, + paddingHorizontal: 20, + flexDirection: 'row', + justifyContent: 'space-between', + }, + h1: { + fontWeight: '900', + fontSize: 20, + marginTop: 6, + marginBottom: 6, + marginLeft: 10, + color: 'black', + alignSelf: 'flex-start', + }, + logoContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + button: { + marginLeft: 10, + }, + buttonContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + userName: { + fontWeight: '700', + }, +}); + +Header.propTypes = { + user: PropTypes.shape({ + name: PropTypes.string.isRequired, + }), + onLogin: PropTypes.func.isRequired, + onLogout: PropTypes.func.isRequired, + onCreateAccount: PropTypes.func.isRequired, +}; + +Header.defaultProps = { + user: null, +}; diff --git a/code/frameworks/react-native-web-vite/template/cli/js/Header.stories.jsx b/code/frameworks/react-native-web-vite/template/cli/js/Header.stories.jsx new file mode 100644 index 000000000000..97da8bee0dea --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/js/Header.stories.jsx @@ -0,0 +1,29 @@ +import { Header } from './Header'; + +const meta = { + title: 'Example/Header', + component: Header, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], +}; + +export default meta; + +export const LoggedIn = { + args: { + user: { + name: 'Jane Doe', + }, + onLogin: () => {}, + onLogout: () => {}, + onCreateAccount: () => {}, + }, +}; + +export const LoggedOut = { + args: { + onLogin: () => {}, + onLogout: () => {}, + onCreateAccount: () => {}, + }, +}; diff --git a/code/frameworks/react-native-web-vite/template/cli/js/Page.jsx b/code/frameworks/react-native-web-vite/template/cli/js/Page.jsx new file mode 100644 index 000000000000..81aa45a0a7b2 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/js/Page.jsx @@ -0,0 +1,162 @@ +import { useState } from 'react'; + +import { Linking, StyleSheet, Text, View } from 'react-native'; + +import { Header } from './Header'; + +export const Page = () => { + const [user, setUser] = useState(); + + return ( + <View> + <Header + user={user} + onLogin={() => setUser({ name: 'Jane Doe' })} + onLogout={() => setUser(undefined)} + onCreateAccount={() => setUser({ name: 'Jane Doe' })} + /> + + <View style={styles.section}> + <Text role="heading" style={styles.h2}> + Pages in Storybook + </Text> + + <Text style={styles.p}> + We recommend building UIs with a{' '} + <Text + style={[styles.a, { fontWeight: 'bold' }]} + role="link" + onPress={() => { + Linking.openURL('https://componentdriven.org'); + }} + > + <Text>component-driven</Text> + </Text>{' '} + process starting with atomic components and ending with pages. + </Text> + + <Text style={styles.p}> + Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page + data in Storybook: + </Text> + + <View> + <View> + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories + </View> + + <View> + Assemble data in the page component from your services. You can mock these services out + using Storybook. + </View> + </View> + + <Text style={styles.p}> + Get a guided tutorial on component-driven development at{' '} + <Text + style={styles.a} + role="link" + onPress={() => { + Linking.openURL('https://storybook.js.org/tutorials/'); + }} + > + Storybook tutorials + </Text> + . Read more in the{' '} + <Text + style={styles.a} + role="link" + onPress={() => { + Linking.openURL('https://storybook.js.org/docs'); + }} + > + docs + </Text> + . + </Text> + + <View style={styles.tipWrapper}> + <View style={styles.tip}> + <Text style={styles.tipText}>Tip </Text> + </View> + + <Text>Adjust the width of the canvas with the </Text> + + <Text>Viewports addon in the toolbar</Text> + </View> + </View> + </View> + ); +}; + +const styles = StyleSheet.create({ + section: { + fontFamily: "'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif", + fontSize: 14, + lineHeight: 24, + paddingVertical: 48, + paddingHorizontal: 20, + marginHorizontal: 'auto', + maxWidth: 600, + color: '#333', + }, + + h2: { + fontWeight: '900', + fontSize: 32, + lineHeight: 1, + marginBottom: 4, + }, + + p: { + marginVertical: 16, + marginHorizontal: 0, + }, + + a: { + color: '#1ea7fd', + }, + + ul: { + paddingLeft: 30, + marginVertical: 16, + }, + + li: { + marginBottom: 8, + }, + + tip: { + alignSelf: 'flex-start', + borderRadius: 16, + backgroundColor: '#e7fdd8', + paddingVertical: 4, + paddingHorizontal: 12, + marginRight: 10, + marginBottom: 4, + }, + tipText: { + fontSize: 11, + lineHeight: 12, + fontWeight: '700', + color: '#66bf3c', + }, + + tipWrapper: { + fontSize: 13, + lineHeight: 20, + marginTop: 40, + marginBottom: 40, + flexDirection: 'row', + flexWrap: 'wrap', + }, + + tipWrapperSvg: { + height: 12, + width: 12, + marginRight: 4, + marginTop: 3, + }, +}); diff --git a/code/frameworks/react-native-web-vite/template/cli/js/Page.stories.jsx b/code/frameworks/react-native-web-vite/template/cli/js/Page.stories.jsx new file mode 100644 index 000000000000..249647fce862 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/js/Page.stories.jsx @@ -0,0 +1,25 @@ +import { expect, userEvent, within } from '@storybook/test'; + +import { Page } from './Page'; + +const meta = { + title: 'Example/Page', + component: Page, +}; + +export default meta; + +export const LoggedIn = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + // FIXME: await expect(loginButton).not.toBeInTheDocument(); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; + +export const LoggedOut = {}; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Button.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Button.stories.tsx new file mode 100644 index 000000000000..77d371d51182 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Button.stories.tsx @@ -0,0 +1,53 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { fn } from '@storybook/test'; + +import { View } from 'react-native'; + +import { Button } from './Button'; + +const meta: Meta<typeof Button> = { + title: 'Example/Button', + component: Button, + decorators: [ + (Story) => ( + <View style={{ flex: 1, alignItems: 'flex-start' }}> + <Story /> + </View> + ), + ], + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + // Use `fn` to spy on the onPress arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args + args: { onPress: fn() }, +}; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary: Story = { + args: { + label: 'Button', + }, +}; + +export const Large: Story = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small: Story = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Button.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Button.tsx new file mode 100644 index 000000000000..3e389596d4d3 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Button.tsx @@ -0,0 +1,99 @@ +import type { StyleProp, ViewStyle } from 'react-native'; +import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; + +export interface ButtonProps { + /** Is this the principal call to action on the page? */ + primary?: boolean; + /** What background color to use */ + backgroundColor?: string; + /** How large should the button be? */ + size?: 'small' | 'medium' | 'large'; + /** Button contents */ + label: string; + /** Optional click handler */ + onPress?: () => void; +} + +/** Primary UI component for user interaction */ +export const Button = ({ + primary = false, + size = 'medium', + backgroundColor, + label, + onPress, +}: ButtonProps) => { + const modeStyle = primary ? styles.primary : styles.secondary; + const textModeStyle = primary ? styles.primaryText : styles.secondaryText; + + const sizeStyle = styles[size]; + const textSizeStyle = textSizeStyles[size]; + + return ( + <TouchableOpacity accessibilityRole="button" activeOpacity={0.6} onPress={onPress}> + <View + style={[ + styles.button, + modeStyle, + sizeStyle, + style, + !!backgroundColor && { backgroundColor }, + { borderColor: 'black' }, + ]} + > + <Text style={[textModeStyle, textSizeStyle]}>{label}</Text> + </View> + </TouchableOpacity> + ); +}; + +const styles = StyleSheet.create({ + button: { + borderWidth: 0, + borderRadius: 48, + }, + buttonText: { + fontWeight: '700', + lineHeight: 1, + }, + primary: { + backgroundColor: '#1ea7fd', + }, + primaryText: { + color: 'white', + }, + secondary: { + backgroundColor: 'transparent', + borderColor: 'rgba(0, 0, 0, 0.15)', + borderWidth: 1, + }, + secondaryText: { + color: '#333', + }, + small: { + paddingVertical: 10, + paddingHorizontal: 16, + }, + smallText: { + fontSize: 12, + }, + medium: { + paddingVertical: 11, + paddingHorizontal: 20, + }, + mediumText: { + fontSize: 14, + }, + large: { + paddingVertical: 12, + paddingHorizontal: 24, + }, + largeText: { + fontSize: 16, + }, +}); + +const textSizeStyles = { + small: styles.smallText, + medium: styles.mediumText, + large: styles.largeText, +}; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Header.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Header.stories.tsx new file mode 100644 index 000000000000..65b1ecf9a010 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Header.stories.tsx @@ -0,0 +1,33 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { Header } from './Header'; + +const meta: Meta<typeof Header> = { + title: 'Example/Header', + component: Header, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], +}; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const LoggedIn: Story = { + args: { + user: { + name: 'Jane Doe', + }, + onLogin: () => {}, + onLogout: () => {}, + onCreateAccount: () => {}, + }, +}; + +export const LoggedOut: Story = { + args: { + onLogin: () => {}, + onLogout: () => {}, + onCreateAccount: () => {}, + }, +}; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Header.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Header.tsx new file mode 100644 index 000000000000..0304209832f9 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Header.tsx @@ -0,0 +1,78 @@ +import { StyleSheet, Text, View } from 'react-native'; + +import { Button } from './Button'; + +export type HeaderProps = { + user?: {}; + onLogin: () => void; + onLogout: () => void; + onCreateAccount: () => void; +}; + +export const Header = ({ user, onLogin, onLogout, onCreateAccount }: HeaderProps) => ( + <View> + <View style={styles.wrapper}> + <View style={styles.logoContainer}> + <Text style={styles.h1}>Acme</Text> + </View> + + <View style={styles.buttonContainer}> + {user ? ( + <> + <> + <Text>Welcome, </Text> + <Text style={styles.userName}>{user.name}!</Text> + </> + <Button style={styles.button} size="small" onPress={onLogout} label="Log out" /> + </> + ) : ( + <> + <Button style={styles.button} size="small" onPress={onLogin} label="Log in" /> + + <Button + style={styles.button} + primary + size="small" + onPress={onCreateAccount} + label="Sign up" + /> + </> + )} + </View> + </View> + </View> +); + +const styles = StyleSheet.create({ + wrapper: { + borderBottomWidth: 1, + borderBottomColor: 'rgba(0, 0, 0, 0.1)', + paddingVertical: 15, + paddingHorizontal: 20, + flexDirection: 'row', + justifyContent: 'space-between', + }, + h1: { + fontWeight: '900', + fontSize: 20, + marginTop: 6, + marginBottom: 6, + marginLeft: 10, + color: 'black', + alignSelf: 'flex-start', + }, + logoContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + button: { + marginLeft: 10, + }, + buttonContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + userName: { + fontWeight: '700', + }, +}); diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Page.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Page.stories.tsx new file mode 100644 index 000000000000..96468b31d19b --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Page.stories.tsx @@ -0,0 +1,28 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { expect, userEvent, within } from '@storybook/test'; + +import { Page } from './Page'; + +const meta: Meta<typeof Page> = { + title: 'Example/Page', + component: Page, +}; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const LoggedIn: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + // FIXME: await expect(loginButton).not.toBeInTheDocument(); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; + +export const LoggedOut: Story = {}; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Page.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Page.tsx new file mode 100644 index 000000000000..81aa45a0a7b2 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-3-8/Page.tsx @@ -0,0 +1,162 @@ +import { useState } from 'react'; + +import { Linking, StyleSheet, Text, View } from 'react-native'; + +import { Header } from './Header'; + +export const Page = () => { + const [user, setUser] = useState(); + + return ( + <View> + <Header + user={user} + onLogin={() => setUser({ name: 'Jane Doe' })} + onLogout={() => setUser(undefined)} + onCreateAccount={() => setUser({ name: 'Jane Doe' })} + /> + + <View style={styles.section}> + <Text role="heading" style={styles.h2}> + Pages in Storybook + </Text> + + <Text style={styles.p}> + We recommend building UIs with a{' '} + <Text + style={[styles.a, { fontWeight: 'bold' }]} + role="link" + onPress={() => { + Linking.openURL('https://componentdriven.org'); + }} + > + <Text>component-driven</Text> + </Text>{' '} + process starting with atomic components and ending with pages. + </Text> + + <Text style={styles.p}> + Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page + data in Storybook: + </Text> + + <View> + <View> + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories + </View> + + <View> + Assemble data in the page component from your services. You can mock these services out + using Storybook. + </View> + </View> + + <Text style={styles.p}> + Get a guided tutorial on component-driven development at{' '} + <Text + style={styles.a} + role="link" + onPress={() => { + Linking.openURL('https://storybook.js.org/tutorials/'); + }} + > + Storybook tutorials + </Text> + . Read more in the{' '} + <Text + style={styles.a} + role="link" + onPress={() => { + Linking.openURL('https://storybook.js.org/docs'); + }} + > + docs + </Text> + . + </Text> + + <View style={styles.tipWrapper}> + <View style={styles.tip}> + <Text style={styles.tipText}>Tip </Text> + </View> + + <Text>Adjust the width of the canvas with the </Text> + + <Text>Viewports addon in the toolbar</Text> + </View> + </View> + </View> + ); +}; + +const styles = StyleSheet.create({ + section: { + fontFamily: "'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif", + fontSize: 14, + lineHeight: 24, + paddingVertical: 48, + paddingHorizontal: 20, + marginHorizontal: 'auto', + maxWidth: 600, + color: '#333', + }, + + h2: { + fontWeight: '900', + fontSize: 32, + lineHeight: 1, + marginBottom: 4, + }, + + p: { + marginVertical: 16, + marginHorizontal: 0, + }, + + a: { + color: '#1ea7fd', + }, + + ul: { + paddingLeft: 30, + marginVertical: 16, + }, + + li: { + marginBottom: 8, + }, + + tip: { + alignSelf: 'flex-start', + borderRadius: 16, + backgroundColor: '#e7fdd8', + paddingVertical: 4, + paddingHorizontal: 12, + marginRight: 10, + marginBottom: 4, + }, + tipText: { + fontSize: 11, + lineHeight: 12, + fontWeight: '700', + color: '#66bf3c', + }, + + tipWrapper: { + fontSize: 13, + lineHeight: 20, + marginTop: 40, + marginBottom: 40, + flexDirection: 'row', + flexWrap: 'wrap', + }, + + tipWrapperSvg: { + height: 12, + width: 12, + marginRight: 4, + marginTop: 3, + }, +}); diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.stories.tsx new file mode 100644 index 000000000000..8e655fbfe266 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.stories.tsx @@ -0,0 +1,53 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { fn } from '@storybook/test'; + +import { View } from 'react-native'; + +import { Button } from './Button'; + +const meta = { + title: 'Example/Button', + component: Button, + decorators: [ + (Story) => ( + <View style={{ flex: 1, alignItems: 'flex-start' }}> + <Story /> + </View> + ), + ], + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + // Use `fn` to spy on the onPress arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args + args: { onPress: fn() }, +} satisfies Meta<typeof Button>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary: Story = { + args: { + label: 'Button', + }, +}; + +export const Large: Story = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small: Story = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.tsx new file mode 100644 index 000000000000..ed17e64a3d20 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.tsx @@ -0,0 +1,101 @@ +import type { StyleProp, ViewStyle } from 'react-native'; +import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; + +export interface ButtonProps { + /** Is this the principal call to action on the page? */ + primary?: boolean; + /** What background color to use */ + backgroundColor?: string; + /** How large should the button be? */ + size?: 'small' | 'medium' | 'large'; + /** Button contents */ + label: string; + /** Optional click handler */ + onPress?: () => void; + style?: StyleProp<ViewStyle>; +} + +/** Primary UI component for user interaction */ +export const Button = ({ + primary = false, + size = 'medium', + backgroundColor, + label, + style, + onPress, +}: ButtonProps) => { + const modeStyle = primary ? styles.primary : styles.secondary; + const textModeStyle = primary ? styles.primaryText : styles.secondaryText; + + const sizeStyle = styles[size]; + const textSizeStyle = textSizeStyles[size]; + + return ( + <TouchableOpacity accessibilityRole="button" activeOpacity={0.6} onPress={onPress}> + <View + style={[ + styles.button, + modeStyle, + sizeStyle, + style, + !!backgroundColor && { backgroundColor }, + { borderColor: 'black' }, + ]} + > + <Text style={[textModeStyle, textSizeStyle]}>{label}</Text> + </View> + </TouchableOpacity> + ); +}; + +const styles = StyleSheet.create({ + button: { + borderWidth: 0, + borderRadius: 48, + }, + buttonText: { + fontWeight: '700', + lineHeight: 1, + }, + primary: { + backgroundColor: '#1ea7fd', + }, + primaryText: { + color: 'white', + }, + secondary: { + backgroundColor: 'transparent', + borderColor: 'rgba(0, 0, 0, 0.15)', + borderWidth: 1, + }, + secondaryText: { + color: '#333', + }, + small: { + paddingVertical: 10, + paddingHorizontal: 16, + }, + smallText: { + fontSize: 12, + }, + medium: { + paddingVertical: 11, + paddingHorizontal: 20, + }, + mediumText: { + fontSize: 14, + }, + large: { + paddingVertical: 12, + paddingHorizontal: 24, + }, + largeText: { + fontSize: 16, + }, +}); + +const textSizeStyles = { + small: styles.smallText, + medium: styles.mediumText, + large: styles.largeText, +}; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.stories.tsx new file mode 100644 index 000000000000..029f040b0396 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.stories.tsx @@ -0,0 +1,33 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { Header } from './Header'; + +const meta = { + title: 'Example/Header', + component: Header, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], +} satisfies Meta<typeof Header>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const LoggedIn: Story = { + args: { + user: { + name: 'Jane Doe', + }, + onLogin: () => {}, + onLogout: () => {}, + onCreateAccount: () => {}, + }, +}; + +export const LoggedOut: Story = { + args: { + onLogin: () => {}, + onLogout: () => {}, + onCreateAccount: () => {}, + }, +}; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.tsx new file mode 100644 index 000000000000..4f8fcf7b8c49 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.tsx @@ -0,0 +1,76 @@ +import { StyleSheet, Text, View } from 'react-native'; + +import { Button } from './Button'; + +export type HeaderProps = { + user?: {}; + onLogin: () => void; + onLogout: () => void; + onCreateAccount: () => void; +}; + +export const Header = ({ user, onLogin, onLogout, onCreateAccount }: HeaderProps) => ( + <View> + <View style={styles.wrapper}> + <View style={styles.logoContainer}> + <Text style={styles.h1}>Acme</Text> + </View> + <View style={styles.buttonContainer}> + {user ? ( + <> + <> + <Text>Welcome, </Text> + <Text style={styles.userName}>{user.name}!</Text> + </> + <Button style={styles.button} size="small" onPress={onLogout} label="Log out" /> + </> + ) : ( + <> + <Button style={styles.button} size="small" onPress={onLogin} label="Log in" /> + <Button + style={styles.button} + primary + size="small" + onPress={onCreateAccount} + label="Sign up" + /> + </> + )} + </View> + </View> + </View> +); + +const styles = StyleSheet.create({ + wrapper: { + borderBottomWidth: 1, + borderBottomColor: 'rgba(0, 0, 0, 0.1)', + paddingVertical: 15, + paddingHorizontal: 20, + flexDirection: 'row', + justifyContent: 'space-between', + }, + h1: { + fontWeight: '900', + fontSize: 20, + marginTop: 6, + marginBottom: 6, + marginLeft: 10, + color: 'black', + alignSelf: 'flex-start', + }, + logoContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + button: { + marginLeft: 10, + }, + buttonContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + userName: { + fontWeight: '700', + }, +}); diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.stories.tsx new file mode 100644 index 000000000000..5a5db7ff2685 --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.stories.tsx @@ -0,0 +1,24 @@ +import type { Meta } from '@storybook/react'; +import { expect, userEvent, within } from '@storybook/test'; + +import { Page } from './Page'; + +export default { + title: 'Example/Page', + component: Page, +} as Meta<typeof Page>; + +export const LoggedIn = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + // FIXME: await expect(loginButton).not.toBeInTheDocument(); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; + +export const LoggedOut = {}; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.tsx new file mode 100644 index 000000000000..44ca0103ecaf --- /dev/null +++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.tsx @@ -0,0 +1,154 @@ +import { useState } from 'react'; + +import { Linking, StyleSheet, Text, View } from 'react-native'; + +import { Header } from './Header'; + +export const Page = () => { + const [user, setUser] = useState(); + + return ( + <View> + <Header + user={user} + onLogin={() => setUser({ name: 'Jane Doe' })} + onLogout={() => setUser(undefined)} + onCreateAccount={() => setUser({ name: 'Jane Doe' })} + /> + + <View style={styles.section}> + <Text role="heading" style={styles.h2}> + Pages in Storybook + </Text> + <Text style={styles.p}> + We recommend building UIs with a{' '} + <Text + style={[styles.a, { fontWeight: 'bold' }]} + role="link" + onPress={() => { + Linking.openURL('https://componentdriven.org'); + }} + > + <Text>component-driven</Text> + </Text>{' '} + process starting with atomic components and ending with pages. + </Text> + <Text style={styles.p}> + Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page + data in Storybook: + </Text> + <View> + <View> + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories + </View> + <View> + Assemble data in the page component from your services. You can mock these services out + using Storybook. + </View> + </View> + <Text style={styles.p}> + Get a guided tutorial on component-driven development at{' '} + <Text + style={styles.a} + role="link" + onPress={() => { + Linking.openURL('https://storybook.js.org/tutorials/'); + }} + > + Storybook tutorials + </Text> + . Read more in the{' '} + <Text + style={styles.a} + role="link" + onPress={() => { + Linking.openURL('https://storybook.js.org/docs'); + }} + > + docs + </Text> + . + </Text> + <View style={styles.tipWrapper}> + <View style={styles.tip}> + <Text style={styles.tipText}>Tip </Text> + </View> + <Text>Adjust the width of the canvas with the </Text> + <Text>Viewports addon in the toolbar</Text> + </View> + </View> + </View> + ); +}; + +const styles = StyleSheet.create({ + section: { + fontFamily: "'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif", + fontSize: 14, + lineHeight: 24, + paddingVertical: 48, + paddingHorizontal: 20, + marginHorizontal: 'auto', + maxWidth: 600, + color: '#333', + }, + + h2: { + fontWeight: '900', + fontSize: 32, + lineHeight: 1, + marginBottom: 4, + }, + + p: { + marginVertical: 16, + marginHorizontal: 0, + }, + + a: { + color: '#1ea7fd', + }, + + ul: { + paddingLeft: 30, + marginVertical: 16, + }, + + li: { + marginBottom: 8, + }, + + tip: { + alignSelf: 'flex-start', + borderRadius: 16, + backgroundColor: '#e7fdd8', + paddingVertical: 4, + paddingHorizontal: 12, + marginRight: 10, + marginBottom: 4, + }, + tipText: { + fontSize: 11, + lineHeight: 12, + fontWeight: '700', + color: '#66bf3c', + }, + + tipWrapper: { + fontSize: 13, + lineHeight: 20, + marginTop: 40, + marginBottom: 40, + flexDirection: 'row', + flexWrap: 'wrap', + }, + + tipWrapperSvg: { + height: 12, + width: 12, + marginRight: 4, + marginTop: 3, + }, +}); diff --git a/code/frameworks/react-native-web-vite/tsconfig.json b/code/frameworks/react-native-web-vite/tsconfig.json new file mode 100644 index 000000000000..c749496d9a6e --- /dev/null +++ b/code/frameworks/react-native-web-vite/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "storybook/internal/*": ["../../lib/cli/core/*"] + }, + "rootDir": "./src" + }, + "extends": "../../tsconfig.json", + "include": ["src/**/*"] +} diff --git a/code/frameworks/react-native-web-vite/vitest.config.ts b/code/frameworks/react-native-web-vite/vitest.config.ts new file mode 100644 index 000000000000..7420176b2e46 --- /dev/null +++ b/code/frameworks/react-native-web-vite/vitest.config.ts @@ -0,0 +1,10 @@ +import { defineConfig, mergeConfig } from 'vitest/config'; + +import { vitestCommonConfig } from '../../vitest.workspace'; + +export default mergeConfig( + vitestCommonConfig, + defineConfig({ + // Add custom config here + }) +); diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index 878d130556a2..5aff664d1d31 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-vite", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for React and Vite: Develop React components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/react-webpack5/package.json b/code/frameworks/react-webpack5/package.json index f9b70c7df783..56dc0cb272b6 100644 --- a/code/frameworks/react-webpack5/package.json +++ b/code/frameworks/react-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-webpack5", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/server-webpack5/package.json b/code/frameworks/server-webpack5/package.json index d3d2cb9226c6..164d7029482a 100644 --- a/code/frameworks/server-webpack5/package.json +++ b/code/frameworks/server-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server-webpack5", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index cc643fbf33d0..35b31e47e780 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-vite", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Svelte and Vite: Develop Svelte components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index 36d4ef03d897..1bf8948004d0 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-webpack5", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json index 05dd93345799..81e1390582d2 100644 --- a/code/frameworks/sveltekit/package.json +++ b/code/frameworks/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/sveltekit", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for SvelteKit", "keywords": [ "storybook", diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json index a5d3f892cb11..8f676ca4d931 100644 --- a/code/frameworks/vue3-vite/package.json +++ b/code/frameworks/vue3-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-vite", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Vue3 and Vite: Develop Vue3 components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/vue3-webpack5/package.json b/code/frameworks/vue3-webpack5/package.json index 82a84c308550..0f9a6f41b350 100644 --- a/code/frameworks/vue3-webpack5/package.json +++ b/code/frameworks/vue3-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-webpack5", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-vite/package.json b/code/frameworks/web-components-vite/package.json index 251e034cf036..5c82c5dc6508 100644 --- a/code/frameworks/web-components-vite/package.json +++ b/code/frameworks/web-components-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-vite", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for web-components and Vite: Develop Web Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-webpack5/package.json b/code/frameworks/web-components-webpack5/package.json index c269e1081a2a..20fc2a014327 100644 --- a/code/frameworks/web-components-webpack5/package.json +++ b/code/frameworks/web-components-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-webpack5", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.", "keywords": [ "lit", diff --git a/code/lib/blocks/package.json b/code/lib/blocks/package.json index d7206af15ab5..a126b4bd9980 100644 --- a/code/lib/blocks/package.json +++ b/code/lib/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/blocks", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook Doc Blocks", "keywords": [ "storybook" diff --git a/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx b/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx index ab867ff74b5c..8d44e5f7cb43 100644 --- a/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx +++ b/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx @@ -90,10 +90,14 @@ export const SectionsAndSubsections = { export const SubsectionsOnly = { args: { rows: { - a: { ...stringType, table: { ...stringType.table, ...componentSubsection } }, + a: { ...stringType, key: 'stringA', table: { ...stringType.table, ...componentSubsection } }, b: { ...numberType, table: { ...stringType.table, ...componentSubsection } }, - c: { ...stringType, table: { ...stringType.table, ...componentSubsection } }, - d: { ...stringType, table: { ...stringType.table, ...htmlElementSubsection } }, + c: { ...stringType, key: 'stringB', table: { ...stringType.table, ...componentSubsection } }, + d: { + ...stringType, + key: 'stringC', + table: { ...stringType.table, ...htmlElementSubsection }, + }, }, }, }; @@ -106,14 +110,14 @@ export const AllControls = { color: ArgRow.Color.args.row, date: ArgRow.Date.args.row, string: ArgRow.String.args.row, - number: ArgRow.Number.args.row, - range: ArgRow.Number.args.row, - radio: ArgRow.Radio.args.row, - inlineRadio: ArgRow.InlineRadio.args.row, - check: ArgRow.Check.args.row, - inlineCheck: ArgRow.InlineCheck.args.row, - select: ArgRow.Select.args.row, - multiSelect: ArgRow.MultiSelect.args.row, + number: { ...ArgRow.Number.args.row, key: 'number' }, + range: { ...ArgRow.Number.args.row, key: 'range' }, + radio: { ...ArgRow.Radio.args.row, key: 'radio' }, + inlineRadio: { ...ArgRow.InlineRadio.args.row, key: 'inlineRadio' }, + check: { ...ArgRow.Check.args.row, key: 'check' }, + inlineCheck: { ...ArgRow.InlineCheck.args.row, key: 'inlineCheck' }, + select: { ...ArgRow.Select.args.row, key: 'select' }, + multiSelect: { ...ArgRow.MultiSelect.args.row, key: 'multiSelect' }, object: ArgRow.ObjectOf.args.row, func: ArgRow.Func.args.row, }, diff --git a/code/lib/blocks/src/examples/Button.stories.tsx b/code/lib/blocks/src/examples/Button.stories.tsx index 31f28a568c51..c22d141f541c 100644 --- a/code/lib/blocks/src/examples/Button.stories.tsx +++ b/code/lib/blocks/src/examples/Button.stories.tsx @@ -137,4 +137,5 @@ export const ErrorStory: Story = { parameters: { chromatic: { disable: true }, }, + tags: ['!test', '!vitest'], }; diff --git a/code/lib/cli-sb/package.json b/code/lib/cli-sb/package.json index 9d8bee7cecd6..664d8f3ad4a8 100644 --- a/code/lib/cli-sb/package.json +++ b/code/lib/cli-sb/package.json @@ -1,6 +1,6 @@ { "name": "sb", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli-storybook/package.json b/code/lib/cli-storybook/package.json index 0e55f1743e5c..cbd6c919760f 100644 --- a/code/lib/cli-storybook/package.json +++ b/code/lib/cli-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/cli", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli-storybook/src/bin/index.ts b/code/lib/cli-storybook/src/bin/index.ts index 2eaa769e4186..165b3f9dd999 100644 --- a/code/lib/cli-storybook/src/bin/index.ts +++ b/code/lib/cli-storybook/src/bin/index.ts @@ -40,6 +40,27 @@ const command = (name: string) => .option('--debug', 'Get more logs in debug mode', false) .option('--enable-crash-reports', 'Enable sending crash reports to telemetry data'); +command('init') + .description('Initialize Storybook into your project') + .option('-f --force', 'Force add Storybook') + .option('-s --skip-install', 'Skip installing deps') + .option('--package-manager <npm|pnpm|yarn1|yarn2>', 'Force package manager for installing deps') + .option('--use-pnp', 'Enable PnP mode for Yarn 2+') + .option('-p --parser <babel | babylon | flow | ts | tsx>', 'jscodeshift parser') + .option('-t --type <type>', 'Add Storybook for a specific project type') + .option('-y --yes', 'Answer yes to all prompts') + .option('-b --builder <webpack5 | vite>', 'Builder library') + .option('-l --linkable', 'Prepare installation for link (contributor helper)') + .option( + '--dev', + 'Launch the development server after completing initialization. Enabled by default (default: true)', + process.env.CI !== 'true' && process.env.IN_STORYBOOK_SANDBOX !== 'true' + ) + .option( + '--no-dev', + 'Complete the initialization of Storybook without launching the Storybook development server' + ); + command('add <addon>') .description('Add an addon to your Storybook') .option( diff --git a/code/lib/cli-storybook/src/sandbox-templates.ts b/code/lib/cli-storybook/src/sandbox-templates.ts index b474937769ff..fe89f9decae0 100644 --- a/code/lib/cli-storybook/src/sandbox-templates.ts +++ b/code/lib/cli-storybook/src/sandbox-templates.ts @@ -156,10 +156,10 @@ const baseTemplates = { }, skipTasks: ['e2e-tests-dev', 'bench', 'vitest-integration'], }, - 'nextjs/default-js': { - name: 'Next.js Latest (Webpack | JavaScript)', + 'nextjs/14-ts': { + name: 'Next.js v14.2 (Webpack | TypeScript)', script: - 'npx create-next-app@^14 {{beforeDir}} --eslint --tailwind --app --import-alias="@/*" --src-dir', + 'yarn create next-app {{beforeDir}} -e https://github.com/vercel/next.js/tree/v14.2.17/examples/hello-world && cd {{beforeDir}} && npm pkg set "dependencies.next"="^14.2.17" && yarn && git add . && git commit --amend --no-edit && cd ..', expected: { framework: '@storybook/nextjs', renderer: '@storybook/react', @@ -172,11 +172,12 @@ const baseTemplates = { extraDependencies: ['server-only', 'prop-types'], }, skipTasks: ['e2e-tests-dev', 'bench', 'vitest-integration'], + inDevelopment: true, }, 'nextjs/default-ts': { name: 'Next.js Latest (Webpack | TypeScript)', script: - 'npx create-next-app@^14 {{beforeDir}} --typescript --eslint --tailwind --app --import-alias="@/*" --src-dir', + 'npx create-next-app {{beforeDir}} --eslint --tailwind --app --import-alias="@/*" --src-dir', expected: { framework: '@storybook/nextjs', renderer: '@storybook/react', @@ -193,7 +194,7 @@ const baseTemplates = { 'nextjs/prerelease': { name: 'Next.js Prerelease (Webpack | TypeScript)', script: - 'npx create-next-app@canary {{beforeDir}} --typescript --eslint --tailwind --app --import-alias="@/*" --src-dir', + 'npx create-next-app@canary {{beforeDir}} --eslint --tailwind --app --import-alias="@/*" --src-dir', expected: { framework: '@storybook/nextjs', renderer: '@storybook/react', @@ -207,10 +208,34 @@ const baseTemplates = { }, skipTasks: ['e2e-tests-dev', 'bench', 'vitest-integration'], }, + 'experimental-nextjs-vite/14-ts': { + name: 'Next.js Latest (Vite | TypeScript)', + script: + 'npx create-next-app@^14 {{beforeDir}} --eslint --tailwind --app --import-alias="@/*" --src-dir', + expected: { + framework: '@storybook/experimental-nextjs-vite', + renderer: '@storybook/react', + builder: '@storybook/builder-vite', + }, + modifications: { + mainConfig: { + framework: '@storybook/experimental-nextjs-vite', + features: { experimentalRSC: true }, + }, + extraDependencies: [ + 'server-only', + '@storybook/experimental-nextjs-vite', + 'vite', + 'prop-types', + ], + }, + inDevelopment: true, + skipTasks: ['e2e-tests-dev', 'bench'], + }, 'experimental-nextjs-vite/default-ts': { name: 'Next.js Latest (Vite | TypeScript)', script: - 'npx create-next-app@^14 {{beforeDir}} --typescript --eslint --tailwind --app --import-alias="@/*" --src-dir', + 'npx create-next-app {{beforeDir}} --eslint --tailwind --app --import-alias="@/*" --src-dir', expected: { framework: '@storybook/experimental-nextjs-vite', renderer: '@storybook/react', @@ -592,6 +617,43 @@ const baseTemplates = { builder: '@storybook/builder-webpack5', }, }, + 'react-native-web-vite/expo-ts': { + // NOTE: create-expo-app installs React 18.2.0. But yarn portal + // expects 18.3.1 (dunno why). Therefore to run this in dev you + // must either: + // - edit the sandbox package.json to depend on react 18.3.1, OR + // - build/run the sandbox in --no-link mode, which is fine + // + // Users & CI won't see this limitation because they are not using + // yarn portals. + name: 'React Native Expo Latest (Vite | TypeScript)', + script: 'npx create-expo-app -y {{beforeDir}}', + expected: { + framework: '@storybook/react-native-web-vite', + renderer: '@storybook/react', + builder: '@storybook/builder-vite', + }, + skipTasks: ['e2e-tests-dev', 'bench', 'vitest-integration'], + }, + 'react-native-web-vite/rn-cli-ts': { + // NOTE: create-expo-app installs React 18.2.0. But yarn portal + // expects 18.3.1 (dunno why). Therefore to run this in dev you + // must either: + // - edit the sandbox package.json to depend on react 18.3.1, OR + // - build/run the sandbox in --no-link mode, which is fine + // + // Users & CI won't see this limitation because they are not using + // yarn portals. + name: 'React Native CLI Latest (Vite | TypeScript)', + script: + 'npx @react-native-community/cli@latest init --install-pods=false --directory={{beforeDir}} rnapp', + expected: { + framework: '@storybook/react-native-web-vite', + renderer: '@storybook/react', + builder: '@storybook/builder-vite', + }, + skipTasks: ['e2e-tests-dev', 'bench', 'vitest-integration'], + }, } satisfies Record<string, BaseTemplates>; /** @@ -785,13 +847,14 @@ export const daily: TemplateKey[] = [ 'svelte-kit/prerelease-ts', 'svelte-vite/default-js', 'nextjs/13-ts', - 'nextjs/default-js', 'nextjs/prerelease', 'qwik-vite/default-ts', 'preact-vite/default-js', 'html-vite/default-js', 'internal/react16-webpack', 'internal/react18-webpack-babel', + 'react-native-web-vite/expo-ts', + // 'react-native-web-vite/rn-cli-ts', ]; export const templatesByCadence = { normal, merged, daily }; diff --git a/code/lib/cli-storybook/test/default/cli.test.cjs b/code/lib/cli-storybook/test/default/cli.test.cjs index b569fa4dc5c6..f55fa0ef9a61 100755 --- a/code/lib/cli-storybook/test/default/cli.test.cjs +++ b/code/lib/cli-storybook/test/default/cli.test.cjs @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, expect, it } from 'vitest'; const run = require('../helpers.cjs'); @@ -12,3 +12,92 @@ describe('Default behavior', () => { expect(stdout.toString()).toContain('Did you mean upgrade?'); }); }); + +describe('Help command', () => { + it('should prints out "init" command', () => { + const { status, stdout, stderr } = run(['help']); + + expect(status).toBe(0); + expect(stderr.toString()).toBe(''); + expect(stdout.toString()).toContain('init'); + expect(stdout.toString()).toContain('Initialize Storybook into your project'); + }); + + it('should prints out "add" command', () => { + const { status, stdout, stderr } = run(['help']); + + expect(status).toBe(0); + expect(stderr.toString()).toBe(''); + expect(stdout.toString()).toContain('add'); + expect(stdout.toString()).toContain('Add an addon to your Storybook'); + }); + + it('should prints out "remove" command', () => { + const { status, stdout, stderr } = run(['help']); + + expect(status).toBe(0); + expect(stderr.toString()).toBe(''); + expect(stdout.toString()).toContain('remove'); + expect(stdout.toString()).toContain('Remove an addon from your Storybook'); + }); + + it('should prints out "upgrade" command', () => { + const { status, stdout, stderr } = run(['help']); + + expect(status).toBe(0); + expect(stderr.toString()).toBe(''); + expect(stdout.toString()).toContain('upgrade'); + expect(stdout.toString()).toContain('Upgrade your Storybook packages to'); + }); + + it('should prints out "migrate" command', () => { + const { status, stdout, stderr } = run(['help']); + + expect(status).toBe(0); + expect(stderr.toString()).toBe(''); + expect(stdout.toString()).toContain('migrate'); + expect(stdout.toString()).toContain('Run a Storybook codemod migration on your source files'); + }); + + it('should prints out "sandbox" command', () => { + const { status, stdout, stderr } = run(['help']); + + expect(status).toBe(0); + expect(stderr.toString()).toBe(''); + expect(stdout.toString()).toContain('sandbox'); + expect(stdout.toString()).toContain('Create a sandbox from a set of possible templates'); + }); + + it('should prints out "link" command', () => { + const { status, stdout, stderr } = run(['help']); + + expect(status).toBe(0); + expect(stderr.toString()).toBe(''); + expect(stdout.toString()).toContain('link'); + expect(stdout.toString()).toContain( + 'Pull down a repro from a URL (or a local directory), link it, and run storybook' + ); + }); + + it('should prints out "automigrate" command', () => { + const { status, stdout, stderr } = run(['help']); + + expect(status).toBe(0); + expect(stderr.toString()).toBe(''); + expect(stdout.toString()).toContain('automigrate'); + expect(stdout.toString()).toContain( + 'Check storybook for incompatibilities or migrations and apply fixes' + ); + }); + + it('should prints out "doctor" command', () => { + const { status, stdout, stderr } = run(['help']); + + expect(status).toBe(0); + expect(stderr.toString()).toBe(''); + expect(stdout.toString()).toContain('doctor'); + expect(stdout.toString()).toContain( + 'Check Storybook for known problems and provide suggestions or fixes' + ); + }); +}); diff --git a/code/lib/cli/package.json b/code/lib/cli/package.json index 77a2a37ca516..77ab3a7984a0 100644 --- a/code/lib/cli/package.json +++ b/code/lib/cli/package.json @@ -1,6 +1,6 @@ { "name": "storybook", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook's CLI - install, dev, build, upgrade, and more", "keywords": [ "cli", diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json index 0ba9b276559b..86b2cc86f04d 100644 --- a/code/lib/codemod/package.json +++ b/code/lib/codemod/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/codemod", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "A collection of codemod scripts written with JSCodeshift", "keywords": [ "storybook" diff --git a/code/lib/core-webpack/package.json b/code/lib/core-webpack/package.json index 77de45a9a7f6..f86bbfd33898 100644 --- a/code/lib/core-webpack/package.json +++ b/code/lib/core-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-webpack", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/lib/create-storybook/package.json b/code/lib/create-storybook/package.json index 1fe15edaa81f..82a80d732f7a 100644 --- a/code/lib/create-storybook/package.json +++ b/code/lib/create-storybook/package.json @@ -1,6 +1,6 @@ { "name": "create-storybook", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Initialize Storybook into your project", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/lib/create-storybook", "bugs": { diff --git a/code/lib/create-storybook/src/generators/REACT_NATIVE_WEB/index.ts b/code/lib/create-storybook/src/generators/REACT_NATIVE_WEB/index.ts new file mode 100644 index 000000000000..f0c1a14076c0 --- /dev/null +++ b/code/lib/create-storybook/src/generators/REACT_NATIVE_WEB/index.ts @@ -0,0 +1,35 @@ +import { readdir, rm } from 'node:fs/promises'; +import { join } from 'node:path'; + +import { SupportedLanguage, cliStoriesTargetPath, detectLanguage } from 'storybook/internal/cli'; + +import { baseGenerator } from '../baseGenerator'; +import type { Generator } from '../types'; + +const generator: Generator = async (packageManager, npmOptions, options) => { + // Add prop-types dependency if not using TypeScript + const language = await detectLanguage(packageManager); + const extraPackages = ['vite', 'react-native-web']; + if (language === SupportedLanguage.JAVASCRIPT) { + extraPackages.push('prop-types'); + } + + await baseGenerator( + packageManager, + npmOptions, + options, + 'react', + { + extraPackages, + extraAddons: [`@storybook/addon-onboarding`], + }, + 'react-native-web-vite' + ); + + // Remove CSS files automatically copeied by baseGenerator + const targetPath = await cliStoriesTargetPath(); + const cssFiles = (await readdir(targetPath)).filter((f) => f.endsWith('.css')); + await Promise.all(cssFiles.map((f) => rm(join(targetPath, f)))); +}; + +export default generator; diff --git a/code/lib/create-storybook/src/generators/baseGenerator.ts b/code/lib/create-storybook/src/generators/baseGenerator.ts index 4ba6db064da3..84daecba1b46 100644 --- a/code/lib/create-storybook/src/generators/baseGenerator.ts +++ b/code/lib/create-storybook/src/generators/baseGenerator.ts @@ -170,7 +170,7 @@ const hasInteractiveStories = (rendererId: SupportedRenderers) => ['react', 'angular', 'preact', 'svelte', 'vue3', 'html', 'solid', 'qwik'].includes(rendererId); const hasFrameworkTemplates = (framework?: SupportedFrameworks) => - framework ? ['angular', 'nextjs'].includes(framework) : false; + framework ? ['angular', 'nextjs', 'react-native-web-vite'].includes(framework) : false; export async function baseGenerator( packageManager: JsPackageManager, @@ -244,12 +244,7 @@ export async function baseGenerator( ...extraAddonsToInstall, ].filter(Boolean); - // TODO: migrate template stories in solid and qwik to use @storybook/test - if (['qwik'].includes(rendererId)) { - addonPackages.push('@storybook/testing-library'); - } else { - addonPackages.push('@storybook/test'); - } + addonPackages.push('@storybook/test'); if (hasInteractiveStories(rendererId)) { addons.push('@storybook/addon-interactions'); diff --git a/code/lib/create-storybook/src/initiate.ts b/code/lib/create-storybook/src/initiate.ts index 868834a1e144..6c1c6559d262 100644 --- a/code/lib/create-storybook/src/initiate.ts +++ b/code/lib/create-storybook/src/initiate.ts @@ -31,6 +31,7 @@ import preactGenerator from './generators/PREACT'; import qwikGenerator from './generators/QWIK'; import reactGenerator from './generators/REACT'; import reactNativeGenerator from './generators/REACT_NATIVE'; +import reactNativeWebGenerator from './generators/REACT_NATIVE_WEB'; import reactScriptsGenerator from './generators/REACT_SCRIPTS'; import serverGenerator from './generators/SERVER'; import solidGenerator from './generators/SOLID'; @@ -84,6 +85,12 @@ const installStorybook = async <Project extends ProjectType>( ); } + case ProjectType.REACT_NATIVE_WEB: { + return reactNativeWebGenerator(packageManager, npmOptions, generatorOptions).then( + commandLog('Adding Storybook support to your "React Native" app') + ); + } + case ProjectType.QWIK: { return qwikGenerator(packageManager, npmOptions, generatorOptions).then( commandLog('Adding Storybook support to your "Qwik" app') diff --git a/code/lib/csf-plugin/package.json b/code/lib/csf-plugin/package.json index 13e3bfcc8551..7f414533f85c 100644 --- a/code/lib/csf-plugin/package.json +++ b/code/lib/csf-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-plugin", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Enrich CSF files via static analysis", "keywords": [ "storybook" diff --git a/code/lib/instrumenter/package.json b/code/lib/instrumenter/package.json index b529f7b13571..f2e34fd6e901 100644 --- a/code/lib/instrumenter/package.json +++ b/code/lib/instrumenter/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/instrumenter", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "", "keywords": [ "storybook" diff --git a/code/lib/react-dom-shim/package.json b/code/lib/react-dom-shim/package.json index bd9c76c456ca..d35a73949c41 100644 --- a/code/lib/react-dom-shim/package.json +++ b/code/lib/react-dom-shim/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-dom-shim", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "", "keywords": [ "storybook" diff --git a/code/lib/source-loader/package.json b/code/lib/source-loader/package.json index 126a0aa63551..317668721177 100644 --- a/code/lib/source-loader/package.json +++ b/code/lib/source-loader/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/source-loader", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Source loader", "keywords": [ "lib", diff --git a/code/lib/test/package.json b/code/lib/test/package.json index 036df428d0bc..410da722d4af 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/test", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "", "keywords": [ "storybook" diff --git a/code/lib/test/template/stories/before-each.stories.ts b/code/lib/test/template/stories/before-each.stories.ts index 79c31874c813..12aad1818afe 100644 --- a/code/lib/test/template/stories/before-each.stories.ts +++ b/code/lib/test/template/stories/before-each.stories.ts @@ -32,7 +32,8 @@ export const BeforeEachOrder = { async play({ canvasElement }: any) { await userEvent.click(getByRole(canvasElement, 'button')); - await expect(mocked(console.log).mock.calls).toEqual([ + const allLogs = mocked(console.log).mock.calls.filter(([message]) => /^\d+ - /.test(message)); + await expect(allLogs).toEqual([ ['1 - [from loaders]'], ['2 - [from meta beforeEach]'], ['3 - [from story beforeEach]'], diff --git a/code/lib/test/template/stories/mount-in-play.stories.ts b/code/lib/test/template/stories/mount-in-play.stories.ts index c7acb7dce688..0c87263ba484 100644 --- a/code/lib/test/template/stories/mount-in-play.stories.ts +++ b/code/lib/test/template/stories/mount-in-play.stories.ts @@ -32,7 +32,8 @@ export const MountInPlay = { await mount(); console.log('6 - [after mount]'); await userEvent.click(getByRole(canvasElement, 'button')); - await expect(mocked(console.log).mock.calls).toEqual([ + const allLogs = mocked(console.log).mock.calls.filter(([message]) => /^\d+ - /.test(message)); + await expect(allLogs).toEqual([ ['1 - [from loaders]'], ['2 - [from meta beforeEach]'], ['3 - [from story beforeEach]'], diff --git a/code/package.json b/code/package.json index 2fc645efc459..49d43900fb56 100644 --- a/code/package.json +++ b/code/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/root", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "private": true, "description": "Storybook root", "homepage": "https://storybook.js.org/", @@ -176,7 +176,7 @@ "@types/serve-static": "^1.13.8", "@typescript-eslint/experimental-utils": "^5.62.0", "@typescript-eslint/parser": "^6.18.1", - "@vitejs/plugin-react": "^3.0.1", + "@vitejs/plugin-react": "^4.3.2", "@vitejs/plugin-vue": "^4.4.0", "@vitest/browser": "^2.1.3", "@vitest/coverage-istanbul": "^2.1.3", diff --git a/code/playwright.config.ts b/code/playwright.config.ts index dee882693c80..5b29fa4cce32 100644 --- a/code/playwright.config.ts +++ b/code/playwright.config.ts @@ -3,6 +3,10 @@ import { defineConfig, devices } from '@playwright/test'; /** Read environment variables from file. https://github.com/motdotla/dotenv */ // require('dotenv').config(); +// Comment this out and fill in the values to run E2E tests locally using the Playwright extension easily +// process.env.STORYBOOK_URL = 'http://localhost:6006'; +// process.env.STORYBOOK_TEMPLATE_NAME = 'react-vite/default-ts'; + /** See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ testDir: './e2e-tests', diff --git a/code/presets/create-react-app/package.json b/code/presets/create-react-app/package.json index 90bb70e95947..740a21a0d914 100644 --- a/code/presets/create-react-app/package.json +++ b/code/presets/create-react-app/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-create-react-app", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Create React App preset", "keywords": [ "storybook" diff --git a/code/presets/html-webpack/package.json b/code/presets/html-webpack/package.json index 764d9449507b..be5717140350 100644 --- a/code/presets/html-webpack/package.json +++ b/code/presets/html-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-html-webpack", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/preact-webpack/package.json b/code/presets/preact-webpack/package.json index f3ebc5f6623b..745c15ea7337 100644 --- a/code/presets/preact-webpack/package.json +++ b/code/presets/preact-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-preact-webpack", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/presets/react-webpack/package.json b/code/presets/react-webpack/package.json index a49e9a4d33e1..f4f4d28d4c30 100644 --- a/code/presets/react-webpack/package.json +++ b/code/presets/react-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-react-webpack", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading", "keywords": [ "storybook" diff --git a/code/presets/server-webpack/package.json b/code/presets/server-webpack/package.json index 8a0ec01169d8..8215d80f54c4 100644 --- a/code/presets/server-webpack/package.json +++ b/code/presets/server-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-server-webpack", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/svelte-webpack/package.json b/code/presets/svelte-webpack/package.json index f29f438661cf..3498da565e46 100644 --- a/code/presets/svelte-webpack/package.json +++ b/code/presets/svelte-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-svelte-webpack", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/vue3-webpack/package.json b/code/presets/vue3-webpack/package.json index 70941cba6d28..5d40cd1af1a5 100644 --- a/code/presets/vue3-webpack/package.json +++ b/code/presets/vue3-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-vue3-webpack", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/renderers/html/package.json b/code/renderers/html/package.json index 3f360e97fd3a..6ed9d780702b 100644 --- a/code/renderers/html/package.json +++ b/code/renderers/html/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook HTML renderer", "keywords": [ "storybook" diff --git a/code/renderers/preact/package.json b/code/renderers/preact/package.json index 935712d26f4f..75a9ccc680d4 100644 --- a/code/renderers/preact/package.json +++ b/code/renderers/preact/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook Preact renderer", "keywords": [ "storybook" diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json index 6d3035da5dec..7d7f72ef57a7 100644 --- a/code/renderers/react/package.json +++ b/code/renderers/react/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook React renderer", "keywords": [ "storybook" diff --git a/code/renderers/server/package.json b/code/renderers/server/package.json index 4881b9b86228..2f37352efad5 100644 --- a/code/renderers/server/package.json +++ b/code/renderers/server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook Server renderer", "keywords": [ "storybook" diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json index 2747727902d4..93c1a5091612 100644 --- a/code/renderers/svelte/package.json +++ b/code/renderers/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook Svelte renderer", "keywords": [ "storybook" diff --git a/code/renderers/vue3/package.json b/code/renderers/vue3/package.json index 2bb6337b1cdf..ac1ceb61e819 100644 --- a/code/renderers/vue3/package.json +++ b/code/renderers/vue3/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook Vue 3 renderer", "keywords": [ "storybook" diff --git a/code/renderers/web-components/package.json b/code/renderers/web-components/package.json index dc2b034dc11a..a5f3d0721e76 100644 --- a/code/renderers/web-components/package.json +++ b/code/renderers/web-components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components", - "version": "8.5.0-alpha.3", + "version": "8.5.0-alpha.10", "description": "Storybook web-components renderer", "keywords": [ "lit", diff --git a/code/yarn.lock b/code/yarn.lock index 272933533d60..107c541a4cdb 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -377,6 +377,17 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0": + version: 7.26.2 + resolution: "@babel/code-frame@npm:7.26.2" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.25.9" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.0.0" + checksum: 10c0/7d79621a6849183c415486af99b1a20b84737e8c11cd55b6544f688c51ce1fd710e6d869c3dd21232023da272a79b91efb3e83b5bc2dc65c1187c5fcd1b72ea8 + languageName: node + linkType: hard + "@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.23.5, @babel/compat-data@npm:^7.24.4, @babel/compat-data@npm:^7.25.2": version: 7.25.2 resolution: "@babel/compat-data@npm:7.25.2" @@ -384,6 +395,13 @@ __metadata: languageName: node linkType: hard +"@babel/compat-data@npm:^7.25.9": + version: 7.26.2 + resolution: "@babel/compat-data@npm:7.26.2" + checksum: 10c0/c9b5f3724828d17f728a778f9d66c19b55c018d0d76de6d731178cca64f182c22b71400a73bf2b65dcc4fcfe52b630088a94d5902911b54206aa90e3ffe07d12 + languageName: node + linkType: hard + "@babel/core@npm:7.23.9": version: 7.23.9 resolution: "@babel/core@npm:7.23.9" @@ -430,7 +448,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.12.0, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.18.9, @babel/core@npm:^7.20.12, @babel/core@npm:^7.23.0, @babel/core@npm:^7.23.2, @babel/core@npm:^7.23.9, @babel/core@npm:^7.24.4, @babel/core@npm:^7.3.4, @babel/core@npm:^7.7.5": +"@babel/core@npm:^7.12.0, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.18.9, @babel/core@npm:^7.23.0, @babel/core@npm:^7.23.2, @babel/core@npm:^7.23.9, @babel/core@npm:^7.24.4, @babel/core@npm:^7.3.4, @babel/core@npm:^7.7.5": version: 7.25.2 resolution: "@babel/core@npm:7.25.2" dependencies: @@ -453,6 +471,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.25.2": + version: 7.26.0 + resolution: "@babel/core@npm:7.26.0" + dependencies: + "@ampproject/remapping": "npm:^2.2.0" + "@babel/code-frame": "npm:^7.26.0" + "@babel/generator": "npm:^7.26.0" + "@babel/helper-compilation-targets": "npm:^7.25.9" + "@babel/helper-module-transforms": "npm:^7.26.0" + "@babel/helpers": "npm:^7.26.0" + "@babel/parser": "npm:^7.26.0" + "@babel/template": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" + "@babel/types": "npm:^7.26.0" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 10c0/91de73a7ff5c4049fbc747930aa039300e4d2670c2a91f5aa622f1b4868600fc89b01b6278385fbcd46f9574186fa3d9b376a9e7538e50f8d118ec13cfbcb63e + languageName: node + linkType: hard + "@babel/generator@npm:7.17.7": version: 7.17.7 resolution: "@babel/generator@npm:7.17.7" @@ -488,6 +529,19 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.25.9, @babel/generator@npm:^7.26.0": + version: 7.26.2 + resolution: "@babel/generator@npm:7.26.2" + dependencies: + "@babel/parser": "npm:^7.26.2" + "@babel/types": "npm:^7.26.0" + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.25" + jsesc: "npm:^3.0.2" + checksum: 10c0/167ebce8977142f5012fad6bd91da51ac52bcd752f2261a54b7ab605d928aebe57e21636cdd2a9c7757e552652c68d9fcb5d40b06fcb66e02d9ee7526e118a5c + languageName: node + linkType: hard + "@babel/helper-annotate-as-pure@npm:7.22.5": version: 7.22.5 resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" @@ -529,6 +583,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-compilation-targets@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-compilation-targets@npm:7.25.9" + dependencies: + "@babel/compat-data": "npm:^7.25.9" + "@babel/helper-validator-option": "npm:^7.25.9" + browserslist: "npm:^4.24.0" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: 10c0/a6b26a1e4222e69ef8e62ee19374308f060b007828bc11c65025ecc9e814aba21ff2175d6d3f8bf53c863edd728ee8f94ba7870f8f90a37d39552ad9933a8aaa + languageName: node + linkType: hard + "@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.21.0, @babel/helper-create-class-features-plugin@npm:^7.24.0, @babel/helper-create-class-features-plugin@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-create-class-features-plugin@npm:7.24.7" @@ -639,6 +706,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-imports@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-module-imports@npm:7.25.9" + dependencies: + "@babel/traverse": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/078d3c2b45d1f97ffe6bb47f61961be4785d2342a4156d8b42c92ee4e1b7b9e365655dd6cb25329e8fe1a675c91eeac7e3d04f0c518b67e417e29d6e27b6aa70 + languageName: node + linkType: hard + "@babel/helper-module-transforms@npm:^7.23.3, @babel/helper-module-transforms@npm:^7.24.7, @babel/helper-module-transforms@npm:^7.25.2": version: 7.25.2 resolution: "@babel/helper-module-transforms@npm:7.25.2" @@ -653,6 +730,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/helper-module-transforms@npm:7.26.0" + dependencies: + "@babel/helper-module-imports": "npm:^7.25.9" + "@babel/helper-validator-identifier": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/ee111b68a5933481d76633dad9cdab30c41df4479f0e5e1cc4756dc9447c1afd2c9473b5ba006362e35b17f4ebddd5fca090233bef8dfc84dca9d9127e56ec3a + languageName: node + linkType: hard + "@babel/helper-optimise-call-expression@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-optimise-call-expression@npm:7.24.7" @@ -669,6 +759,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-plugin-utils@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-plugin-utils@npm:7.25.9" + checksum: 10c0/483066a1ba36ff16c0116cd24f93de05de746a603a777cd695ac7a1b034928a65a4ecb35f255761ca56626435d7abdb73219eba196f9aa83b6c3c3169325599d + languageName: node + linkType: hard + "@babel/helper-remap-async-to-generator@npm:^7.22.20, @babel/helper-remap-async-to-generator@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-remap-async-to-generator@npm:7.24.7" @@ -740,6 +837,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-string-parser@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-string-parser@npm:7.25.9" + checksum: 10c0/7244b45d8e65f6b4338a6a68a8556f2cb161b782343e97281a5f2b9b93e420cad0d9f5773a59d79f61d0c448913d06f6a2358a87f2e203cf112e3c5b53522ee6 + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.16.7, @babel/helper-validator-identifier@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-validator-identifier@npm:7.24.7" @@ -747,6 +851,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-identifier@npm:7.25.9" + checksum: 10c0/4fc6f830177b7b7e887ad3277ddb3b91d81e6c4a24151540d9d1023e8dc6b1c0505f0f0628ae653601eb4388a8db45c1c14b2c07a9173837aef7e4116456259d + languageName: node + linkType: hard + "@babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.23.5, @babel/helper-validator-option@npm:^7.24.8": version: 7.24.8 resolution: "@babel/helper-validator-option@npm:7.24.8" @@ -754,6 +865,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-option@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-option@npm:7.25.9" + checksum: 10c0/27fb195d14c7dcb07f14e58fe77c44eea19a6a40a74472ec05c441478fa0bb49fa1c32b2d64be7a38870ee48ef6601bdebe98d512f0253aea0b39756c4014f3e + languageName: node + linkType: hard + "@babel/helper-wrap-function@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-wrap-function@npm:7.24.7" @@ -776,6 +894,16 @@ __metadata: languageName: node linkType: hard +"@babel/helpers@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/helpers@npm:7.26.0" + dependencies: + "@babel/template": "npm:^7.25.9" + "@babel/types": "npm:^7.26.0" + checksum: 10c0/343333cced6946fe46617690a1d0789346960910225ce359021a88a60a65bc0d791f0c5d240c0ed46cf8cc63b5fd7df52734ff14e43b9c32feae2b61b1647097 + languageName: node + linkType: hard + "@babel/highlight@npm:^7.24.7": version: 7.24.7 resolution: "@babel/highlight@npm:7.24.7" @@ -799,6 +927,17 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.2": + version: 7.26.2 + resolution: "@babel/parser@npm:7.26.2" + dependencies: + "@babel/types": "npm:^7.26.0" + bin: + parser: ./bin/babel-parser.js + checksum: 10c0/751a743087b3a9172a7599f1421830d44c38f065ef781588d2bfb1c98f9b461719a226feb13c868d7a284783eee120c88ea522593118f2668f46ebfb1105c4d7 + languageName: node + linkType: hard + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.24.4": version: 7.24.4 resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.24.4" @@ -1711,25 +1850,25 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-self@npm:^7.18.6": - version: 7.22.5 - resolution: "@babel/plugin-transform-react-jsx-self@npm:7.22.5" +"@babel/plugin-transform-react-jsx-self@npm:^7.24.7": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx-self@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/263091bdede1f448cb2c59b84eb69972c15d3f022c929a75337bd20d8b65551ac38cd26dad1946eaa93289643506b10ddaea3445a28cb8fca5a773a22a0df90b + checksum: 10c0/ce0e289f6af93d7c4dc6b385512199c5bb138ae61507b4d5117ba88b6a6b5092f704f1bdf80080b7d69b1b8c36649f2a0b250e8198667d4d30c08bbb1546bd99 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-source@npm:^7.19.6": - version: 7.22.5 - resolution: "@babel/plugin-transform-react-jsx-source@npm:7.22.5" +"@babel/plugin-transform-react-jsx-source@npm:^7.24.7": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx-source@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/defc9debb76b4295e3617ef7795a0533dbbecef6f51bf5ba4bfc162df892a84fd39e14d5f1b9a5aad7b09b97074fef4c6756f9d2036eef5a9874acabe198f75a + checksum: 10c0/fc9ee08efc9be7cbd2cc6788bbf92579adf3cab37912481f1b915221be3d22b0613b5b36a721df5f4c0ab65efe8582fcf8673caab83e6e1ce4cc04ceebf57dfa languageName: node linkType: hard @@ -2258,6 +2397,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/template@npm:7.25.9" + dependencies: + "@babel/code-frame": "npm:^7.25.9" + "@babel/parser": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/ebe677273f96a36c92cc15b7aa7b11cc8bc8a3bb7a01d55b2125baca8f19cae94ff3ce15f1b1880fb8437f3a690d9f89d4e91f16fc1dc4d3eb66226d128983ab + languageName: node + linkType: hard + "@babel/traverse@npm:7.23.2": version: 7.23.2 resolution: "@babel/traverse@npm:7.23.2" @@ -2291,6 +2441,21 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/traverse@npm:7.25.9" + dependencies: + "@babel/code-frame": "npm:^7.25.9" + "@babel/generator": "npm:^7.25.9" + "@babel/parser": "npm:^7.25.9" + "@babel/template": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + debug: "npm:^4.3.1" + globals: "npm:^11.1.0" + checksum: 10c0/e90be586a714da4adb80e6cb6a3c5cfcaa9b28148abdafb065e34cc109676fc3db22cf98cd2b2fff66ffb9b50c0ef882cab0f466b6844be0f6c637b82719bba1 + languageName: node + linkType: hard + "@babel/types@npm:7.17.0": version: 7.17.0 resolution: "@babel/types@npm:7.17.0" @@ -2312,6 +2477,16 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/types@npm:7.26.0" + dependencies: + "@babel/helper-string-parser": "npm:^7.25.9" + "@babel/helper-validator-identifier": "npm:^7.25.9" + checksum: 10c0/b694f41ad1597127e16024d766c33a641508aad037abd08d0d1f73af753e1119fa03b4a107d04b5f92cc19c095a594660547ae9bead1db2299212d644b0a5cb8 + languageName: node + linkType: hard + "@base2/pretty-print-object@npm:1.0.1": version: 1.0.1 resolution: "@base2/pretty-print-object@npm:1.0.1" @@ -2504,6 +2679,15 @@ __metadata: languageName: node linkType: hard +"@emnapi/runtime@npm:^1.2.0": + version: 1.3.1 + resolution: "@emnapi/runtime@npm:1.3.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/060ffede50f1b619c15083312b80a9e62a5b0c87aa8c1b54854c49766c9d69f8d1d3d87bd963a647071263a320db41b25eaa50b74d6a80dcc763c23dbeaafd6c + languageName: node + linkType: hard + "@emotion/babel-plugin@npm:^11.11.0": version: 11.11.0 resolution: "@emotion/babel-plugin@npm:11.11.0" @@ -3429,6 +3613,18 @@ __metadata: languageName: node linkType: hard +"@img/sharp-darwin-arm64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-darwin-arm64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-darwin-arm64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-darwin-arm64": + optional: true + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@img/sharp-darwin-x64@npm:0.33.4": version: 0.33.4 resolution: "@img/sharp-darwin-x64@npm:0.33.4" @@ -3441,6 +3637,18 @@ __metadata: languageName: node linkType: hard +"@img/sharp-darwin-x64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-darwin-x64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-darwin-x64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-darwin-x64": + optional: true + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@img/sharp-libvips-darwin-arm64@npm:1.0.2": version: 1.0.2 resolution: "@img/sharp-libvips-darwin-arm64@npm:1.0.2" @@ -3448,6 +3656,13 @@ __metadata: languageName: node linkType: hard +"@img/sharp-libvips-darwin-arm64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-darwin-arm64@npm:1.0.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@img/sharp-libvips-darwin-x64@npm:1.0.2": version: 1.0.2 resolution: "@img/sharp-libvips-darwin-x64@npm:1.0.2" @@ -3455,6 +3670,13 @@ __metadata: languageName: node linkType: hard +"@img/sharp-libvips-darwin-x64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-darwin-x64@npm:1.0.4" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@img/sharp-libvips-linux-arm64@npm:1.0.2": version: 1.0.2 resolution: "@img/sharp-libvips-linux-arm64@npm:1.0.2" @@ -3462,6 +3684,13 @@ __metadata: languageName: node linkType: hard +"@img/sharp-libvips-linux-arm64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-linux-arm64@npm:1.0.4" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@img/sharp-libvips-linux-arm@npm:1.0.2": version: 1.0.2 resolution: "@img/sharp-libvips-linux-arm@npm:1.0.2" @@ -3469,6 +3698,13 @@ __metadata: languageName: node linkType: hard +"@img/sharp-libvips-linux-arm@npm:1.0.5": + version: 1.0.5 + resolution: "@img/sharp-libvips-linux-arm@npm:1.0.5" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + "@img/sharp-libvips-linux-s390x@npm:1.0.2": version: 1.0.2 resolution: "@img/sharp-libvips-linux-s390x@npm:1.0.2" @@ -3476,6 +3712,13 @@ __metadata: languageName: node linkType: hard +"@img/sharp-libvips-linux-s390x@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-linux-s390x@npm:1.0.4" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + "@img/sharp-libvips-linux-x64@npm:1.0.2": version: 1.0.2 resolution: "@img/sharp-libvips-linux-x64@npm:1.0.2" @@ -3483,6 +3726,13 @@ __metadata: languageName: node linkType: hard +"@img/sharp-libvips-linux-x64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-linux-x64@npm:1.0.4" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@img/sharp-libvips-linuxmusl-arm64@npm:1.0.2": version: 1.0.2 resolution: "@img/sharp-libvips-linuxmusl-arm64@npm:1.0.2" @@ -3490,6 +3740,13 @@ __metadata: languageName: node linkType: hard +"@img/sharp-libvips-linuxmusl-arm64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-linuxmusl-arm64@npm:1.0.4" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@img/sharp-libvips-linuxmusl-x64@npm:1.0.2": version: 1.0.2 resolution: "@img/sharp-libvips-linuxmusl-x64@npm:1.0.2" @@ -3497,6 +3754,13 @@ __metadata: languageName: node linkType: hard +"@img/sharp-libvips-linuxmusl-x64@npm:1.0.4": + version: 1.0.4 + resolution: "@img/sharp-libvips-linuxmusl-x64@npm:1.0.4" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@img/sharp-linux-arm64@npm:0.33.4": version: 0.33.4 resolution: "@img/sharp-linux-arm64@npm:0.33.4" @@ -3509,6 +3773,18 @@ __metadata: languageName: node linkType: hard +"@img/sharp-linux-arm64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linux-arm64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linux-arm64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-linux-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@img/sharp-linux-arm@npm:0.33.4": version: 0.33.4 resolution: "@img/sharp-linux-arm@npm:0.33.4" @@ -3521,6 +3797,18 @@ __metadata: languageName: node linkType: hard +"@img/sharp-linux-arm@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linux-arm@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linux-arm": "npm:1.0.5" + dependenciesMeta: + "@img/sharp-libvips-linux-arm": + optional: true + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + "@img/sharp-linux-s390x@npm:0.33.4": version: 0.33.4 resolution: "@img/sharp-linux-s390x@npm:0.33.4" @@ -3533,6 +3821,18 @@ __metadata: languageName: node linkType: hard +"@img/sharp-linux-s390x@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linux-s390x@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linux-s390x": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-linux-s390x": + optional: true + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + "@img/sharp-linux-x64@npm:0.33.4": version: 0.33.4 resolution: "@img/sharp-linux-x64@npm:0.33.4" @@ -3545,6 +3845,18 @@ __metadata: languageName: node linkType: hard +"@img/sharp-linux-x64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linux-x64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linux-x64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-linux-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@img/sharp-linuxmusl-arm64@npm:0.33.4": version: 0.33.4 resolution: "@img/sharp-linuxmusl-arm64@npm:0.33.4" @@ -3557,6 +3869,18 @@ __metadata: languageName: node linkType: hard +"@img/sharp-linuxmusl-arm64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linuxmusl-arm64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@img/sharp-linuxmusl-x64@npm:0.33.4": version: 0.33.4 resolution: "@img/sharp-linuxmusl-x64@npm:0.33.4" @@ -3569,6 +3893,18 @@ __metadata: languageName: node linkType: hard +"@img/sharp-linuxmusl-x64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-linuxmusl-x64@npm:0.33.5" + dependencies: + "@img/sharp-libvips-linuxmusl-x64": "npm:1.0.4" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@img/sharp-wasm32@npm:0.33.4": version: 0.33.4 resolution: "@img/sharp-wasm32@npm:0.33.4" @@ -3578,6 +3914,15 @@ __metadata: languageName: node linkType: hard +"@img/sharp-wasm32@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-wasm32@npm:0.33.5" + dependencies: + "@emnapi/runtime": "npm:^1.2.0" + conditions: cpu=wasm32 + languageName: node + linkType: hard + "@img/sharp-win32-ia32@npm:0.33.4": version: 0.33.4 resolution: "@img/sharp-win32-ia32@npm:0.33.4" @@ -3585,6 +3930,13 @@ __metadata: languageName: node linkType: hard +"@img/sharp-win32-ia32@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-win32-ia32@npm:0.33.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@img/sharp-win32-x64@npm:0.33.4": version: 0.33.4 resolution: "@img/sharp-win32-x64@npm:0.33.4" @@ -3592,6 +3944,13 @@ __metadata: languageName: node linkType: hard +"@img/sharp-win32-x64@npm:0.33.5": + version: 0.33.5 + resolution: "@img/sharp-win32-x64@npm:0.33.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@inquirer/confirm@npm:^3.0.0": version: 3.1.20 resolution: "@inquirer/confirm@npm:3.1.20" @@ -3908,72 +4267,65 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:14.2.5, @next/env@npm:^14.2.5": - version: 14.2.5 - resolution: "@next/env@npm:14.2.5" - checksum: 10c0/63d8b88ac450b3c37940a9e2119a63a1074aca89908574ade6157a8aa295275dcb3ac5f69e00883fc55d0f12963b73b74e87ba32a5768a489f9609c6be57b699 +"@next/env@npm:15.0.3, @next/env@npm:^15.0.3": + version: 15.0.3 + resolution: "@next/env@npm:15.0.3" + checksum: 10c0/63582fed80d6a28fff102c935095da71fd57ddf6b5f5d564e85ebdefdeb93298f7f7cf7d813c75b460c6627106717ea959b4c232939e7abb97d73d8b8467d4cd languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:14.2.5": - version: 14.2.5 - resolution: "@next/swc-darwin-arm64@npm:14.2.5" +"@next/swc-darwin-arm64@npm:15.0.3": + version: 15.0.3 + resolution: "@next/swc-darwin-arm64@npm:15.0.3" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:14.2.5": - version: 14.2.5 - resolution: "@next/swc-darwin-x64@npm:14.2.5" +"@next/swc-darwin-x64@npm:15.0.3": + version: 15.0.3 + resolution: "@next/swc-darwin-x64@npm:15.0.3" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:14.2.5": - version: 14.2.5 - resolution: "@next/swc-linux-arm64-gnu@npm:14.2.5" +"@next/swc-linux-arm64-gnu@npm:15.0.3": + version: 15.0.3 + resolution: "@next/swc-linux-arm64-gnu@npm:15.0.3" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:14.2.5": - version: 14.2.5 - resolution: "@next/swc-linux-arm64-musl@npm:14.2.5" +"@next/swc-linux-arm64-musl@npm:15.0.3": + version: 15.0.3 + resolution: "@next/swc-linux-arm64-musl@npm:15.0.3" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:14.2.5": - version: 14.2.5 - resolution: "@next/swc-linux-x64-gnu@npm:14.2.5" +"@next/swc-linux-x64-gnu@npm:15.0.3": + version: 15.0.3 + resolution: "@next/swc-linux-x64-gnu@npm:15.0.3" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:14.2.5": - version: 14.2.5 - resolution: "@next/swc-linux-x64-musl@npm:14.2.5" +"@next/swc-linux-x64-musl@npm:15.0.3": + version: 15.0.3 + resolution: "@next/swc-linux-x64-musl@npm:15.0.3" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:14.2.5": - version: 14.2.5 - resolution: "@next/swc-win32-arm64-msvc@npm:14.2.5" +"@next/swc-win32-arm64-msvc@npm:15.0.3": + version: 15.0.3 + resolution: "@next/swc-win32-arm64-msvc@npm:15.0.3" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:14.2.5": - version: 14.2.5 - resolution: "@next/swc-win32-ia32-msvc@npm:14.2.5" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@next/swc-win32-x64-msvc@npm:14.2.5": - version: 14.2.5 - resolution: "@next/swc-win32-x64-msvc@npm:14.2.5" +"@next/swc-win32-x64-msvc@npm:15.0.3": + version: 15.0.3 + resolution: "@next/swc-win32-x64-msvc@npm:15.0.3" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -5716,17 +6068,17 @@ __metadata: webpack: "npm:5" zone.js: "npm:^0.14.2" peerDependencies: - "@angular-devkit/architect": ">=0.1500.0 < 0.1900.0" - "@angular-devkit/build-angular": ">=15.0.0 < 19.0.0" - "@angular-devkit/core": ">=15.0.0 < 19.0.0" - "@angular/cli": ">=15.0.0 < 19.0.0" - "@angular/common": ">=15.0.0 < 19.0.0" - "@angular/compiler": ">=15.0.0 < 19.0.0" - "@angular/compiler-cli": ">=15.0.0 < 19.0.0" - "@angular/core": ">=15.0.0 < 19.0.0" - "@angular/forms": ">=15.0.0 < 19.0.0" - "@angular/platform-browser": ">=15.0.0 < 19.0.0" - "@angular/platform-browser-dynamic": ">=15.0.0 < 19.0.0" + "@angular-devkit/architect": ">=0.1500.0 < 0.2000.0" + "@angular-devkit/build-angular": ">=15.0.0 < 20.0.0" + "@angular-devkit/core": ">=15.0.0 < 20.0.0" + "@angular/cli": ">=15.0.0 < 20.0.0" + "@angular/common": ">=15.0.0 < 20.0.0" + "@angular/compiler": ">=15.0.0 < 20.0.0" + "@angular/compiler-cli": ">=15.0.0 < 20.0.0" + "@angular/core": ">=15.0.0 < 20.0.0" + "@angular/forms": ">=15.0.0 < 20.0.0" + "@angular/platform-browser": ">=15.0.0 < 20.0.0" + "@angular/platform-browser-dynamic": ">=15.0.0 < 20.0.0" rxjs: ^6.0.0 || ^7.4.0 storybook: "workspace:^" typescript: ^4.0.0 || ^5.0.0 @@ -6260,6 +6612,7 @@ __metadata: execa: "npm:^8.0.1" find-up: "npm:^7.0.0" formik: "npm:^2.2.9" + pathe: "npm:^1.1.2" picocolors: "npm:^1.1.0" polished: "npm:^4.2.2" prompts: "npm:^2.4.0" @@ -6294,14 +6647,14 @@ __metadata: "@storybook/react": "workspace:*" "@storybook/test": "workspace:*" "@types/node": "npm:^18.0.0" - next: "npm:^14.2.5" + next: "npm:^15.0.3" sharp: "npm:^0.33.3" styled-jsx: "npm:5.1.6" typescript: "npm:^5.3.2" - vite-plugin-storybook-nextjs: "npm:^1.0.11" + vite-plugin-storybook-nextjs: "npm:^1.1.0" peerDependencies: "@storybook/test": "workspace:*" - next: ^14.1.0 + next: ^14.1.0 || ^15.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta storybook: "workspace:^" @@ -6477,7 +6830,7 @@ __metadata: find-up: "npm:^5.0.0" image-size: "npm:^1.0.0" loader-utils: "npm:^3.2.1" - next: "npm:^14.1.0" + next: "npm:^15.0.3" node-polyfill-webpack-plugin: "npm:^2.0.1" pnp-webpack-plugin: "npm:^1.7.0" postcss: "npm:^8.4.38" @@ -6495,7 +6848,7 @@ __metadata: typescript: "npm:^5.3.2" webpack: "npm:^5.65.0" peerDependencies: - next: ^13.5.0 || ^14.0.0 + next: ^13.5.0 || ^14.0.0 || ^15.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta storybook: "workspace:^" @@ -6742,6 +7095,27 @@ __metadata: languageName: unknown linkType: soft +"@storybook/react-native-web-vite@workspace:frameworks/react-native-web-vite": + version: 0.0.0-use.local + resolution: "@storybook/react-native-web-vite@workspace:frameworks/react-native-web-vite" + dependencies: + "@joshwooding/vite-plugin-react-docgen-typescript": "npm:0.3.0" + "@storybook/builder-vite": "workspace:*" + "@storybook/react": "workspace:*" + "@storybook/react-vite": "workspace:*" + "@types/node": "npm:^22.0.0" + "@vitejs/plugin-react": "npm:^4.3.2" + typescript: "npm:^5.3.2" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-native: ">=0.74.5" + react-native-web: ^0.19.12 + storybook: "workspace:^" + vite: ^5.0.0 + languageName: unknown + linkType: soft + "@storybook/react-vite@workspace:*, @storybook/react-vite@workspace:frameworks/react-vite": version: 0.0.0-use.local resolution: "@storybook/react-vite@workspace:frameworks/react-vite" @@ -6919,7 +7293,7 @@ __metadata: "@types/serve-static": "npm:^1.13.8" "@typescript-eslint/experimental-utils": "npm:^5.62.0" "@typescript-eslint/parser": "npm:^6.18.1" - "@vitejs/plugin-react": "npm:^3.0.1" + "@vitejs/plugin-react": "npm:^4.3.2" "@vitejs/plugin-vue": "npm:^4.4.0" "@vitest/browser": "npm:^2.1.3" "@vitest/coverage-istanbul": "npm:^2.1.3" @@ -7343,20 +7717,19 @@ __metadata: languageName: node linkType: hard -"@swc/counter@npm:^0.1.3": +"@swc/counter@npm:0.1.3": version: 0.1.3 resolution: "@swc/counter@npm:0.1.3" checksum: 10c0/8424f60f6bf8694cfd2a9bca45845bce29f26105cda8cf19cdb9fd3e78dc6338699e4db77a89ae449260bafa1cc6bec307e81e7fb96dbf7dcfce0eea55151356 languageName: node linkType: hard -"@swc/helpers@npm:0.5.5": - version: 0.5.5 - resolution: "@swc/helpers@npm:0.5.5" +"@swc/helpers@npm:0.5.13": + version: 0.5.13 + resolution: "@swc/helpers@npm:0.5.13" dependencies: - "@swc/counter": "npm:^0.1.3" tslib: "npm:^2.4.0" - checksum: 10c0/21a9b9cfe7e00865f9c9f3eb4c1cc5b397143464f7abee76a2c5366e591e06b0155b5aac93fe8269ef8d548df253f6fd931e9ddfc0fd12efd405f90f45506e7d + checksum: 10c0/b9df578401fc62405da9a6c31e79e447a2fd90f68b25b1daee12f2caf2821991bb89106f0397bc1acb4c4d84a8ce079d04b60b65f534496952e3bf8c9a52f40f languageName: node linkType: hard @@ -7605,7 +7978,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:*, @types/babel__core@npm:^7, @types/babel__core@npm:^7.18.0": +"@types/babel__core@npm:*, @types/babel__core@npm:^7, @types/babel__core@npm:^7.18.0, @types/babel__core@npm:^7.20.5": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" dependencies: @@ -8751,18 +9124,18 @@ __metadata: languageName: node linkType: hard -"@vitejs/plugin-react@npm:^3.0.1": - version: 3.1.0 - resolution: "@vitejs/plugin-react@npm:3.1.0" +"@vitejs/plugin-react@npm:^4.3.2": + version: 4.3.3 + resolution: "@vitejs/plugin-react@npm:4.3.3" dependencies: - "@babel/core": "npm:^7.20.12" - "@babel/plugin-transform-react-jsx-self": "npm:^7.18.6" - "@babel/plugin-transform-react-jsx-source": "npm:^7.19.6" - magic-string: "npm:^0.27.0" - react-refresh: "npm:^0.14.0" + "@babel/core": "npm:^7.25.2" + "@babel/plugin-transform-react-jsx-self": "npm:^7.24.7" + "@babel/plugin-transform-react-jsx-source": "npm:^7.24.7" + "@types/babel__core": "npm:^7.20.5" + react-refresh: "npm:^0.14.2" peerDependencies: - vite: ^4.1.0-beta.0 - checksum: 10c0/259a92a303cd736240dc0d3282d1261339e7bbcf51c5b326868c910b35d4bd22a360334b2dafa5bfc7f3e935f2cd0fdc7ccb6ec6b519b81017c4c4812cd05290 + vite: ^4.2.0 || ^5.0.0 + checksum: 10c0/b370c25fb47bb96f0cc51f3aadbbcfce54e40f95a4de67cf932e5ec526f139648da703725c6ea2c71a1b525eb3dd6e3e8ff877da143627cd2575de5ec4f00aa3 languageName: node linkType: hard @@ -11274,6 +11647,20 @@ __metadata: languageName: node linkType: hard +"browserslist@npm:^4.24.0": + version: 4.24.2 + resolution: "browserslist@npm:4.24.2" + dependencies: + caniuse-lite: "npm:^1.0.30001669" + electron-to-chromium: "npm:^1.5.41" + node-releases: "npm:^2.0.18" + update-browserslist-db: "npm:^1.1.1" + bin: + browserslist: cli.js + checksum: 10c0/d747c9fb65ed7b4f1abcae4959405707ed9a7b835639f8a9ba0da2911995a6ab9b0648fd05baf2a4d4e3cf7f9fdbad56d3753f91881e365992c1d49c8d88ff7a + languageName: node + linkType: hard + "buffer-crc32@npm:^0.2.5": version: 0.2.13 resolution: "buffer-crc32@npm:0.2.13" @@ -11534,6 +11921,13 @@ __metadata: languageName: node linkType: hard +"caniuse-lite@npm:^1.0.30001669": + version: 1.0.30001677 + resolution: "caniuse-lite@npm:1.0.30001677" + checksum: 10c0/22b4aa738b213b5d0bc820c26ba23fa265ca90a5c59776e1a686b9ab6fff9120d0825fd920c0a601a4b65056ef40d01548405feb95c8dd6083255f50c71a0864 + languageName: node + linkType: hard + "case-sensitive-paths-webpack-plugin@npm:^2.4.0": version: 2.4.0 resolution: "case-sensitive-paths-webpack-plugin@npm:2.4.0" @@ -13598,6 +13992,13 @@ __metadata: languageName: node linkType: hard +"electron-to-chromium@npm:^1.5.41": + version: 1.5.50 + resolution: "electron-to-chromium@npm:1.5.50" + checksum: 10c0/8b77b18ae833bfe2173e346ac33b8d66b5b5acf0cf5de65df9799f4d482334c938aa0950e4d01391d5fab8994f46c0e9059f4517843e7b8d861f9b0c49eb4c5d + languageName: node + linkType: hard + "elliptic@npm:^6.5.3, elliptic@npm:^6.5.4": version: 6.5.4 resolution: "elliptic@npm:6.5.4" @@ -14265,6 +14666,13 @@ __metadata: languageName: node linkType: hard +"escalade@npm:^3.2.0": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 + languageName: node + linkType: hard + "escape-html@npm:~1.0.3": version: 1.0.3 resolution: "escape-html@npm:1.0.3" @@ -16461,7 +16869,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.3, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.3, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 @@ -18540,6 +18948,15 @@ __metadata: languageName: node linkType: hard +"jsesc@npm:^3.0.2": + version: 3.0.2 + resolution: "jsesc@npm:3.0.2" + bin: + jsesc: bin/jsesc + checksum: 10c0/ef22148f9e793180b14d8a145ee6f9f60f301abf443288117b4b6c53d0ecd58354898dc506ccbb553a5f7827965cd38bc5fb726575aae93c5e8915e2de8290e1 + languageName: node + linkType: hard + "jsesc@npm:~0.5.0": version: 0.5.0 resolution: "jsesc@npm:0.5.0" @@ -21267,31 +21684,32 @@ __metadata: languageName: node linkType: hard -"next@npm:^14.1.0, next@npm:^14.2.5": - version: 14.2.5 - resolution: "next@npm:14.2.5" +"next@npm:^15.0.3": + version: 15.0.3 + resolution: "next@npm:15.0.3" dependencies: - "@next/env": "npm:14.2.5" - "@next/swc-darwin-arm64": "npm:14.2.5" - "@next/swc-darwin-x64": "npm:14.2.5" - "@next/swc-linux-arm64-gnu": "npm:14.2.5" - "@next/swc-linux-arm64-musl": "npm:14.2.5" - "@next/swc-linux-x64-gnu": "npm:14.2.5" - "@next/swc-linux-x64-musl": "npm:14.2.5" - "@next/swc-win32-arm64-msvc": "npm:14.2.5" - "@next/swc-win32-ia32-msvc": "npm:14.2.5" - "@next/swc-win32-x64-msvc": "npm:14.2.5" - "@swc/helpers": "npm:0.5.5" + "@next/env": "npm:15.0.3" + "@next/swc-darwin-arm64": "npm:15.0.3" + "@next/swc-darwin-x64": "npm:15.0.3" + "@next/swc-linux-arm64-gnu": "npm:15.0.3" + "@next/swc-linux-arm64-musl": "npm:15.0.3" + "@next/swc-linux-x64-gnu": "npm:15.0.3" + "@next/swc-linux-x64-musl": "npm:15.0.3" + "@next/swc-win32-arm64-msvc": "npm:15.0.3" + "@next/swc-win32-x64-msvc": "npm:15.0.3" + "@swc/counter": "npm:0.1.3" + "@swc/helpers": "npm:0.5.13" busboy: "npm:1.6.0" caniuse-lite: "npm:^1.0.30001579" - graceful-fs: "npm:^4.2.11" postcss: "npm:8.4.31" - styled-jsx: "npm:5.1.1" + sharp: "npm:^0.33.5" + styled-jsx: "npm:5.1.6" peerDependencies: "@opentelemetry/api": ^1.1.0 "@playwright/test": ^1.41.2 - react: ^18.2.0 - react-dom: ^18.2.0 + babel-plugin-react-compiler: "*" + react: ^18.2.0 || 19.0.0-rc-66855b96-20241106 + react-dom: ^18.2.0 || 19.0.0-rc-66855b96-20241106 sass: ^1.3.0 dependenciesMeta: "@next/swc-darwin-arm64": @@ -21308,20 +21726,22 @@ __metadata: optional: true "@next/swc-win32-arm64-msvc": optional: true - "@next/swc-win32-ia32-msvc": - optional: true "@next/swc-win32-x64-msvc": optional: true + sharp: + optional: true peerDependenciesMeta: "@opentelemetry/api": optional: true "@playwright/test": optional: true + babel-plugin-react-compiler: + optional: true sass: optional: true bin: next: dist/bin/next - checksum: 10c0/8df7d8ccc1a5bab03fa50dd6656c8a6f3750e81ef0b087dc329fea9346847c3094a933a890a8e87151dc32f0bc55020b8f6386d4565856d83bcc10895d29ec08 + checksum: 10c0/c5f6a57acb5f29063abc82d4d4417a048d0c2d5216d6ded6aa3fe32d60bb4835ed57dd34e2ef8fdda15579e97205820dc25bf34556b1d942a01a33d9ae7f88db languageName: node linkType: hard @@ -23975,6 +24395,13 @@ __metadata: languageName: node linkType: hard +"react-refresh@npm:^0.14.2": + version: 0.14.2 + resolution: "react-refresh@npm:0.14.2" + checksum: 10c0/875b72ef56b147a131e33f2abd6ec059d1989854b3ff438898e4f9310bfcc73acff709445b7ba843318a953cb9424bcc2c05af2b3d80011cee28f25aef3e2ebb + languageName: node + linkType: hard + "react-remove-scroll-bar@npm:^2.3.3": version: 2.3.5 resolution: "react-remove-scroll-bar@npm:2.3.5" @@ -25724,6 +26151,75 @@ __metadata: languageName: node linkType: hard +"sharp@npm:^0.33.5": + version: 0.33.5 + resolution: "sharp@npm:0.33.5" + dependencies: + "@img/sharp-darwin-arm64": "npm:0.33.5" + "@img/sharp-darwin-x64": "npm:0.33.5" + "@img/sharp-libvips-darwin-arm64": "npm:1.0.4" + "@img/sharp-libvips-darwin-x64": "npm:1.0.4" + "@img/sharp-libvips-linux-arm": "npm:1.0.5" + "@img/sharp-libvips-linux-arm64": "npm:1.0.4" + "@img/sharp-libvips-linux-s390x": "npm:1.0.4" + "@img/sharp-libvips-linux-x64": "npm:1.0.4" + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.0.4" + "@img/sharp-libvips-linuxmusl-x64": "npm:1.0.4" + "@img/sharp-linux-arm": "npm:0.33.5" + "@img/sharp-linux-arm64": "npm:0.33.5" + "@img/sharp-linux-s390x": "npm:0.33.5" + "@img/sharp-linux-x64": "npm:0.33.5" + "@img/sharp-linuxmusl-arm64": "npm:0.33.5" + "@img/sharp-linuxmusl-x64": "npm:0.33.5" + "@img/sharp-wasm32": "npm:0.33.5" + "@img/sharp-win32-ia32": "npm:0.33.5" + "@img/sharp-win32-x64": "npm:0.33.5" + color: "npm:^4.2.3" + detect-libc: "npm:^2.0.3" + semver: "npm:^7.6.3" + dependenciesMeta: + "@img/sharp-darwin-arm64": + optional: true + "@img/sharp-darwin-x64": + optional: true + "@img/sharp-libvips-darwin-arm64": + optional: true + "@img/sharp-libvips-darwin-x64": + optional: true + "@img/sharp-libvips-linux-arm": + optional: true + "@img/sharp-libvips-linux-arm64": + optional: true + "@img/sharp-libvips-linux-s390x": + optional: true + "@img/sharp-libvips-linux-x64": + optional: true + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + "@img/sharp-libvips-linuxmusl-x64": + optional: true + "@img/sharp-linux-arm": + optional: true + "@img/sharp-linux-arm64": + optional: true + "@img/sharp-linux-s390x": + optional: true + "@img/sharp-linux-x64": + optional: true + "@img/sharp-linuxmusl-arm64": + optional: true + "@img/sharp-linuxmusl-x64": + optional: true + "@img/sharp-wasm32": + optional: true + "@img/sharp-win32-ia32": + optional: true + "@img/sharp-win32-x64": + optional: true + checksum: 10c0/6b81421ddfe6ee524d8d77e325c5e147fef22884e1c7b1656dfd89a88d7025894115da02d5f984261bf2e6daa16f98cadd1721c4ba408b4212b1d2a60f233484 + languageName: node + linkType: hard + "shebang-command@npm:^1.2.0": version: 1.2.0 resolution: "shebang-command@npm:1.2.0" @@ -26627,22 +27123,6 @@ __metadata: languageName: node linkType: hard -"styled-jsx@npm:5.1.1": - version: 5.1.1 - resolution: "styled-jsx@npm:5.1.1" - dependencies: - client-only: "npm:0.0.1" - peerDependencies: - react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" - peerDependenciesMeta: - "@babel/core": - optional: true - babel-plugin-macros: - optional: true - checksum: 10c0/42655cdadfa5388f8a48bb282d6b450df7d7b8cf066ac37038bd0499d3c9f084815ebd9ff9dfa12a218fd4441338851db79603498d7557207009c1cf4d609835 - languageName: node - linkType: hard - "styled-jsx@npm:5.1.6, styled-jsx@npm:^5.1.6": version: 5.1.6 resolution: "styled-jsx@npm:5.1.6" @@ -28182,6 +28662,20 @@ __metadata: languageName: node linkType: hard +"update-browserslist-db@npm:^1.1.1": + version: 1.1.1 + resolution: "update-browserslist-db@npm:1.1.1" + dependencies: + escalade: "npm:^3.2.0" + picocolors: "npm:^1.1.0" + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 10c0/536a2979adda2b4be81b07e311bd2f3ad5e978690987956bc5f514130ad50cac87cd22c710b686d79731e00fbee8ef43efe5fcd72baa241045209195d43dcc80 + languageName: node + linkType: hard + "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -28559,25 +29053,25 @@ __metadata: languageName: node linkType: hard -"vite-plugin-storybook-nextjs@npm:^1.0.11": - version: 1.0.11 - resolution: "vite-plugin-storybook-nextjs@npm:1.0.11" +"vite-plugin-storybook-nextjs@npm:^1.1.0": + version: 1.1.0 + resolution: "vite-plugin-storybook-nextjs@npm:1.1.0" dependencies: - "@next/env": "npm:^14.2.5" + "@next/env": "npm:^15.0.3" image-size: "npm:^1.1.1" magic-string: "npm:^0.30.11" module-alias: "npm:^2.2.3" sharp: "npm:^0.33.4" ts-dedent: "npm:^2.2.0" peerDependencies: - "@storybook/test": ^8.3.0-alpha.3 - next: ^14.1.0 - storybook: ^8.3.0-alpha.3 + "@storybook/test": ^8.3.0 + next: ^14.1.0 || ^15.0.0 + storybook: ^8.3.0 vite: ^5.0.0 dependenciesMeta: sharp: optional: true - checksum: 10c0/9652b76c13a682b688d9a4f617b1a66263f25f395a99af8e258bedef4f3b3ce1c856ec1ff66cc0359d6aedc96adee9750fd6b0432514dd575ad7896cd1de70df + checksum: 10c0/02761e1074e62a46b30fc5e13b1c7a3bf6047a5736ac17de8e33376a6cff2b1118a48a95d195ddfd37b1e7a55f6eb3385677da9b4d713189c2b68b9f9843906d languageName: node linkType: hard diff --git a/docs/_assets/contribute/local-storybook-website-dropdown-optimized.mp4 b/docs/_assets/contribute/local-storybook-website-dropdown-optimized.mp4 new file mode 100644 index 000000000000..b165b199c31b Binary files /dev/null and b/docs/_assets/contribute/local-storybook-website-dropdown-optimized.mp4 differ diff --git a/docs/_assets/contribute/local-storybook-website-dropdown-optimized.png b/docs/_assets/contribute/local-storybook-website-dropdown-optimized.png deleted file mode 100644 index 229efa469abf..000000000000 Binary files a/docs/_assets/contribute/local-storybook-website-dropdown-optimized.png and /dev/null differ diff --git a/docs/_snippets/add-localize-package-to-polyfills.md b/docs/_snippets/add-localize-package-to-polyfills.md deleted file mode 100644 index 109a146cb5d3..000000000000 --- a/docs/_snippets/add-localize-package-to-polyfills.md +++ /dev/null @@ -1,4 +0,0 @@ -```ts filename="src/polyfills.ts" renderer="angular" language="ts" -import '@angular/localize/init'; -``` - diff --git a/docs/_snippets/addon-actions-action-function.md b/docs/_snippets/addon-actions-action-function.md index 2bfa724a201b..ac2c1cd93a7d 100644 --- a/docs/_snippets/addon-actions-action-function.md +++ b/docs/_snippets/addon-actions-action-function.md @@ -91,4 +91,3 @@ const meta: Meta { export default meta; ``` - diff --git a/docs/_snippets/addon-backgrounds-grid.md b/docs/_snippets/addon-backgrounds-grid.md index 03c3b7559735..266d4e39d520 100644 --- a/docs/_snippets/addon-backgrounds-grid.md +++ b/docs/_snippets/addon-backgrounds-grid.md @@ -131,4 +131,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/addon-consume-and-update-globaltype.md b/docs/_snippets/addon-consume-and-update-globaltype.md index d2e163551ea6..08eed8c3a8bd 100644 --- a/docs/_snippets/addon-consume-and-update-globaltype.md +++ b/docs/_snippets/addon-consume-and-update-globaltype.md @@ -38,4 +38,3 @@ const ExampleToolbar = () => { ); }; ``` - diff --git a/docs/_snippets/addon-consume-globaltype.md b/docs/_snippets/addon-consume-globaltype.md index cbebb92a408d..6a53af2bdc55 100644 --- a/docs/_snippets/addon-consume-globaltype.md +++ b/docs/_snippets/addon-consume-globaltype.md @@ -38,4 +38,3 @@ const ThemePanel = (props) => { ); }; ``` - diff --git a/docs/_snippets/addon-highlight-reset.md b/docs/_snippets/addon-highlight-reset.md index 5cd0e675b9f0..72a5f296a996 100644 --- a/docs/_snippets/addon-highlight-reset.md +++ b/docs/_snippets/addon-highlight-reset.md @@ -240,4 +240,3 @@ export const ResetHighlight: Story = { ], }; ``` - diff --git a/docs/_snippets/addon-test-install.md b/docs/_snippets/addon-test-install.md index b516f291b85f..482a6c00793e 100644 --- a/docs/_snippets/addon-test-install.md +++ b/docs/_snippets/addon-test-install.md @@ -1,4 +1,4 @@ -```shell renderer="common" language="js" packageManager="npx" +```shell renderer="common" language="js" packageManager="npm" npx storybook add @storybook/experimental-addon-test ``` diff --git a/docs/_snippets/addon-viewport-options-in-preview.md b/docs/_snippets/addon-viewport-options-in-preview.md index 332b1e171235..c342682af443 100644 --- a/docs/_snippets/addon-viewport-options-in-preview.md +++ b/docs/_snippets/addon-viewport-options-in-preview.md @@ -4,7 +4,7 @@ import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport'; export default { parameters: { viewport: { - viewports: INITIAL_VIEWPORTS, + options: INITIAL_VIEWPORTS, }, }, initialGlobals: { @@ -20,7 +20,7 @@ import { Preview } from '@storybook/your-renderer'; const preview: Preview = { parameters: { viewport: { - viewports: INITIAL_VIEWPORTS, + options: INITIAL_VIEWPORTS, }, }, initialGlobals: { diff --git a/docs/_snippets/angular-install.md b/docs/_snippets/angular-install.md index 25add9054a0d..5333417d45d9 100644 --- a/docs/_snippets/angular-install.md +++ b/docs/_snippets/angular-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/angular ```shell renderer="angular" language="js" packageManager="yarn" yarn add --dev @storybook/angular ``` - diff --git a/docs/_snippets/angular-project-compodoc-config.md b/docs/_snippets/angular-project-compodoc-config.md index 161f5cfce106..ce7077448325 100644 --- a/docs/_snippets/angular-project-compodoc-config.md +++ b/docs/_snippets/angular-project-compodoc-config.md @@ -46,4 +46,3 @@ } } ``` - diff --git a/docs/_snippets/api-doc-block-argtypes-parameter.md b/docs/_snippets/api-doc-block-argtypes-parameter.md index f0f64183d994..abd54038f549 100644 --- a/docs/_snippets/api-doc-block-argtypes-parameter.md +++ b/docs/_snippets/api-doc-block-argtypes-parameter.md @@ -63,4 +63,3 @@ const meta: Meta<typeof Button> = { export default meta; ``` - diff --git a/docs/_snippets/api-doc-block-canvas-parameter.md b/docs/_snippets/api-doc-block-canvas-parameter.md index 64c77770d0d2..f49d31200bde 100644 --- a/docs/_snippets/api-doc-block-canvas-parameter.md +++ b/docs/_snippets/api-doc-block-canvas-parameter.md @@ -107,4 +107,3 @@ export const Basic: Story = { }, }; ``` - diff --git a/docs/_snippets/api-doc-block-controls-parameter.md b/docs/_snippets/api-doc-block-controls-parameter.md index 229051ffabb8..03f33b83c7ed 100644 --- a/docs/_snippets/api-doc-block-controls-parameter.md +++ b/docs/_snippets/api-doc-block-controls-parameter.md @@ -94,4 +94,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/api-doc-block-description-example.md b/docs/_snippets/api-doc-block-description-example.md index 8ae271fdb0af..63221a8078fc 100644 --- a/docs/_snippets/api-doc-block-description-example.md +++ b/docs/_snippets/api-doc-block-description-example.md @@ -4,7 +4,7 @@ import type { Meta, StoryObj } from '@storybook/angular'; import { Button } from './button.component'; /** - * # Button stories + * Button stories * These stories showcase the button */ const meta: Meta<Button> = { @@ -22,7 +22,7 @@ export default meta; type Story = StoryObj<Button>; /** - * # Primary Button + * Primary Button * This is the primary button */ export const Primary: Story = { @@ -40,7 +40,7 @@ export const Primary: Story = { import { Button } from './Button'; /** - * # Button stories + * Button stories * These stories showcase the button */ export default { @@ -55,7 +55,7 @@ export default { } /** - * # Primary Button + * Primary Button * This is the primary button */ export const Primary = { @@ -76,7 +76,7 @@ import type { Meta, StoryObj } from '@storybook/your-framework'; import { Button } from './Button'; /** - * # Button stories + * Button stories * These stories showcase the button */ const meta = { @@ -94,7 +94,7 @@ export default meta; type Story = StoryObj<typeof meta> /** - * # Primary Button + * Primary Button * This is the primary button */ export const Primary: Story = { @@ -115,7 +115,7 @@ import type { Meta, StoryObj } from '@storybook/your-framework'; import { Button } from './Button'; /** - * # Button stories + * Button stories * These stories showcase the button */ const meta: Meta<typeof Button> = { @@ -133,7 +133,7 @@ export default meta; type Story = StoryObj<typeof Button>; /** - * # Primary Button + * Primary Button * This is the primary button */ export const Primary: Story = { @@ -148,6 +148,10 @@ export const Primary: Story = { ``` ```js filename="Button.stories.js" renderer="web-components" language="js" +/** + * Button stories + * These stories showcase the button + */ export default { title: 'Button', component: 'demo-button', @@ -179,7 +183,7 @@ export const Primary = { import type { Meta, StoryObj } from '@storybook/web-components'; /** - * # Button stories + * Button stories * These stories showcase the button */ const meta: Meta = { @@ -198,7 +202,7 @@ export default meta; type Story = StoryObj; /** - * # Primary Button + * Primary Button * This is the primary button */ export const Primary: Story = { @@ -211,4 +215,3 @@ export const Primary: Story = { }, }; ``` - diff --git a/docs/_snippets/api-doc-block-source-parameter.md b/docs/_snippets/api-doc-block-source-parameter.md index 3f9b48757f67..8b1293180248 100644 --- a/docs/_snippets/api-doc-block-source-parameter.md +++ b/docs/_snippets/api-doc-block-source-parameter.md @@ -107,4 +107,3 @@ export const Basic: Story = { }, }; ``` - diff --git a/docs/_snippets/api-doc-block-story-parameter.md b/docs/_snippets/api-doc-block-story-parameter.md index 681649f5b5c8..1054cf6d1620 100644 --- a/docs/_snippets/api-doc-block-story-parameter.md +++ b/docs/_snippets/api-doc-block-story-parameter.md @@ -107,4 +107,3 @@ export const Basic: Story = { }, }; ``` - diff --git a/docs/_snippets/apollo-module.md b/docs/_snippets/apollo-module.md deleted file mode 100644 index 9412daad09df..000000000000 --- a/docs/_snippets/apollo-module.md +++ /dev/null @@ -1,38 +0,0 @@ -```ts filename="mock-graphql.module.ts" renderer="angular" language="ts" tabTitle="mock-apollo-module" -import { NgModule } from '@angular/core'; -import { APOLLO_OPTIONS } from 'apollo-angular'; -import { ApolloClientOptions, InMemoryCache } from '@apollo/client/core'; -import { HttpLink } from 'apollo-angular/http'; - -// See here for docs https://apollo-angular.com/docs/get-started - -const uri = 'https://your-graphql-endpoint'; -export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> { - return { - link: httpLink.create({ uri }), - cache: new InMemoryCache(), - defaultOptions: { - watchQuery: { - fetchPolicy: 'no-cache', - errorPolicy: 'all', - }, - query: { - fetchPolicy: 'no-cache', - errorPolicy: 'all', - }, - }, - }; -} - -@NgModule({ - providers: [ - { - provide: APOLLO_OPTIONS, - useFactory: createApollo, - deps: [HttpLink], - }, - ], -}) -export class MockGraphQLModule {} -``` - diff --git a/docs/_snippets/apollo-wrapper-component.md b/docs/_snippets/apollo-wrapper-component.md deleted file mode 100644 index bafb8de364d2..000000000000 --- a/docs/_snippets/apollo-wrapper-component.md +++ /dev/null @@ -1,98 +0,0 @@ -```html renderer="svelte" language="js" tabTitle="with-mock-implementation" -{/* MockApolloWrapperClient.svelte */} - -<script> - import { ApolloClient, InMemoryCache } from '@apollo/client'; - - import { setClient } from 'svelte-apollo'; - - const mockedClient = new ApolloClient({ - uri: 'https://your-graphql-endpoint', - cache: new InMemoryCache(), - defaultOptions: { - watchQuery: { - fetchPolicy: 'no-cache', - errorPolicy: 'all', - }, - query: { - fetchPolicy: 'no-cache', - errorPolicy: 'all', - }, - }, - }); - setClient(mockedClient); -</script> - -<slot /> -``` - -```html renderer="svelte" language="ts" tabTitle="with-mock-implementation" -{/* MockApolloWrapperClient.svelte */} - -<script lang="ts"> - import { ApolloClient, InMemoryCache } from '@apollo/client'; - - import { setClient } from 'svelte-apollo'; - - const mockedClient = new ApolloClient({ - uri: 'https://your-graphql-endpoint', - cache: new InMemoryCache(), - defaultOptions: { - watchQuery: { - fetchPolicy: 'no-cache', - errorPolicy: 'all', - }, - query: { - fetchPolicy: 'no-cache', - errorPolicy: 'all', - }, - }, - }); - setClient(mockedClient); -</script> - -<slot /> -``` - -```html renderer="vue" language="js" tabTitle="with-mock-implementation-3" -{/* ApolloWrapperClient.vue */} - -<template> - <div><slot /></div> -</template> - -<script> - import { defineComponent, provide } from 'vue'; - import { DefaultApolloClient } from '@vue/apollo-composable'; - import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core'; - - // Apollo client wrapper component that can be used within your app and Storybook - export default defineComponent({ - name: 'WrapperComponent', - setup() { - const httpLink = createHttpLink({ - // You should use an absolute URL here - uri: 'https://your-graphql-endpoint', - }); - const cache = new InMemoryCache(); - - const mockedClient = new ApolloClient({ - link: httpLink, - cache, - defaultOptions: { - watchQuery: { - fetchPolicy: 'no-cache', - errorPolicy: 'all', - }, - query: { - fetchPolicy: 'no-cache', - errorPolicy: 'all', - }, - }, - }); - provide(DefaultApolloClient, mockedClient); - }, - }); -</script> -``` - diff --git a/docs/_snippets/arg-types-control.md b/docs/_snippets/arg-types-control.md index 243e52f4056d..4cbca48ac3db 100644 --- a/docs/_snippets/arg-types-control.md +++ b/docs/_snippets/arg-types-control.md @@ -119,4 +119,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/arg-types-default-value.md b/docs/_snippets/arg-types-default-value.md index 9373e3301604..bc866a132112 100644 --- a/docs/_snippets/arg-types-default-value.md +++ b/docs/_snippets/arg-types-default-value.md @@ -119,4 +119,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/arg-types-description.md b/docs/_snippets/arg-types-description.md index c28da88b53f5..8ba11bbdc06f 100644 --- a/docs/_snippets/arg-types-description.md +++ b/docs/_snippets/arg-types-description.md @@ -89,4 +89,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/arg-types-if.md b/docs/_snippets/arg-types-if.md index 2844fd7896e6..73979e5bc378 100644 --- a/docs/_snippets/arg-types-if.md +++ b/docs/_snippets/arg-types-if.md @@ -221,4 +221,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/arg-types-in-meta.md b/docs/_snippets/arg-types-in-meta.md index 34ddd566c374..fe333056e15a 100644 --- a/docs/_snippets/arg-types-in-meta.md +++ b/docs/_snippets/arg-types-in-meta.md @@ -101,4 +101,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/arg-types-in-preview.md b/docs/_snippets/arg-types-in-preview.md index f382c50956c8..73c7b6bf4c5d 100644 --- a/docs/_snippets/arg-types-in-preview.md +++ b/docs/_snippets/arg-types-in-preview.md @@ -43,4 +43,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/arg-types-in-story.md b/docs/_snippets/arg-types-in-story.md index 41508f9a65df..43ce951c112c 100644 --- a/docs/_snippets/arg-types-in-story.md +++ b/docs/_snippets/arg-types-in-story.md @@ -52,7 +52,7 @@ const meta = { export default meta; -type Story = StoryObj<typeof Meta>; +type Story = StoryObj<typeof meta>; export const Basic = { argTypes: { @@ -126,4 +126,3 @@ export const Basic: Story = { }, }; ``` - diff --git a/docs/_snippets/arg-types-mapping.md b/docs/_snippets/arg-types-mapping.md index 88652f526512..7993754b63d0 100644 --- a/docs/_snippets/arg-types-mapping.md +++ b/docs/_snippets/arg-types-mapping.md @@ -117,4 +117,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/arg-types-name.md b/docs/_snippets/arg-types-name.md index 6e9237bbfd80..8053c80de77c 100644 --- a/docs/_snippets/arg-types-name.md +++ b/docs/_snippets/arg-types-name.md @@ -89,4 +89,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/arg-types-options.md b/docs/_snippets/arg-types-options.md index 3ca62ed1a603..730332d7f449 100644 --- a/docs/_snippets/arg-types-options.md +++ b/docs/_snippets/arg-types-options.md @@ -89,4 +89,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/arg-types-table.md b/docs/_snippets/arg-types-table.md index cbf0121445c8..231a02b9fc86 100644 --- a/docs/_snippets/arg-types-table.md +++ b/docs/_snippets/arg-types-table.md @@ -107,4 +107,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/arg-types-type.md b/docs/_snippets/arg-types-type.md index f51719f5a640..d1950ece31d4 100644 --- a/docs/_snippets/arg-types-type.md +++ b/docs/_snippets/arg-types-type.md @@ -77,4 +77,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/args-in-preview.md b/docs/_snippets/args-in-preview.md index d66d35c7a330..d0dd6acb435f 100644 --- a/docs/_snippets/args-in-preview.md +++ b/docs/_snippets/args-in-preview.md @@ -28,4 +28,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/args-usage-with-addons.md b/docs/_snippets/args-usage-with-addons.md index 58b3f7f22cad..59929a410957 100644 --- a/docs/_snippets/args-usage-with-addons.md +++ b/docs/_snippets/args-usage-with-addons.md @@ -12,4 +12,3 @@ resetArgs((argNames: ['key'])); // To reset all args resetArgs(); ``` - diff --git a/docs/_snippets/before-each-in-preview.md b/docs/_snippets/before-each-in-preview.md index 47abe76c5057..d8e79641135b 100644 --- a/docs/_snippets/before-each-in-preview.md +++ b/docs/_snippets/before-each-in-preview.md @@ -3,8 +3,8 @@ import MockDate from 'mockdate'; export default { async beforeEach() { - MockDate.reset() - } + MockDate.reset(); + }, }; ``` @@ -15,10 +15,9 @@ import MockDate from 'mockdate'; const preview: Preview = { async beforeEach() { - MockDate.reset() - } + MockDate.reset(); + }, }; export default preview; ``` - diff --git a/docs/_snippets/build-storybook-production-mode.md b/docs/_snippets/build-storybook-production-mode.md index 27b75f36ca31..ca247450716e 100644 --- a/docs/_snippets/build-storybook-production-mode.md +++ b/docs/_snippets/build-storybook-production-mode.md @@ -16,4 +16,3 @@ pnpm run build-storybook ```shell renderer="common" language="js" packageManager="yarn" yarn build-storybook ``` - diff --git a/docs/_snippets/button-component-with-proptypes.md b/docs/_snippets/button-component-with-proptypes.md index 4a36ccb3e890..253586174075 100644 --- a/docs/_snippets/button-component-with-proptypes.md +++ b/docs/_snippets/button-component-with-proptypes.md @@ -69,7 +69,7 @@ export const Button: React.FC<ButtonProps> = ({ isDisabled = false, content = '' }; ``` -```html filename="Button.svelte" renderer="svelte" language="js" +```svelte filename="Button.svelte" renderer="svelte" language="js" <script> /** * A Button Component @@ -92,9 +92,7 @@ export const Button: React.FC<ButtonProps> = ({ isDisabled = false, content = '' <button type="button" {disabled}>{content}</button> ``` -```html renderer="vue" language="js" tabTitle="3" -{/* Button.vue */} - +```html filename="Button.vue" renderer="vue" language="js" <template> <button type="button" :disabled="isDisabled">{{ label }}</button> </template> @@ -136,9 +134,7 @@ export const Button: React.FC<ButtonProps> = ({ isDisabled = false, content = '' </script> ``` -```html renderer="vue" language="ts" tabTitle="3" -{/* Button.vue */} - +```html filename="Button.vue" renderer="vue" language="ts" <template> <button type="button" :disabled="isDisabled">{{ label }}</button> </template> @@ -230,4 +226,3 @@ export class CustomButton extends LitElement { } } ``` - diff --git a/docs/_snippets/button-group-story.md b/docs/_snippets/button-group-story.md index e7695e6334a4..9fd1b5efaa1d 100644 --- a/docs/_snippets/button-group-story.md +++ b/docs/_snippets/button-group-story.md @@ -160,7 +160,30 @@ export const Pair: Story = { }; ``` -```js filename="ButtonGroup.stories.js" renderer="svelte" language="js" +```svelte filename="ButtonGroup.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import ButtonGroup from './ButtonGroup.svelte'; + + //👇 Imports the Button stories + import * as ButtonStories from './Button.stories.svelte'; + + const { Story } = defineMeta({ + component: ButtonGroup, + }); +</script> + +<Story + name="Pair" + args={{ + buttons: [{ ...ButtonStories.Primary.args }, { ...ButtonStories.Secondary.args }], + orientation: 'horizontal', + }} +/> +``` + +```js filename="ButtonGroup.stories.js" renderer="svelte" language="js" tabTitle="CSF" import ButtonGroup from '../ButtonGroup.svelte'; //👇 Imports the Button stories @@ -178,7 +201,30 @@ export const Pair = { }; ``` -```ts filename="ButtonGroup.stories.ts" renderer="svelte" language="ts-4-9" +```svelte filename="ButtonGroup.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import ButtonGroup from './ButtonGroup.svelte'; + + //👇 Imports the Button stories + import * as ButtonStories from './Button.stories.svelte'; + + const { Story } = defineMeta({ + component: ButtonGroup, + }); +</script> + +<Story + name="Pair" + args={{ + buttons: [{ ...ButtonStories.Primary.args }, { ...ButtonStories.Secondary.args }], + orientation: 'horizontal', + }} +/> +``` + +```ts filename="ButtonGroup.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import ButtonGroup from './ButtonGroup.svelte'; @@ -201,7 +247,30 @@ export const Pair: Story = { }; ``` -```ts filename="ButtonGroup.stories.ts" renderer="svelte" language="ts" +```svelte filename="ButtonGroup.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import ButtonGroup from './ButtonGroup.svelte'; + + //👇 Imports the Button stories + import * as ButtonStories from './Button.stories.svelte'; + + const { Story } = defineMeta({ + component: ButtonGroup, + }); +</script> + +<Story + name="Pair" + args={{ + buttons: [{ ...ButtonStories.Primary.args }, { ...ButtonStories.Secondary.args }], + orientation: 'horizontal', + }} +/> +``` + +```ts filename="ButtonGroup.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import ButtonGroup from './ButtonGroup.svelte'; @@ -224,7 +293,7 @@ export const Pair: Story = { }; ``` -```js filename="ButtonGroup.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="ButtonGroup.stories.js" renderer="vue" language="js" import ButtonGroup from './ButtonGroup.vue'; //👇 Imports the Button stories @@ -254,7 +323,7 @@ export const Pair = { }; ``` -```ts filename="ButtonGroup.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="ButtonGroup.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import ButtonGroup from './ButtonGroup.vue'; @@ -284,7 +353,7 @@ export const Pair: Story = { }; ``` -```ts filename="ButtonGroup.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="ButtonGroup.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import ButtonGroup from './ButtonGroup.vue'; @@ -350,4 +419,3 @@ export const Pair: Story = { }, }; ``` - diff --git a/docs/_snippets/button-implementation.md b/docs/_snippets/button-implementation.md index 333017bf79dd..9e9c3ee4cc70 100644 --- a/docs/_snippets/button-implementation.md +++ b/docs/_snippets/button-implementation.md @@ -114,9 +114,7 @@ export const Button: React.FC<ButtonProps> = ({ }; ``` -```html renderer="svelte" language="js" -{/* Button.svelte */} - +```svelte filename="Button.svelte" renderer="svelte" language="js" <script> import { createEventDispatcher } from 'svelte'; /** @@ -152,12 +150,8 @@ export const Button: React.FC<ButtonProps> = ({ <button type="button" {style} on:click="{onClick}">{label}</button> ``` -```html renderer="vue" language="js" tabTitle="3" -{/* Button.vue */} - -<template> - {/* the component markup implementation */} -</template> +```html filename="Button.vue" renderer="vue" language="js" +<template> <!-- The component markup implementation --> </template> <script> export default { @@ -210,12 +204,8 @@ export const Button: React.FC<ButtonProps> = ({ </script> ``` -```html renderer="vue" language="ts" tabTitle="3" -{/* Button.vue */} - -<template> - {/* the component markup implementation */} -</template> +```html filename="Button.vue" renderer="vue" language="ts" +<template> <!-- The component markup implementation --> </template> <script lang="ts"> import { defineComponent, reactive } from 'vue'; @@ -270,4 +260,3 @@ export const Button: React.FC<ButtonProps> = ({ }); </script> ``` - diff --git a/docs/_snippets/button-story-action-event-handle.md b/docs/_snippets/button-story-action-event-handle.md index 32c31b10ffdb..a574de6e82b6 100644 --- a/docs/_snippets/button-story-action-event-handle.md +++ b/docs/_snippets/button-story-action-event-handle.md @@ -106,4 +106,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/button-story-argtypes-with-categories.md b/docs/_snippets/button-story-argtypes-with-categories.md index d4b36cbb7d9a..b1278748f55d 100644 --- a/docs/_snippets/button-story-argtypes-with-categories.md +++ b/docs/_snippets/button-story-argtypes-with-categories.md @@ -251,4 +251,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/button-story-baseline-with-satisfies-story-level.md b/docs/_snippets/button-story-baseline-with-satisfies-story-level.md index 61da26569ef2..d95245125c81 100644 --- a/docs/_snippets/button-story-baseline-with-satisfies-story-level.md +++ b/docs/_snippets/button-story-baseline-with-satisfies-story-level.md @@ -18,4 +18,3 @@ export const Example = { }, } satisfies Story; ``` - diff --git a/docs/_snippets/button-story-baseline-with-satisfies.md b/docs/_snippets/button-story-baseline-with-satisfies.md index 5ac57b99484f..c1cfe8ddec81 100644 --- a/docs/_snippets/button-story-baseline-with-satisfies.md +++ b/docs/_snippets/button-story-baseline-with-satisfies.md @@ -10,4 +10,3 @@ const meta = { export default meta; ``` - diff --git a/docs/_snippets/button-story-click-handler-args.md b/docs/_snippets/button-story-click-handler-args.md index 03f55f914183..1feaa43722d1 100644 --- a/docs/_snippets/button-story-click-handler-args.md +++ b/docs/_snippets/button-story-click-handler-args.md @@ -245,7 +245,7 @@ export const Text: Story = { }; ``` -```js filename="Button.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="Button.stories.js" renderer="vue" language="js" import Button from './Button.vue'; import { action } from '@storybook/addon-actions'; @@ -271,7 +271,7 @@ export const Text = { }; ``` -```ts filename="Button.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="Button.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -302,7 +302,7 @@ export const Primary: Story = { }; ``` -```ts filename="Button.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="Button.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -374,4 +374,3 @@ export const Text: Story = { }, }; ``` - diff --git a/docs/_snippets/button-story-click-handler-simple-docs.md b/docs/_snippets/button-story-click-handler-simple-docs.md deleted file mode 100644 index 20dfff72f628..000000000000 --- a/docs/_snippets/button-story-click-handler-simple-docs.md +++ /dev/null @@ -1,14 +0,0 @@ -```js filename="Button.stories.js|jsx" renderer="react" language="js" -import { action } from '@storybook/addon-actions'; - -import { Button } from './Button'; - -export default { - component: Button, -}; - -export const Text = { - render: ({ label, onClick }) => <Button label={label} onClick={onClick} />, -}; -``` - diff --git a/docs/_snippets/button-story-click-handler-simplificated.md b/docs/_snippets/button-story-click-handler-simplificated.md index 7c15bd02541b..983d07c5a843 100644 --- a/docs/_snippets/button-story-click-handler-simplificated.md +++ b/docs/_snippets/button-story-click-handler-simplificated.md @@ -119,28 +119,6 @@ export const Text = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* Button.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; - import Button from './Button.svelte'; -</script> - -{/* - See https://storybook.js.org/docs/essentials/actions#action-argtype-annotation - to learn how to set up argTypes for actions -*/} - -<Meta title="Button" component={Button} argTypes={{ onClick: { action: "onClick" }, }} /> - -<template let:args> - <button {...args} on:click="{args.onClick}" /> -</template> - -<Story name="Text" args={{ label: 'Hello' }}/> -``` - ```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/svelte'; @@ -262,4 +240,3 @@ export const Text: Story = { args: {}, }; ``` - diff --git a/docs/_snippets/button-story-click-handler.md b/docs/_snippets/button-story-click-handler.md index c9b2e1a206d1..72ceb73b21c7 100644 --- a/docs/_snippets/button-story-click-handler.md +++ b/docs/_snippets/button-story-click-handler.md @@ -149,22 +149,6 @@ export const Text = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* Button.stories.svelte */} - -<script> - import { Meta, Story } from '@storybook/addon-svelte-csf'; - - import { action } from '@storybook/addon-actions'; - - import Button from './Button.svelte'; -</script> - -<meta title="Button" component="{Button}" /> - -<Story name="Text"> <Button text="Hello" on:click={action('clicked')}/> </Story> -``` - ```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/svelte'; import { action } from '@storybook/addon-actions'; @@ -216,7 +200,7 @@ export const Text: Story = { }; ``` -```js filename="Button.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="Button.stories.js" renderer="vue" language="js" import Button from './Button.vue'; import { action } from '@storybook/addon-actions'; @@ -238,7 +222,7 @@ export const Text = { }; ``` -```ts filename="Button.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="Button.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -265,7 +249,7 @@ export const Text: Story = { }; ``` -```ts filename="Button.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="Button.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -323,4 +307,3 @@ export const Text: Story = { render: () => html`<custom-button label="Hello" @click=${action('clicked')}></custom-button>`, }; ``` - diff --git a/docs/_snippets/button-story-component-args-primary.md b/docs/_snippets/button-story-component-args-primary.md index 81b292e7a885..16519e18cd48 100644 --- a/docs/_snippets/button-story-component-args-primary.md +++ b/docs/_snippets/button-story-component-args-primary.md @@ -52,7 +52,6 @@ const meta = { } satisfies Meta<typeof Button>; export default meta; -type Story = StoryObj<typeof meta>; ``` ```ts filename="Button.stories.ts|tsx" renderer="react" language="ts" @@ -93,7 +92,7 @@ export default { ``` ```tsx filename="Button.stories.ts|tsx" renderer="solid" language="ts-4-9" -import type { Meta, StoryObj } from 'storybook-solidjs'; +import type { Meta } from 'storybook-solidjs'; import { Button } from './Button'; @@ -110,7 +109,6 @@ const meta = { } satisfies Meta<typeof Button>; export default meta; -type Story = StoryObj<typeof meta>; ``` ```tsx filename="Button.stories.ts|tsx" renderer="solid" language="ts" @@ -134,7 +132,27 @@ export default meta; type Story = StoryObj<typeof Button>; ``` -```js filename="Button.stories.js" renderer="svelte" language="js" +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + //👇 Creates specific argTypes + argTypes: { + backgroundColor: { control: 'color' }, + }, + args: { + //👇 Now all Button stories will be primary. + primary: true, + }, + }); +</script> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" import Button from './Button.svelte'; export default { @@ -150,19 +168,27 @@ export default { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* Button.stories.svelte */} - -<script> - import { Meta } from '@storybook/addon-svelte-csf'; +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import Button from './Button.svelte'; -</script> -<Meta title="Button" component={Button} args={{ primary: true, }} /> + const { Story } = defineMeta({ + component: Button, + //👇 Creates specific argTypes + argTypes: { + backgroundColor: { control: 'color' }, + }, + args: { + //👇 Now all Button stories will be primary. + primary: true, + }, + }); +</script> ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -182,7 +208,27 @@ const meta = { export default meta; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + //👇 Creates specific argTypes + argTypes: { + backgroundColor: { control: 'color' }, + }, + args: { + //👇 Now all Button stories will be primary. + primary: true, + }, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -289,4 +335,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/button-story-component-decorator.md b/docs/_snippets/button-story-component-decorator.md index a50f6e1e6034..85ef46ff097f 100644 --- a/docs/_snippets/button-story-component-decorator.md +++ b/docs/_snippets/button-story-component-decorator.md @@ -190,7 +190,21 @@ const meta: Meta<typeof Button> = { export default meta; ``` -```js filename="Button.stories.js" renderer="svelte" language="js" +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + import MarginDecorator from './MarginDecorator.svelte'; + + const { Story } = defineMeta({ + component: Button, + decorators: [() => MarginDecorator], + }); +</script> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" import Button from './Button.svelte'; import MarginDecorator from './MarginDecorator.svelte'; @@ -200,27 +214,21 @@ export default { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* Button.stories.svelte */} - -<script> - import { Meta, Template } from '@storybook/addon-svelte-csf'; +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + import Button from './Button.svelte'; import MarginDecorator from './MarginDecorator.svelte'; - import Button from './Button.svelte'; + const { Story } = defineMeta({ + component: Button, + decorators: [() => MarginDecorator], + }); </script> - -<meta title="Button" component="{Button}" /> - -<template let:args> - <MarginDecorator> - {/*👇 Your component here */} - </MarginDecorator> -</template> ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -229,12 +237,26 @@ import MarginDecorator from './MarginDecorator.svelte'; const meta = { component: Button, decorators: [() => MarginDecorator], -}; +} satisfies Meta<typeof Button>; export default meta; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + import MarginDecorator from './MarginDecorator.svelte'; + + const { Story } = defineMeta({ + component: Button, + decorators: [() => MarginDecorator], + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -309,4 +331,3 @@ type Story = StoryObj; export const Example: Story = {}; ``` - diff --git a/docs/_snippets/button-story-controls-primary-variant.md b/docs/_snippets/button-story-controls-primary-variant.md index c3b6dc562ca1..bec2cf1b1044 100644 --- a/docs/_snippets/button-story-controls-primary-variant.md +++ b/docs/_snippets/button-story-controls-primary-variant.md @@ -17,6 +17,34 @@ export const Primary: Story = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story name="Primary" args={{ variant: 'primary' }} /> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, +}; + +export const Primary = { + args: { + variant: 'primary', + }, +}; +``` + ```js filename="Button.stories.js|jsx" renderer="common" language="js" import { Button } from './Button'; @@ -31,6 +59,39 @@ export const Primary = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story name="Primary" args={{ variant: 'primary' }} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, +} satisfies Meta<typeof Button>; + +export default meta; +type Story = StoryObj<typeof meta>; + +export const Primary: Story = { + args: { + variant: 'primary', + }, +}; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -51,6 +112,39 @@ export const Primary: Story = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story name="Primary" args={{ variant: 'primary' }} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, +}; + +export default meta; +type Story = StoryObj<typeof Button>; + +export const Primary: Story = { + args: { + variant: 'primary', + }, +}; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -99,4 +193,3 @@ export const Primary: Story = { }, }; ``` - diff --git a/docs/_snippets/button-story-controls-radio-group.md b/docs/_snippets/button-story-controls-radio-group.md index 7a548bee60a4..19a3386680f4 100644 --- a/docs/_snippets/button-story-controls-radio-group.md +++ b/docs/_snippets/button-story-controls-radio-group.md @@ -16,6 +16,38 @@ const meta: Meta<Button> = { export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + variant: { + options: ['primary', 'secondary'], + control: { type: 'radio' }, + }, + }, + }); +</script> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, + argTypes: { + variant: { + options: ['primary', 'secondary'], + control: { type: 'radio' }, + }, + }, +}; +``` + ```js filename="Button.stories.js|jsx" renderer="common" language="js" import { Button } from './Button'; @@ -30,6 +62,42 @@ export default { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + variant: { + options: ['primary', 'secondary'], + control: { type: 'radio' }, + }, + }, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, + argTypes: { + variant: { + options: ['primary', 'secondary'], + control: { type: 'radio' }, + }, + }, +} satisfies Meta<typeof Button>; + +export default meta; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -49,6 +117,42 @@ const meta = { export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + variant: { + options: ['primary', 'secondary'], + control: { type: 'radio' }, + }, + }, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, + argTypes: { + variant: { + options: ['primary', 'secondary'], + control: { type: 'radio' }, + }, + }, +}; + +export default meta; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -95,4 +199,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/button-story-decorator.md b/docs/_snippets/button-story-decorator.md index e0611b5e6458..e53848edf6fa 100644 --- a/docs/_snippets/button-story-decorator.md +++ b/docs/_snippets/button-story-decorator.md @@ -159,7 +159,27 @@ export const Primary: Story = { }; ``` -```js filename="Button.stories.js" renderer="svelte" language="js" +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + import MarginDecorator from './MarginDecorator.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story + name="Primary" + decorators={[ + () => MarginDecorator + ]} +/> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" import Button from './Button.svelte'; import MarginDecorator from './MarginDecorator.svelte'; @@ -172,7 +192,27 @@ export const Primary = { }; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + import MarginDecorator from './MarginDecorator.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story + name="Primary" + decorators={[ + () => MarginDecorator + ]} +/> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -190,7 +230,27 @@ export const Primary: Story = { }; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + import MarginDecorator from './MarginDecorator.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story + name="Primary" + decorators={[ + () => MarginDecorator + ]} +/> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -307,4 +367,3 @@ export const Primary: Story = { decorators: [(story) => html`<div style="margin: 3em">${story()}</div>`], }; ``` - diff --git a/docs/_snippets/button-story-default-docs-code.md b/docs/_snippets/button-story-default-docs-code.md deleted file mode 100644 index 65c72cab6b18..000000000000 --- a/docs/_snippets/button-story-default-docs-code.md +++ /dev/null @@ -1,67 +0,0 @@ -```js filename="Button.stories.js" renderer="svelte" language="js" -import Button from './Button.svelte'; - -export default { - /* 👇 The title prop is optional. - * See https://storybook.js.org/docs/configure/#configure-story-loading - * to learn how to generate automatic titles - */ - title: 'Button', - component: Button, - //👇 Creates specific argTypes - argTypes: { - backgroundColor: { control: 'color' }, - }, -}; - -//👇 Some function to demonstrate the behavior -const someFunction = (someValue) => { - return `i am a ${someValue}`; -}; - -export const ExampleStory = (args) => { - //👇 Destructure the label from the args object - const { label } = args; - - //👇 Assigns the function result to a variable and pass it as a prop into the component - const functionResult = someFunction(label); - return { - Component: Button, - props: { - ...args, - label: functionResult, - }, - }; -}; -ExampleStory.args = { - primary: true, - size: 'small', - label: 'button', -}; -``` - -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* Button.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; - - import Button from './Button.svelte'; - - //👇 Some function to demonstrate the behavior - function someFunction(someValue) { - return `i am a ${someValue}`; - } -</script> - -{/*👇 Creates specific argTypes */} -<Meta title="Button" component={Button} argTypes={{ backgroundColor: { control: 'color' }, }} /> - -{/* 👇 Assigns the function result to a variable and pass it as a prop into the component */} -<template let:args> - <button {...args} label="{someFunction(args.label)}" /> -</template> - -<Story name="ExampleStory" args={{ primary: true, size:'small', label: 'Button', }} /> -``` - diff --git a/docs/_snippets/button-story-default-export-with-component.md b/docs/_snippets/button-story-default-export-with-component.md index 11b2d8aa7039..e4e58c13a619 100644 --- a/docs/_snippets/button-story-default-export-with-component.md +++ b/docs/_snippets/button-story-default-export-with-component.md @@ -88,7 +88,19 @@ const meta: Meta<typeof Button> = { export default meta; ``` -```js filename="Button.stories.js" renderer="svelte" language="js" +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" import Button from './Button.svelte'; export default { @@ -96,7 +108,19 @@ export default { }; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -108,7 +132,19 @@ const meta = { export default meta; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -168,4 +204,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/button-story-default-export.md b/docs/_snippets/button-story-default-export.md index cfd0cbae6bc0..1cf14b769a66 100644 --- a/docs/_snippets/button-story-default-export.md +++ b/docs/_snippets/button-story-default-export.md @@ -109,4 +109,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/button-story-disable-addon.md b/docs/_snippets/button-story-disable-addon.md index a147b623f617..41ceff477219 100644 --- a/docs/_snippets/button-story-disable-addon.md +++ b/docs/_snippets/button-story-disable-addon.md @@ -92,4 +92,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/button-story-grouped.md b/docs/_snippets/button-story-grouped.md index ff931669c2de..0ff8b0086931 100644 --- a/docs/_snippets/button-story-grouped.md +++ b/docs/_snippets/button-story-grouped.md @@ -81,4 +81,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/button-story-hoisted.md b/docs/_snippets/button-story-hoisted.md index 8072369576e5..8d61bb1f0990 100644 --- a/docs/_snippets/button-story-hoisted.md +++ b/docs/_snippets/button-story-hoisted.md @@ -103,4 +103,3 @@ type Story = StoryObj; // This is the only named export in the file, and it matches the component name export const Button: Story = {}; ``` - diff --git a/docs/_snippets/button-story-hypothetical-example.md b/docs/_snippets/button-story-hypothetical-example.md index 055e451d8eb6..ed974f40b2c4 100644 --- a/docs/_snippets/button-story-hypothetical-example.md +++ b/docs/_snippets/button-story-hypothetical-example.md @@ -60,4 +60,3 @@ export const Sample: Story = { }), }; ``` - diff --git a/docs/_snippets/button-story-matching-argtypes.md b/docs/_snippets/button-story-matching-argtypes.md index f1f373ba323d..080f78c84e77 100644 --- a/docs/_snippets/button-story-matching-argtypes.md +++ b/docs/_snippets/button-story-matching-argtypes.md @@ -65,4 +65,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/button-story-onclick-action-spy.md b/docs/_snippets/button-story-onclick-action-spy.md index 67e85c1e778c..d868c21456ea 100644 --- a/docs/_snippets/button-story-onclick-action-spy.md +++ b/docs/_snippets/button-story-onclick-action-spy.md @@ -55,4 +55,3 @@ const meta: Meta<typeof Button> = { export default meta; ``` - diff --git a/docs/_snippets/button-story-primary-composition.md b/docs/_snippets/button-story-primary-composition.md index 15a9897a0427..f04787b86ae4 100644 --- a/docs/_snippets/button-story-primary-composition.md +++ b/docs/_snippets/button-story-primary-composition.md @@ -25,6 +25,49 @@ export const Secondary: Story = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); + + const primaryArgs = { + primary: true, + label: 'Button', + } +</script> + +<Story name="Primary" args={primaryArgs} /> + +<Story name="Secondary" args={{...primaryArgs, primary: false}} /> +``` + +```js filename="Button.stories.js|jsx" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, +}; + +export const Primary = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary = { + args: { + ...Primary.args, + primary: false, + }, +}; +``` + ```js filename="Button.stories.js|jsx" renderer="common" language="js" import { Button } from './Button'; @@ -47,6 +90,54 @@ export const Secondary = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); + + const primaryArgs = { + primary: true, + label: 'Button', + } +</script> + +<Story name="Primary" args={primaryArgs} /> + +<Story name="Secondary" args={{...primaryArgs, primary: false}} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, +} satisfies Meta<typeof Button>; + +export default meta; +type Story = StoryObj<typeof meta>; + +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary: Story = { + args: { + ...Primary.args, + primary: false, + }, +}; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -75,6 +166,54 @@ export const Secondary: Story = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); + + const primaryArgs = { + primary: true, + label: 'Button', + } +</script> + +<Story name="Primary" args={primaryArgs} /> + +<Story name="Secondary" args={{...primaryArgs, primary: false}} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, +}; + +export default meta; +type Story = StoryObj<typeof Button>; + +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary: Story = { + args: { + ...Primary.args, + primary: false, + }, +}; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -147,4 +286,3 @@ export const Secondary: Story = { }, }; ``` - diff --git a/docs/_snippets/button-story-primary-long-name.md b/docs/_snippets/button-story-primary-long-name.md index 0bf7d82e78d1..ae477a342a28 100644 --- a/docs/_snippets/button-story-primary-long-name.md +++ b/docs/_snippets/button-story-primary-long-name.md @@ -25,6 +25,53 @@ export const PrimaryLongName: Story = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); + + const primaryArgs = { + primary: true, + label: 'Button', + } +</script> + +<Story name="Primary" args={primaryArgs} /> + +<Story name="PrimaryLongName" + args={{ + ...primaryArgs, + label: 'Primary with a really long name' + }} /> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, +}; + +export const Primary = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const PrimaryLongName = { + args: { + ...Primary.args, + label: 'Primary with a really long name', + }, +}; +``` + ```js filename="Button.stories.js|jsx" renderer="common" language="js" import { Button } from './Button'; @@ -47,6 +94,58 @@ export const PrimaryLongName = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); + + const primaryArgs = { + primary: true, + label: 'Button', + } +</script> + +<Story name="Primary" args={primaryArgs} /> + +<Story name="PrimaryLongName" + args={{ + ...primaryArgs, + label: 'Primary with a really long name' + }} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, +} satisfies Meta<typeof Button>; + +export default meta; +type Story = StoryObj<typeof meta>; + +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const PrimaryLongName: Story = { + args: { + ...Primary.args, + label: 'Primary with a really long name', + }, +}; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -75,6 +174,58 @@ export const PrimaryLongName: Story = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); + + const primaryArgs = { + primary: true, + label: 'Button', + } +</script> + +<Story name="Primary" args={primaryArgs} /> + +<Story name="PrimaryLongName" + args={{ + ...primaryArgs, + label: 'Primary with a really long name' + }} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, +}; + +export default meta; +type Story = StoryObj<typeof Button>; + +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const PrimaryLongName: Story = { + args: { + ...Primary.args, + label: 'Primary with a really long name', + }, +}; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -147,4 +298,3 @@ export const PrimaryLongName: Story = { }, }; ``` - diff --git a/docs/_snippets/button-story-rename-story.md b/docs/_snippets/button-story-rename-story.md index 23e6f25a0918..e1c114962351 100644 --- a/docs/_snippets/button-story-rename-story.md +++ b/docs/_snippets/button-story-rename-story.md @@ -188,7 +188,7 @@ export default { component: Button, }; -export const Primary = ({ +export const Primary = { // 👇 Rename this story name: 'I am the primary', args: { @@ -210,7 +210,7 @@ const meta = { export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = ({ +export const Primary: Story = { // 👇 Rename this story name: 'I am the primary', args: { @@ -232,7 +232,7 @@ const meta: Meta<typeof Button> = { export default meta; type Story = StoryObj<typeof meta>; -export const Primary: Story = ({ +export const Primary: Story = { // 👇 Rename this story name: 'I am the primary', args: { @@ -337,4 +337,3 @@ export const Primary: Story = { }, }; ``` - diff --git a/docs/_snippets/button-story-using-args.md b/docs/_snippets/button-story-using-args.md index aa8610f4d991..848448d8a6cd 100644 --- a/docs/_snippets/button-story-using-args.md +++ b/docs/_snippets/button-story-using-args.md @@ -12,8 +12,8 @@ type Story = StoryObj<Button>; export const Primary: Story = { args: { - label: 'Button', backgroundColor: '#ff0', + label: 'Button', }, }; @@ -51,7 +51,7 @@ export default { export const Primary = { render: (args) => createButton(args), args: { - primary: true, + backgroundColor: '#ff0', label: 'Button', }, }; @@ -96,7 +96,7 @@ type Story = StoryObj<ButtonArgs>; export const Primary: Story = { render: (args) => createButton(args), args: { - primary: true, + backgroundColor: '#ff0', label: 'Button', }, }; @@ -312,7 +312,43 @@ export const Tertiary: Story = { }; ``` -```js filename="Button.stories.js" renderer="svelte" language="js" +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story + name="Primary" + args={{ + backgroundColor: '#ff0', + label: 'Button', + }} +/> + +<Story + name="Secondary" + args={{ + backgroundColor: '#ff0', + label: '😄👍😍💯', + }} +/> + +<Story + name="Tertiary" + args={{ + backgroundColor:'#ff0', + label: '📚📕📈🤓', + }} +/> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" import Button from './Button.svelte'; export default { @@ -341,35 +377,47 @@ export const Tertiary = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* Button.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); </script> -<Meta title="Button" component={Button} argTypes={{ label: { control: 'text' }, primary: { control: -'boolean' }, }} /> +<Story + name="Primary" + args={{ + backgroundColor: '#ff0', + label: 'Button', + }} +/> -{/* 👇 We create a “template” of how args map to rendering */} -<template let:args> - <button {...args} /> -</template> +<Story + name="Secondary" + args={{ + backgroundColor: '#ff0', + label: '😄👍😍💯', + }} +/> -{/* 👇 Each story then reuses that template */} -<Story name="Primary" args={{ background: '#ff0', label: 'Button' }} /> <Story name="Secondary" -args={{ background: '#ff0', label: '😄👍😍💯' }} /> <Story name="Tertiary" args={{ background: -'#ff0', label: '📚📕📈🤓' }} /> +<Story + name="Tertiary" + args={{ + backgroundColor:'#ff0', + label: '📚📕📈🤓', + }} +/> ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; -//👇This default export determines where your story goes in the story list const meta = { component: Button, } satisfies Meta<typeof Button>; @@ -399,12 +447,47 @@ export const Tertiary: Story = { }; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story + name="Primary" + args={{ + backgroundColor: '#ff0', + label: 'Button', + }} +/> + +<Story + name="Secondary" + args={{ + backgroundColor: '#ff0', + label: '😄👍😍💯', + }} +/> + +<Story + name="Tertiary" + args={{ + backgroundColor:'#ff0', + label: '📚📕📈🤓', + }} +/> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; -//👇This default export determines where your story goes in the story list const meta: Meta<typeof Button> = { component: Button, }; @@ -434,7 +517,7 @@ export const Tertiary: Story = { }; ``` -```js filename="Button.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="Button.stories.js" renderer="vue" language="js" import Button from './Button.vue'; export default { @@ -489,7 +572,7 @@ export const Tertiary = { }; ``` -```ts filename="Button.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="Button.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -549,7 +632,7 @@ export const Tertiary: Story = { }; ``` -```ts filename="Button.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="Button.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -575,7 +658,7 @@ export const Primary: Story = { template: '<Button v-bind="args" />', }), args: { - background: '#ff0', + backgroundColor: '#ff0', label: 'Button', }, }; @@ -616,7 +699,7 @@ export default { export const Primary = { args: { - background: '#ff0', + backgroundColor: '#ff0', label: 'Button', }, }; @@ -648,7 +731,7 @@ type Story = StoryObj; export const Primary: Story = { args: { - background: '#ff0', + backgroundColor: '#ff0', label: 'Button', }, }; @@ -667,4 +750,3 @@ export const Tertiary: Story = { }, }; ``` - diff --git a/docs/_snippets/button-story-with-addon-example.md b/docs/_snippets/button-story-with-addon-example.md index 211a987fcbec..352ed0817f75 100644 --- a/docs/_snippets/button-story-with-addon-example.md +++ b/docs/_snippets/button-story-with-addon-example.md @@ -213,7 +213,31 @@ export const Basic: Story = { }; ``` -```js filename="Button.stories.js" renderer="svelte" language="js" +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + /* 👇 The title prop is optional. + * See https://storybook.js.org/docs/configure/#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'Button', + component: Button, + parameters: { + myAddon: { + data: 'This data is passed to the addon', + }, + }, + }); +</script> + +<Story name="Basic"/> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" import Button from './Button.svelte'; export default { @@ -234,24 +258,31 @@ export default { export const Basic = {}; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* Button.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import Button from './Button.svelte'; -</script> -<Meta title="Button" component={Button} parameters={{ myAddon: { data: 'this data is passed to the -addon', }, }} /> + const { Story } = defineMeta({ + /* 👇 The title prop is optional. + * See https://storybook.js.org/docs/configure/#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'Button', + component: Button, + parameters: { + myAddon: { + data: 'This data is passed to the addon', + }, + }, + }); +</script> -<template let:args> - <button {...args} /> -</template> +<Story name="Basic"/> ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -277,7 +308,31 @@ type Story = StoryObj<typeof meta>; export const Basic: Story = {}; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + /* 👇 The title prop is optional. + * See https://storybook.js.org/docs/configure/#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'Button', + component: Button, + parameters: { + myAddon: { + data: 'This data is passed to the addon', + }, + }, + }); +</script> + +<Story name="Basic"/> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -453,4 +508,3 @@ export const Basic: Story = { render: () => html`<custom-button label="Hello"></custom-button>`, }; ``` - diff --git a/docs/_snippets/button-story-with-args.md b/docs/_snippets/button-story-with-args.md index 2c0e9701c35f..3ff2014ecd91 100644 --- a/docs/_snippets/button-story-with-args.md +++ b/docs/_snippets/button-story-with-args.md @@ -224,7 +224,27 @@ export const Primary: Story = { }; ``` -```js filename="Button.stories.js" renderer="svelte" language="js" +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story + name="Primary" + args={{ + primary: true, + label: 'Button' + }} +/> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" import Button from './Button.svelte'; export default { @@ -239,30 +259,27 @@ export const Primary = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* Button.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import Button from './Button.svelte'; -</script> - -<Meta title="Button" component={Button} argTypes={{ label: { control: 'text' }, primary: { control: -'boolean' }, }} /> - -{/*👇 We create a “template” of how args map to rendering */} -<template let:args> - <button {...args} /> -</template> - -{/* 👇 Each story then reuses that template */} + const { Story } = defineMeta({ + component: Button, + }); +</script> -<Story name='Primary' args={{ primary: true, label: 'Button' }} /> +<Story + name="Primary" + args={{ + primary: true, + label: 'Button' + }} +/> ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -282,7 +299,27 @@ export const Primary: Story = { }; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story + name="Primary" + args={{ + primary: true, + label: 'Button' + }} +/> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -302,7 +339,7 @@ export const Primary: Story = { }; ``` -```js filename="Button.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="Button.stories.js" renderer="vue" language="js" import Button from './Button.vue'; export default { @@ -329,7 +366,7 @@ export const Primary = { }; ``` -```ts filename="Button.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="Button.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -361,7 +398,7 @@ export const Primary: Story = { }; ``` -```ts filename="Button.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="Button.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -423,4 +460,3 @@ export const Primary: Story = { }, }; ``` - diff --git a/docs/_snippets/button-story-with-emojis.md b/docs/_snippets/button-story-with-emojis.md index f59e8067860f..0588748d9039 100644 --- a/docs/_snippets/button-story-with-emojis.md +++ b/docs/_snippets/button-story-with-emojis.md @@ -275,7 +275,31 @@ export const Tertiary: Story = { }; ``` -```js filename="Button.stories.js" renderer="svelte" language="js" +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story name="Primary"> + <Button backgroundColor="#ff0" label="Button" /> +</Story> + +<Story name="Secondary"> + <Button backgroundColor="#ff0" label="😄👍😍💯" /> +</Story> + +<Story name="Tertiary"> + <Button backgroundColor="#ff0" label="📚📕📈🤓" /> +</Story> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" import Button from './Button.svelte'; export default { @@ -318,29 +342,31 @@ export const Tertiary = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -<script> - import { Meta, Story } from '@storybook/addon-svelte-csf'; +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import Button from './Button.svelte'; -</script> -<meta title="Button" component="{Button}" /> + const { Story } = defineMeta({ + component: Button, + }); +</script> <Story name="Primary"> - <button background="#ff0" label="Button" /> + <Button backgroundColor="#ff0" label="Button" /> </Story> <Story name="Secondary"> - <button background="#ff0" label="😄👍😍💯" /> + <Button backgroundColor="#ff0" label="😄👍😍💯" /> </Story> <Story name="Tertiary"> - <button background="#ff0" label="📚📕📈🤓" /> + <Button backgroundColor="#ff0" label="📚📕📈🤓" /> </Story> ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -388,7 +414,31 @@ export const Tertiary: Story = { }; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story name="Primary"> + <Button backgroundColor="#ff0" label="Button" /> +</Story> + +<Story name="Secondary"> + <Button backgroundColor="#ff0" label="😄👍😍💯" /> +</Story> + +<Story name="Tertiary"> + <Button backgroundColor="#ff0" label="📚📕📈🤓" /> +</Story> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -489,21 +539,21 @@ type Story = StoryObj<typeof Button>; export const Primary: Story = { render: () => ({ components: { Button }, - template: '<Button background="#ff0" label="Button" />', + template: '<Button backgroundColor="#ff0" label="Button" />', }), }; export const Secondary: Story = { render: () => ({ components: { Button }, - template: '<Button background="#ff0" label="😄👍😍💯" />', + template: '<Button backgroundColor="#ff0" label="😄👍😍💯" />', }), }; export const Tertiary: Story = { render: () => ({ components: { Button }, - template: '<Button background="#ff0" label="📚📕📈🤓" />', + template: '<Button backgroundColor="#ff0" label="📚📕📈🤓" />', }), }; ``` @@ -528,21 +578,21 @@ type Story = StoryObj<typeof Button>; export const Primary: Story = { render: () => ({ components: { Button }, - template: '<Button background="#ff0" label="Button" />', + template: '<Button backgroundColor="#ff0" label="Button" />', }), }; export const Secondary: Story = { render: () => ({ components: { Button }, - template: '<Button background="#ff0" label="😄👍😍💯" />', + template: '<Button backgroundColor="#ff0" label="😄👍😍💯" />', }), }; export const Tertiary: Story = { render: () => ({ components: { Button }, - template: '<Button background="#ff0" label="📚📕📈🤓" />', + template: '<Button backgroundColor="#ff0" label="📚📕📈🤓" />', }), }; ``` @@ -560,15 +610,15 @@ export default { * to learn how to use render functions. */ export const Primary = { - render: () => html`<demo-button .background="#ff0" .label="Button"></demo-button>`, + render: () => html`<demo-button .backgroundColor="#ff0" .label="Button"></demo-button>`, }; export const Secondary = { - render: () => html`<demo-button .background="#ff0" .label="😄👍😍💯"></demo-button>`, + render: () => html`<demo-button .backgroundColor="#ff0" .label="😄👍😍💯"></demo-button>`, }; export const Tertiary = { - render: () => html`<demo-button .background="#ff0" .label="📚📕📈🤓"></demo-button>`, + render: () => html`<demo-button .backgroundColor="#ff0" .label="📚📕📈🤓"></demo-button>`, }; ``` @@ -590,15 +640,14 @@ type Story = StoryObj; * to learn how to use render functions. */ export const Primary: Story = { - render: () => html`<demo-button .background="#ff0" .label="Button"></demo-button>`, + render: () => html`<demo-button .backgroundColor="#ff0" .label="Button"></demo-button>`, }; export const Secondary: Story = { - render: () => html`<demo-button .background="#ff0" .label="😄👍😍💯"></demo-button>`, + render: () => html`<demo-button .backgroundColor="#ff0" .label="😄👍😍💯"></demo-button>`, }; export const Tertiary: Story = { - render: () => html`<demo-button .background="#ff0" .label="📚📕📈🤓"></demo-button>`, + render: () => html`<demo-button .backgroundColor="#ff0" .label="📚📕📈🤓"></demo-button>`, }; ``` - diff --git a/docs/_snippets/button-story-with-parameters.md b/docs/_snippets/button-story-with-parameters.md index da16a27e21ff..ee308f651d33 100644 --- a/docs/_snippets/button-story-with-parameters.md +++ b/docs/_snippets/button-story-with-parameters.md @@ -126,4 +126,3 @@ const meta: Meta<typeof Button> = { export default meta; ``` - diff --git a/docs/_snippets/button-story-with-sample.md b/docs/_snippets/button-story-with-sample.md index 5876bf16d4ae..92480d5059a9 100644 --- a/docs/_snippets/button-story-with-sample.md +++ b/docs/_snippets/button-story-with-sample.md @@ -21,4 +21,3 @@ export const Sample = { render: () => <Button label="hello button" />, }; ``` - diff --git a/docs/_snippets/button-story.md b/docs/_snippets/button-story.md index 3b9b10ac020a..fef764603915 100644 --- a/docs/_snippets/button-story.md +++ b/docs/_snippets/button-story.md @@ -449,46 +449,35 @@ export const Primary: Story = { }; ``` -```js filename="Button.stories.js" renderer="svelte" language="js" -import Button from './Button.svelte'; +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; -export default { - component: Button, -}; + import Button from './Button.svelte'; -/* - *👇 Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ -export const Primary = { - render: () => ({ - Component: Button, - props: { - primary: true, - label: 'Button', - }, - }), -}; -``` + const { Story } = defineMeta({ + component: Button, + }); +</script> -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* Button.stories.svelte */} +<Story name="Primary" args={{ primary: true, label: 'Button' }} /> +``` -<script> - import { Meta, Story } from '@storybook/addon-svelte-csf'; +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import Button from './Button.svelte'; -</script> -<meta title="Button" component="{Button}" /> + const { Story } = defineMeta({ + component: Button, + }); +</script> -<Story name="Primary"> - <button primary="true" label="Button" /> -</Story> +<Story name="Primary" args={{ primary: true, label: 'Button' }} /> ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -516,7 +505,21 @@ export const Primary: Story = { }; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<Story name="Primary" args={{ primary: true, label: 'Button' }} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -642,4 +645,3 @@ export const Primary: Story = { render: () => html`<demo-button primary></demo-button>`, }; ``` - diff --git a/docs/_snippets/checkbox-story-csf.md b/docs/_snippets/checkbox-story-csf.md index 579a92497eab..b277479d0b13 100644 --- a/docs/_snippets/checkbox-story-csf.md +++ b/docs/_snippets/checkbox-story-csf.md @@ -17,6 +17,39 @@ export const Unchecked: Story = { }; ``` +```svelte filename="Checkbox.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Checkbox from './Checkbox.svelte'; + + const { Story } = defineMeta({ + component: Checkbox, + }); +</script> + +<Story + name="Unchecked" + args={{ + label: 'Unchecked', + }} +/> +``` + +```js filename="Checkbox.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Checkbox from './Checkbox.svelte'; + +export default { + component: Checkbox, +}; + +export const Unchecked = { + args: { + label: 'Unchecked', + }, +}; +``` + ```js filename="Checkbox.stories.js|jsx" renderer="common" language="js" import { Checkbox } from './Checkbox'; @@ -31,6 +64,44 @@ export const Unchecked = { }; ``` +```svelte filename="Checkbox.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Checkbox from './Checkbox.svelte'; + + const { Story } = defineMeta({ + component: Checkbox, + }); +</script> + +<Story + name="Unchecked" + args={{ + label: 'Unchecked', + }} +/> +``` + +```ts filename="Checkbox.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Checkbox from './Checkbox.svelte'; + +const meta = { + component: Checkbox, +} satisfies Meta<typeof Checkbox>; + +export default meta; +type Story = StoryObj<typeof meta>; + +export const Unchecked: Story = { + args: { + label: 'Unchecked', + }, +}; +``` + ```ts filename="Checkbox.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -51,11 +122,29 @@ export const Unchecked: Story = { }; ``` -```ts filename="Checkbox.stories.ts|tsx" renderer="common" language="ts" -// Replace your-framework with the name of your framework -import type { Meta, StoryObj } from '@storybook/your-framework'; +```svelte filename="Checkbox.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; -import { Checkbox } from './Checkbox'; + import Checkbox from './Checkbox.svelte'; + + const { Story } = defineMeta({ + component: Checkbox, + }); +</script> + +<Story + name="Unchecked" + args={{ + label: 'Unchecked', + }} +/> +``` + +```ts filename="Checkbox.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Checkbox from './Checkbox.svelte'; const meta: Meta<typeof Checkbox> = { component: Checkbox, @@ -71,24 +160,24 @@ export const Unchecked: Story = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* Checkbox.stories.svelte */} +```ts filename="Checkbox.stories.ts|tsx" renderer="common" language="ts" +// Replace your-framework with the name of your framework +import type { Meta, StoryObj } from '@storybook/your-framework'; -<script> - import { Meta, Story } from '@storybook/addon-svelte-csf'; +import { Checkbox } from './Checkbox'; - import Checkbox from './Checkbox.svelte'; -</script> +const meta: Meta<typeof Checkbox> = { + component: Checkbox, +}; -<meta title="MDX/Checkbox" component="{Checkbox}" /> +export default meta; +type Story = StoryObj<typeof Checkbox>; -<Story name="allCheckboxes"> - <form> - <Checkbox id="Unchecked" label="Unchecked" /> - <Checkbox id="Checked" label="Checked" {checked} /> - <Checkbox appearance="secondary" id="second" label="Secondary" {checked} /> - </form> -</Story> +export const Unchecked: Story = { + args: { + label: 'Unchecked', + }, +}; ``` ```js filename="Checkbox.stories.js" renderer="web-components" language="js" @@ -120,4 +209,3 @@ export const Unchecked: Story = { }, }; ``` - diff --git a/docs/_snippets/checkbox-story.md b/docs/_snippets/checkbox-story.md index 6abf4e1c3017..8f34aee9e443 100644 --- a/docs/_snippets/checkbox-story.md +++ b/docs/_snippets/checkbox-story.md @@ -1,6 +1,4 @@ -```mdx renderer="common" language="mdx" -{/* Checkbox.mdx */} - +```mdx filename="Checkbox.mdx" renderer="common" language="mdx" import { Canvas, Meta } from '@storybook/blocks'; import * as CheckboxStories from './Checkbox.stories'; @@ -9,27 +7,41 @@ import * as CheckboxStories from './Checkbox.stories'; # Checkbox -A checkbox is a square box that can be activated or deactivated when ticked. +A checkbox is a square box that can be activated or deactivated when ticked. Use checkboxes to select one or more options from a list of choices. <Canvas of={CheckboxStories.Unchecked} /> -```` +``` -```md renderer="react" language="mdx" -{/* Checkbox.mdx */} +```mdx filename="Checkbox.mdx" renderer="svelte" language="mdx" tabTitle="Svelte CSF" +import { Canvas, Meta } from '@storybook/blocks'; -import { Canvas, Meta, Story } from '@storybook/blocks'; -import * as CheckboxStories from './Checkbox.stories'; +import * as CheckboxStories from './Checkbox.stories.svelte'; <Meta of={CheckboxStories} /> # Checkbox -With `MDX` we can compose Markdown documentation with `Checkbox` stories and interactive controls. +A checkbox is a square box that can be activated or deactivated when ticked. + +Use checkboxes to select one or more options from a list of choices. -<Canvas> - <Story of={CheckboxStories.Unchecked} /> -</Canvas> +<Canvas of={CheckboxStories.Unchecked} /> ``` +```mdx filename="Checkbox.mdx" renderer="svelte" language="mdx" tabTitle="CSF" +import { Canvas, Meta } from '@storybook/blocks'; + +import * as CheckboxStories from './Checkbox.stories'; + +<Meta of={CheckboxStories} /> + +# Checkbox + +A checkbox is a square box that can be activated or deactivated when ticked. + +Use checkboxes to select one or more options from a list of choices. + +<Canvas of={CheckboxStories.Unchecked} /> +``` diff --git a/docs/_snippets/chromatic-github-action.md b/docs/_snippets/chromatic-github-action.md index 47bb6d65d2c9..ab5bb8523cc5 100644 --- a/docs/_snippets/chromatic-github-action.md +++ b/docs/_snippets/chromatic-github-action.md @@ -1,6 +1,4 @@ -```shell renderer="common" language="js" -# .github/workflows/chromatic.yml - +```yml filename=".github/workflows/chromatic.yml" renderer="common" language="js" # Workflow name name: 'Chromatic Publish' @@ -19,15 +17,14 @@ jobs: fetch-depth: 0 - uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 cache: 'yarn' - run: yarn #👇 Adds Chromatic as a step in the workflow - - uses: chromaui/action@v1 + - uses: chromaui/action@latest # Options required for Chromatic's GitHub Action with: #👇 Chromatic projectToken, projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }} ``` - diff --git a/docs/_snippets/chromatic-install.md b/docs/_snippets/chromatic-install.md index f04d6b4c7470..6eaaaab77d1d 100644 --- a/docs/_snippets/chromatic-install.md +++ b/docs/_snippets/chromatic-install.md @@ -2,6 +2,10 @@ npm install chromatic --save-dev ``` +```shell renderer="common" language="js" packageManager="pnpm" +pnpm add --save-dev chromatic +``` + ```shell renderer="common" language="js" packageManager="yarn" yarn add --dev chromatic ``` diff --git a/docs/_snippets/chromatic-storybook-add.md b/docs/_snippets/chromatic-storybook-add.md index aea0b17aa5f5..84756a1ae1b8 100644 --- a/docs/_snippets/chromatic-storybook-add.md +++ b/docs/_snippets/chromatic-storybook-add.md @@ -9,4 +9,3 @@ pnpm dlx storybook@latest add @chromatic-com/storybook ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@latest add @chromatic-com/storybook ``` - diff --git a/docs/_snippets/compodoc-install.md b/docs/_snippets/compodoc-install.md index 2db606064ae7..7319f09a66b4 100644 --- a/docs/_snippets/compodoc-install.md +++ b/docs/_snippets/compodoc-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @compodoc/compodoc ```shell renderer="angular" language="js" packageManager="yarn" yarn add --dev @compodoc/compodoc ``` - diff --git a/docs/_snippets/component-cypress-test.md b/docs/_snippets/component-cypress-test.md index ef5562daf806..3346798edfad 100644 --- a/docs/_snippets/component-cypress-test.md +++ b/docs/_snippets/component-cypress-test.md @@ -13,4 +13,3 @@ describe('Login Form', () => { }); }); ``` - diff --git a/docs/_snippets/component-playwright-test.md b/docs/_snippets/component-playwright-test.md index faa1ce9728c1..91b6705612e7 100644 --- a/docs/_snippets/component-playwright-test.md +++ b/docs/_snippets/component-playwright-test.md @@ -9,4 +9,3 @@ test('Login Form inputs', async ({ page }) => { await expect(password).toBe('a-random-password'); }); ``` - diff --git a/docs/_snippets/component-story-auto-title.md b/docs/_snippets/component-story-auto-title.md index b89bb194b176..92ba228a4f75 100644 --- a/docs/_snippets/component-story-auto-title.md +++ b/docs/_snippets/component-story-auto-title.md @@ -80,4 +80,3 @@ export const Default = { args: { message: 'Hello world!' }, }; ``` - diff --git a/docs/_snippets/component-story-conditional-controls-mutual-exclusion.md b/docs/_snippets/component-story-conditional-controls-mutual-exclusion.md index 41a16c128408..cf09815088d7 100644 --- a/docs/_snippets/component-story-conditional-controls-mutual-exclusion.md +++ b/docs/_snippets/component-story-conditional-controls-mutual-exclusion.md @@ -21,6 +21,48 @@ const meta: Meta<Button> = { export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + // Button can be passed a label or an image, not both + label: { + control: 'text', + if: { arg: 'image', truthy: false }, + }, + image: { + control: { type: 'select', options: ['foo.jpg', 'bar.jpg'] }, + if: { arg: 'label', truthy: false }, + }, + }, + }); +</script> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, + argTypes: { + // Button can be passed a label or an image, not both + label: { + control: 'text', + if: { arg: 'image', truthy: false }, + }, + image: { + control: { type: 'select', options: ['foo.jpg', 'bar.jpg'] }, + if: { arg: 'label', truthy: false }, + }, + }, +}; +``` + ```js filename="Button.stories.js|jsx" renderer="common" language="js" import { Button } from './Button'; @@ -40,6 +82,52 @@ export default { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + // Button can be passed a label or an image, not both + label: { + control: 'text', + if: { arg: 'image', truthy: false }, + }, + image: { + control: { type: 'select', options: ['foo.jpg', 'bar.jpg'] }, + if: { arg: 'label', truthy: false }, + }, + }, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, + argTypes: { + // Button can be passed a label or an image, not both + label: { + control: 'text', + if: { arg: 'image', truthy: false }, + }, + image: { + control: { type: 'select', options: ['foo.jpg', 'bar.jpg'] }, + if: { arg: 'label', truthy: false }, + }, + }, +} satisfies Meta<typeof Button>; + +export default meta; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -64,6 +152,52 @@ const meta = { export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + // Button can be passed a label or an image, not both + label: { + control: 'text', + if: { arg: 'image', truthy: false }, + }, + image: { + control: { type: 'select', options: ['foo.jpg', 'bar.jpg'] }, + if: { arg: 'label', truthy: false }, + }, + }, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, + argTypes: { + // Button can be passed a label or an image, not both + label: { + control: 'text', + if: { arg: 'image', truthy: false }, + }, + image: { + control: { type: 'select', options: ['foo.jpg', 'bar.jpg'] }, + if: { arg: 'label', truthy: false }, + }, + }, +}; + +export default meta; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -125,4 +259,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/component-story-conditional-controls-toggle.md b/docs/_snippets/component-story-conditional-controls-toggle.md index fa14d79829c9..5a5f0ededa8f 100644 --- a/docs/_snippets/component-story-conditional-controls-toggle.md +++ b/docs/_snippets/component-story-conditional-controls-toggle.md @@ -18,6 +18,42 @@ const meta: Meta<Button> = { export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + label: { control: 'text' }, // Always shows the control + advanced: { control: 'boolean' }, + // Only enabled if advanced is true + margin: { control: 'number', if: { arg: 'advanced' } }, + padding: { control: 'number', if: { arg: 'advanced' } }, + cornerRadius: { control: 'number', if: { arg: 'advanced' } }, + }, + }); +</script> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, + argTypes: { + label: { control: 'text' }, // Always shows the control + advanced: { control: 'boolean' }, + // Only enabled if advanced is true + margin: { control: 'number', if: { arg: 'advanced' } }, + padding: { control: 'number', if: { arg: 'advanced' } }, + cornerRadius: { control: 'number', if: { arg: 'advanced' } }, + }, +}; +``` + ```js filename="Button.stories.js|jsx" renderer="common" language="js" import { Button } from './Button'; @@ -34,6 +70,46 @@ export default { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + label: { control: 'text' }, // Always shows the control + advanced: { control: 'boolean' }, + // Only enabled if advanced is true + margin: { control: 'number', if: { arg: 'advanced' } }, + padding: { control: 'number', if: { arg: 'advanced' } }, + cornerRadius: { control: 'number', if: { arg: 'advanced' } }, + }, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, + argTypes: { + label: { control: 'text' }, // Always shows the control + advanced: { control: 'boolean' }, + // Only enabled if advanced is true + margin: { control: 'number', if: { arg: 'advanced' } }, + padding: { control: 'number', if: { arg: 'advanced' } }, + cornerRadius: { control: 'number', if: { arg: 'advanced' } }, + }, +} satisfies Meta<typeof Button>; + +export default meta; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -55,6 +131,46 @@ const meta = { export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + label: { control: 'text' }, // Always shows the control + advanced: { control: 'boolean' }, + // Only enabled if advanced is true + margin: { control: 'number', if: { arg: 'advanced' } }, + padding: { control: 'number', if: { arg: 'advanced' } }, + cornerRadius: { control: 'number', if: { arg: 'advanced' } }, + }, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, + argTypes: { + label: { control: 'text' }, // Always shows the control + advanced: { control: 'boolean' }, + // Only enabled if advanced is true + margin: { control: 'number', if: { arg: 'advanced' } }, + padding: { control: 'number', if: { arg: 'advanced' } }, + cornerRadius: { control: 'number', if: { arg: 'advanced' } }, + }, +}; + +export default meta; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -107,4 +223,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/component-story-custom-args-complex.md b/docs/_snippets/component-story-custom-args-complex.md index f3a5b1793fa6..de88849bca7e 100644 --- a/docs/_snippets/component-story-custom-args-complex.md +++ b/docs/_snippets/component-story-custom-args-complex.md @@ -288,7 +288,46 @@ export const ExampleStory: Story = { }; ``` -```js filename="YourComponent.stories.js" renderer="svelte" language="js" +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + const { Story } = defineMeta({ + component: YourComponent, + //👇 Creates specific argTypes + argTypes: { + propertyA: { + options: ['Item One', 'Item Two', 'Item Three'], + control: { type: 'select' }, // Automatically inferred when 'options' is defined + }, + propertyB: { + options: ['Another Item One', 'Another Item Two', 'Another Item Three'], + }, + }, + }); + + const someFunction = (valuePropertyA, valuePropertyB) => { + // Do some logic here + }; +</script> + +<Story + name="ExampleStory" + args={{ + propertyA: 'Item One', + propertyB: 'Another Item One', + }} +> + {#snippet children(args)} + <YourComponent + {...args} + someProperty={someFunction(args.propertyA, args.propertyB)} + /> + {/snippet} +</Story> +``` + +```js filename="YourComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" import YourComponent from './YourComponent.svelte'; export default { @@ -310,9 +349,9 @@ const someFunction = (valuePropertyA, valuePropertyB) => { }; export const ExampleStory = { - render: ({ propertyA, propertyB }) => { + render: (args) => { //👇 Assigns the function result to a variable - const someFunctionResult = someFunction(propertyA, propertyB); + const someFunctionResult = someFunction(args.propertyA, args.propertyB); return { Component: YourComponent, props: { @@ -328,32 +367,46 @@ export const ExampleStory = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* YourComponent.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; - - import YourComponent from './YourComponent.svelte'; +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + const { Story } = defineMeta({ + component: YourComponent, + //👇 Creates specific argTypes + argTypes: { + propertyA: { + options: ['Item One', 'Item Two', 'Item Three'], + control: { type: 'select' }, // Automatically inferred when 'options' is defined + }, + propertyB: { + options: ['Another Item One', 'Another Item Two', 'Another Item Three'], + }, + }, + }); - //👇 Some function to demonstrate the behavior - function someFunction(valuePropertyA, valuePropertyB) { - // Makes some computations and returns something - } + const someFunction = (valuePropertyA, valuePropertyB) => { + // Do some logic here + }; </script> -{/*👇 Creates specific argTypes and automatically infers them when 'options' is defined */} - -<Meta title="YourComponent" component={YourComponent} argTypes={{ propertyA: { options: ['Item One', -'Item Two', 'Item Three'], control: { type: 'select' }, }, propertyB: { options: ['Another Item -One', 'Another Item Two', 'Another Item Three'], }, }} /> - -<template let:args> - <YourComponent {...args} someProperty="{someFunction(args.propertyA," args.propertyB)} /> -</template> +<Story + name="ExampleStory" + args={{ + propertyA: 'Item One', + propertyB: 'Another Item One', + }} +> + {#snippet children(args)} + <YourComponent + {...args} + someProperty={someFunction(args.propertyA, args.propertyB)} + /> + {/snippet} +</Story> ``` -```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import YourComponent from './YourComponent.svelte'; @@ -380,9 +433,9 @@ const someFunction = (valuePropertyA, valuePropertyB) => { }; export const ExampleStory: Story = { - render: ({ propertyA, propertyB }) => { + render: (args) => { //👇 Assigns the function result to a variable - const someFunctionResult = someFunction(propertyA, propertyB); + const someFunctionResult = someFunction(args.propertyA, args.propertyB); return { Component: YourComponent, props: { @@ -398,7 +451,46 @@ export const ExampleStory: Story = { }; ``` -```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts" +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + const { Story } = defineMeta({ + component: YourComponent, + //👇 Creates specific argTypes + argTypes: { + propertyA: { + options: ['Item One', 'Item Two', 'Item Three'], + control: { type: 'select' }, // Automatically inferred when 'options' is defined + }, + propertyB: { + options: ['Another Item One', 'Another Item Two', 'Another Item Three'], + }, + }, + }); + + const someFunction = (valuePropertyA, valuePropertyB) => { + // Do some logic here + }; +</script> + +<Story + name="ExampleStory" + args={{ + propertyA: 'Item One', + propertyB: 'Another Item One', + }} +> + {#snippet children(args)} + <YourComponent + {...args} + someProperty={someFunction(args.propertyA, args.propertyB)} + /> + {/snippet} +</Story> +``` + +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import YourComponent from './YourComponent.svelte'; @@ -425,9 +517,9 @@ const someFunction = (valuePropertyA, valuePropertyB) => { }; export const ExampleStory: Story = { - render: ({ propertyA, propertyB }) => { + render: (args) => { //👇 Assigns the function result to a variable - const someFunctionResult = someFunction(propertyA, propertyB); + const someFunctionResult = someFunction(args.propertyA, args.propertyB); return { Component: YourComponent, props: { @@ -677,4 +769,3 @@ export const ExampleStory: Story = { }, }; ``` - diff --git a/docs/_snippets/component-story-custom-args-mapping.md b/docs/_snippets/component-story-custom-args-mapping.md index 606e2e82f51d..f6df7d66211b 100644 --- a/docs/_snippets/component-story-custom-args-mapping.md +++ b/docs/_snippets/component-story-custom-args-mapping.md @@ -30,6 +30,66 @@ const meta: Meta<Button> = { export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + import { ArrowUp, ArrowDown, ArrowLeft, ArrowRight } from './icons'; + + const arrows = { ArrowUp, ArrowDown, ArrowLeft, ArrowRight }; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + arrow: { + options: Object.keys(arrows), // An array of serializable values + mapping: arrows, // Maps serializable option values to complex arg values + control: { + type: 'select', // Type 'select' is automatically inferred when 'options' is defined + labels: { + // 'labels' maps option values to string labels + ArrowUp: 'Up', + ArrowDown: 'Down', + ArrowLeft: 'Left', + ArrowRight: 'Right', + }, + }, + }, + }, + }); +</script> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +import { ArrowUp, ArrowDown, ArrowLeft, ArrowRight } from './icons'; + +const arrows = { ArrowUp, ArrowDown, ArrowLeft, ArrowRight }; + +export default { + component: Button, + argTypes: { + arrow: { + options: Object.keys(arrows), // An array of serializable values + mapping: arrows, // Maps serializable option values to complex arg values + control: { + type: 'select', // Type 'select' is automatically inferred when 'options' is defined + labels: { + // 'labels' maps option values to string labels + ArrowUp: 'Up', + ArrowDown: 'Down', + ArrowLeft: 'Left', + ArrowRight: 'Right', + }, + }, + }, + }, +}; +``` + ```js filename="Button.stories.js|jsx" renderer="common" language="js" import { Button } from './Button'; @@ -58,6 +118,70 @@ export default { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + import { ArrowUp, ArrowDown, ArrowLeft, ArrowRight } from './icons'; + + const arrows = { ArrowUp, ArrowDown, ArrowLeft, ArrowRight }; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + arrow: { + options: Object.keys(arrows), // An array of serializable values + mapping: arrows, // Maps serializable option values to complex arg values + control: { + type: 'select', // Type 'select' is automatically inferred when 'options' is defined + labels: { + // 'labels' maps option values to string labels + ArrowUp: 'Up', + ArrowDown: 'Down', + ArrowLeft: 'Left', + ArrowRight: 'Right', + }, + }, + }, + }, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +import { ArrowUp, ArrowDown, ArrowLeft, ArrowRight } from './icons'; + +const arrows = { ArrowUp, ArrowDown, ArrowLeft, ArrowRight }; + +const meta = { + component: Button, + argTypes: { + arrow: { + options: Object.keys(arrows), // An array of serializable values + mapping: arrows, // Maps serializable option values to complex arg values + control: { + type: 'select', // Type 'select' is automatically inferred when 'options' is defined + labels: { + // 'labels' maps option values to string labels + ArrowUp: 'Up', + ArrowDown: 'Down', + ArrowLeft: 'Left', + ArrowRight: 'Right', + }, + }, + }, + }, +} satisfies Meta<typeof Button>; + +export default meta; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -91,6 +215,70 @@ const meta = { export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + import { ArrowUp, ArrowDown, ArrowLeft, ArrowRight } from './icons'; + + const arrows = { ArrowUp, ArrowDown, ArrowLeft, ArrowRight }; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + arrow: { + options: Object.keys(arrows), // An array of serializable values + mapping: arrows, // Maps serializable option values to complex arg values + control: { + type: 'select', // Type 'select' is automatically inferred when 'options' is defined + labels: { + // 'labels' maps option values to string labels + ArrowUp: 'Up', + ArrowDown: 'Down', + ArrowLeft: 'Left', + ArrowRight: 'Right', + }, + }, + }, + }, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +import { ArrowUp, ArrowDown, ArrowLeft, ArrowRight } from './icons'; + +const arrows = { ArrowUp, ArrowDown, ArrowLeft, ArrowRight }; + +const meta: Meta<typeof Button> = { + component: Button, + argTypes: { + arrow: { + options: Object.keys(arrows), // An array of serializable values + mapping: arrows, // Maps serializable option values to complex arg values + control: { + type: 'select', // Type 'select' is automatically inferred when 'options' is defined + labels: { + // 'labels' maps option values to string labels + ArrowUp: 'Up', + ArrowDown: 'Down', + ArrowLeft: 'Left', + ArrowRight: 'Right', + }, + }, + }, + }, +}; + +export default meta; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -179,4 +367,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/component-story-disable-controls-alt.md b/docs/_snippets/component-story-disable-controls-alt.md index 2bec9b308315..b4b593505bcb 100644 --- a/docs/_snippets/component-story-disable-controls-alt.md +++ b/docs/_snippets/component-story-disable-controls-alt.md @@ -16,6 +16,38 @@ const meta: Meta<YourComponent> = { export default meta; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + control: false, + }, + }, + }); +</script> +``` + +```js filename="YourComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import YourComponent from './YourComponent.svelte'; + +export default { + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + control: false, + }, + }, +}; +``` + ```js filename="YourComponent.stories.js|jsx" renderer="common" language="js" import { YourComponent } from './YourComponent'; @@ -30,6 +62,42 @@ export default { }; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + control: false, + }, + }, + }); +</script> +``` + +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import YourComponent from './YourComponent.svelte'; + +const meta = { + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + control: false, + }, + }, +} satisfies Meta<typeof YourComponent>; + +export default meta; +``` + ```ts filename="YourComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -49,6 +117,42 @@ const meta = { export default meta; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + control: false, + }, + }, + }); +</script> +``` + +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import YourComponent from './YourComponent.svelte'; + +const meta: Meta<typeof YourComponent> = { + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + control: false, + }, + }, +}; + +export default meta; +``` + ```ts filename="YourComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -95,4 +199,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/component-story-disable-controls-regex.md b/docs/_snippets/component-story-disable-controls-regex.md index 13c6d4e56d7b..69309e6b7720 100644 --- a/docs/_snippets/component-story-disable-controls-regex.md +++ b/docs/_snippets/component-story-disable-controls-regex.md @@ -35,6 +35,78 @@ export const RegexExclude: Story = { }; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + }); +</script> + +<Story + name="ArrayInclude" + parameters={{ + controls: { include: ['foo', 'bar'] }, + }} +/> + +<Story + name="RegexInclude" + parameters={{ + controls: { include: /^hello*/ }, + }} +/> + +<Story + name="ArrayExclude" + parameters={{ + controls: { exclude: ['foo', 'bar'] }, + }} +/> + +<Story + name="RegexExclude" + parameters={{ + controls: { exclude: /^hello*/ }, + }} +/> +``` + +```js filename="YourComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import YourComponent from './YourComponent.svelte'; + +export default { + component: YourComponent, +}; + +export const ArrayInclude = { + parameters: { + controls: { include: ['foo', 'bar'] }, + }, +}; + +export const RegexInclude = { + parameters: { + controls: { include: /^hello*/ }, + }, +}; + +export const ArrayExclude = { + parameters: { + controls: { exclude: ['foo', 'bar'] }, + }, +}; + +export const RegexExclude = { + parameters: { + controls: { exclude: /^hello*/ }, + }, +}; +``` + ```js filename="YourComponent.stories.js|jsx" renderer="common" language="js" import { YourComponent } from './YourComponent'; @@ -67,6 +139,83 @@ export const RegexExclude = { }; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + }); +</script> + +<Story + name="ArrayInclude" + parameters={{ + controls: { include: ['foo', 'bar'] }, + }} +/> + +<Story + name="RegexInclude" + parameters={{ + controls: { include: /^hello*/ }, + }} +/> + +<Story + name="ArrayExclude" + parameters={{ + controls: { exclude: ['foo', 'bar'] }, + }} +/> + +<Story + name="RegexExclude" + parameters={{ + controls: { exclude: /^hello*/ }, + }} +/> +``` + +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import YourComponent from './YourComponent.svelte'; + +const meta = { + component: YourComponent, +} satisfies Meta<typeof YourComponent>; + +export default meta; +type Story = StoryObj<typeof meta>; + +export const ArrayInclude: Story = { + parameters: { + controls: { include: ['foo', 'bar'] }, + }, +}; + +export const RegexInclude: Story = { + parameters: { + controls: { include: /^hello*/ }, + }, +}; + +export const ArrayExclude: Story = { + parameters: { + controls: { exclude: ['foo', 'bar'] }, + }, +}; + +export const RegexExclude: Story = { + parameters: { + controls: { exclude: /^hello*/ }, + }, +}; +``` + ```ts filename="YourComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -105,6 +254,83 @@ export const RegexExclude: Story = { }; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + }); +</script> + +<Story + name="ArrayInclude" + parameters={{ + controls: { include: ['foo', 'bar'] }, + }} +/> + +<Story + name="RegexInclude" + parameters={{ + controls: { include: /^hello*/ }, + }} +/> + +<Story + name="ArrayExclude" + parameters={{ + controls: { exclude: ['foo', 'bar'] }, + }} +/> + +<Story + name="RegexExclude" + parameters={{ + controls: { exclude: /^hello*/ }, + }} +/> +``` + +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import YourComponent from './YourComponent.svelte'; + +const meta: Meta<typeof YourComponent> = { + component: YourComponent, +}; + +export default meta; +type Story = StoryObj<typeof YourComponent>; + +export const ArrayInclude: Story = { + parameters: { + controls: { include: ['foo', 'bar'] }, + }, +}; + +export const RegexInclude: Story = { + parameters: { + controls: { include: /^hello*/ }, + }, +}; + +export const ArrayExclude: Story = { + parameters: { + controls: { exclude: ['foo', 'bar'] }, + }, +}; + +export const RegexExclude: Story = { + parameters: { + controls: { exclude: /^hello*/ }, + }, +}; +``` + ```ts filename="YourComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -207,4 +433,3 @@ export const RegexExclude: Story = { }, }; ``` - diff --git a/docs/_snippets/component-story-disable-controls.md b/docs/_snippets/component-story-disable-controls.md index 60af7727dd6d..ba68941855f4 100644 --- a/docs/_snippets/component-story-disable-controls.md +++ b/docs/_snippets/component-story-disable-controls.md @@ -18,6 +18,42 @@ const meta: Meta<YourComponent> = { export default meta; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + table: { + disable: true, + }, + }, + }, + }); +</script> +``` + +```js filename="YourComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import YourComponent from './YourComponent.svelte'; + +export default { + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + table: { + disable: true, + }, + }, + }, +}; +``` + ```js filename="YourComponent.stories.js|jsx" renderer="common" language="js" import { YourComponent } from './YourComponent'; @@ -34,6 +70,46 @@ export default { }; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + table: { + disable: true, + }, + }, + }, + }); +</script> +``` + +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import YourComponent from './YourComponent.svelte'; + +const meta = { + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + table: { + disable: true, + }, + }, + }, +} satisfies Meta<typeof YourComponent>; + +export default meta; +``` + ```ts filename="YourComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -55,6 +131,46 @@ const meta = { export default meta; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + table: { + disable: true, + }, + }, + }, + }); +</script> +``` + +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import YourComponent from './YourComponent.svelte'; + +const meta: Meta<typeof YourComponent> = { + component: YourComponent, + argTypes: { + // foo is the property we want to remove from the UI + foo: { + table: { + disable: true, + }, + }, + }, +}; + +export default meta; +``` + ```ts filename="YourComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -107,4 +223,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/component-story-figma-integration.md b/docs/_snippets/component-story-figma-integration.md index afd0a641a762..d417ce880537 100644 --- a/docs/_snippets/component-story-figma-integration.md +++ b/docs/_snippets/component-story-figma-integration.md @@ -308,4 +308,3 @@ export const Example: Story = { }, }; ``` - diff --git a/docs/_snippets/component-story-highlight-addon.md b/docs/_snippets/component-story-highlight-addon.md index 942ac7c524a7..03d1a8e0ba52 100644 --- a/docs/_snippets/component-story-highlight-addon.md +++ b/docs/_snippets/component-story-highlight-addon.md @@ -231,4 +231,3 @@ export const Highlighted: Story = { ], }; ``` - diff --git a/docs/_snippets/component-story-sort-controls.md b/docs/_snippets/component-story-sort-controls.md index 0af15d4f2125..5c152e4312a7 100644 --- a/docs/_snippets/component-story-sort-controls.md +++ b/docs/_snippets/component-story-sort-controls.md @@ -11,8 +11,30 @@ const meta: Meta<YourComponent> = { export default meta; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + parameters: { controls: { sort: 'requiredFirst' } }, + }); +</script> +``` + +```js filename="YourComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import YourComponent from './YourComponent.svelte'; + +export default { + component: YourComponent, + parameters: { controls: { sort: 'requiredFirst' } }, +}; +``` + ```js filename="YourComponent.stories.js|jsx" renderer="common" language="js" -import { YourComponent } from './your-component'; +import { YourComponent } from './YourComponent'; export default { component: YourComponent, @@ -20,6 +42,32 @@ export default { }; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + parameters: { controls: { sort: 'requiredFirst' } }, + }); +</script> +``` + +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import YourComponent from './YourComponent.svelte'; + +const meta = { + component: YourComponent, + parameters: { controls: { sort: 'requiredFirst' } }, +} satisfies Meta<typeof YourComponent>; + +export default meta; +``` + ```ts filename="YourComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -34,6 +82,32 @@ const meta = { export default meta; ``` +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + parameters: { controls: { sort: 'requiredFirst' } }, + }); +</script> +``` + +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import YourComponent from './YourComponent.svelte'; + +const meta: Meta<typeof YourComponent> = { + component: YourComponent, + parameters: { controls: { sort: 'requiredFirst' } }, +}; + +export default meta; +``` + ```ts filename="YourComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -65,4 +139,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/component-story-static-asset-cdn.md b/docs/_snippets/component-story-static-asset-cdn.md index 11802b03e0e2..b75ef7a9187e 100644 --- a/docs/_snippets/component-story-static-asset-cdn.md +++ b/docs/_snippets/component-story-static-asset-cdn.md @@ -34,7 +34,7 @@ export const WithAnImage = { }; ``` -```ts filename=" MyComponent.stories.ts|tsx" renderer="react" language="ts-4-9" +```ts filename="MyComponent.stories.ts|tsx" renderer="react" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/react'; import { MyComponent } from './MyComponent'; @@ -53,7 +53,7 @@ export const WithAnImage: Story = { }; ``` -```tsx filename=" MyComponent.stories.ts|tsx" renderer="react" language="ts" +```tsx filename="MyComponent.stories.ts|tsx" renderer="react" language="ts" import type { Meta, StoryObj } from '@storybook/react'; import { MyComponent } from './MyComponent'; @@ -86,7 +86,7 @@ export const WithAnImage = { }; ``` -```tsx filename=" MyComponent.stories.ts|tsx" renderer="solid" language="ts-4-9" +```tsx filename="MyComponent.stories.ts|tsx" renderer="solid" language="ts-4-9" import type { Meta, StoryObj } from 'storybook-solidjs'; import { MyComponent } from './MyComponent'; @@ -105,7 +105,7 @@ export const WithAnImage: Story = { }; ``` -```tsx filename=" MyComponent.stories.ts|tsx" renderer="solid" language="ts" +```tsx filename="MyComponent.stories.ts|tsx" renderer="solid" language="ts" import type { Meta, StoryObj } from 'storybook-solidjs'; import { MyComponent } from './MyComponent'; @@ -124,7 +124,26 @@ export const WithAnImage: Story = { }; ``` -```js filename="MyComponent.stories.js" renderer="svelte" language="js" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story name="WithAnImage"> + <MyComponent + src="https://storybook.js.org/images/placeholders/350x150.png" + alt="My CDN placeholder" + /> +</Story> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" import MyComponent from './MyComponent.svelte'; export default { @@ -142,28 +161,26 @@ export const WithAnImage = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* MyComponent.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import MyComponent from './MyComponent.svelte'; -</script> -<meta title="img" component="{MyComponent}" /> + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> -<template> +<Story name="WithAnImage"> <MyComponent src="https://storybook.js.org/images/placeholders/350x150.png" alt="My CDN placeholder" /> -</template> - -<Story name="WithAnImage" /> +</Story> ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -186,7 +203,26 @@ export const WithAnImage: Story = { }; ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story name="WithAnImage"> + <MyComponent + src="https://storybook.js.org/images/placeholders/350x150.png" + alt="My CDN placeholder" + /> +</Story> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -300,4 +336,3 @@ export const WithAnImage: Story = { />`, }; ``` - diff --git a/docs/_snippets/component-story-static-asset-with-import.md b/docs/_snippets/component-story-static-asset-with-import.md index 832e85099131..3301d3b03561 100644 --- a/docs/_snippets/component-story-static-asset-with-import.md +++ b/docs/_snippets/component-story-static-asset-with-import.md @@ -47,7 +47,7 @@ export const WithAnImage = { }; ``` -```tsx filename=" MyComponent.stories.ts|tsx" renderer="react" language="ts-4-9" +```tsx filename="MyComponent.stories.ts|tsx" renderer="react" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/react'; import imageFile from './static/image.png'; @@ -71,7 +71,7 @@ export const WithAnImage: Story = { }; ``` -```tsx filename=" MyComponent.stories.ts|tsx" renderer="react" language="ts" +```tsx filename="MyComponent.stories.ts|tsx" renderer="react" language="ts" import type { Meta, StoryObj } from '@storybook/react'; import imageFile from './static/image.png'; @@ -114,7 +114,7 @@ export const WithAnImage = { }; ``` -```tsx filename=" MyComponent.stories.ts|tsx" renderer="solid" language="ts-4-9" +```tsx filename="MyComponent.stories.ts|tsx" renderer="solid" language="ts-4-9" import type { Meta, StoryObj } from 'storybook-solidjs'; import imageFile from './static/image.png'; @@ -138,7 +138,7 @@ export const WithAnImage: Story = { }; ``` -```tsx filename=" MyComponent.stories.ts|tsx" renderer="solid" language="ts" +```tsx filename="MyComponent.stories.ts|tsx" renderer="solid" language="ts" import type { Meta, StoryObj } from 'storybook-solidjs'; import imageFile from './static/image.png'; @@ -162,9 +162,30 @@ export const WithAnImage: Story = { }; ``` -```js renderer="svelte" language="js" -//MyComponent.stories.js +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + import MyComponent from './MyComponent.svelte'; + + import imageFile from './static/image.png'; + + let image = { + src: imageFile, + alt: 'my image', + }; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story name="WithAnImage"> + <MyComponent {image} /> +</Story> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" import MyComponent from './MyComponent.svelte'; import imageFile from './static/image.png'; @@ -186,11 +207,9 @@ export const WithAnImage = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* MyComponent.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import MyComponent from './MyComponent.svelte'; @@ -200,18 +219,18 @@ export const WithAnImage = { src: imageFile, alt: 'my image', }; -</script> -<meta title="img" component="{MyComponent}" /> - -<template> - <MyComponent {image} /> -</template> + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> -<Story name="WithAnImage" /> +<Story name="WithAnImage"> + <MyComponent {image} /> +</Story> ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -238,7 +257,30 @@ export const WithAnImage: Story = { }; ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + import imageFile from './static/image.png'; + + let image = { + src: imageFile, + alt: 'my image', + }; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story name="WithAnImage"> + <MyComponent {image} /> +</Story> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -265,7 +307,7 @@ export const WithAnImage: Story = { }; ``` -```js filename="MyComponent.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="MyComponent.stories.js" renderer="vue" language="js" import MyComponent from './MyComponent.vue'; import imageFile from './static/image.png'; @@ -290,7 +332,7 @@ export const WithAnImage = { }; ``` -```ts filename="MyComponent.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="MyComponent.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import MyComponent from './MyComponent.vue'; @@ -320,7 +362,7 @@ export const WithAnImage: Story = { }; ``` -```ts filename="MyComponent.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="MyComponent.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import MyComponent from './MyComponent.vue'; @@ -392,4 +434,3 @@ export const WithAnImage: Story = { render: () => html`<img src="${image.src}" alt="${image.alt}" />`, }; ``` - diff --git a/docs/_snippets/component-story-static-asset-without-import.md b/docs/_snippets/component-story-static-asset-without-import.md index c0ab68f70118..99b0e2d32734 100644 --- a/docs/_snippets/component-story-static-asset-without-import.md +++ b/docs/_snippets/component-story-static-asset-without-import.md @@ -34,7 +34,7 @@ export const WithAnImage = { }; ``` -```tsx filename=" MyComponent.stories.ts|tsx" renderer="react" language="ts-4-9" +```tsx filename="MyComponent.stories.ts|tsx" renderer="react" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/react'; import { MyComponent } from './MyComponent'; @@ -52,7 +52,7 @@ export const WithAnImage: Story = { }; ``` -```tsx filename=" MyComponent.stories.ts|tsx" renderer="react" language="ts" +```tsx filename="MyComponent.stories.ts|tsx" renderer="react" language="ts" import type { Meta, StoryObj } from '@storybook/react'; import { MyComponent } from './MyComponent'; @@ -119,7 +119,23 @@ export const WithAnImage: Story = { }; ``` -```js filename="MyComponent.stories.js" renderer="svelte" language="js" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story name="WithAnImage"> + <MyComponent src="/image.png" alt="my image" /> +</Story> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" import MyComponent from './MyComponent.svelte'; export default { @@ -138,25 +154,23 @@ export const WithAnImage = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* MyComponent.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import MyComponent from './MyComponent.svelte'; -</script> -<meta title="img" component="{MyComponent}" /> + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> -<template> +<Story name="WithAnImage"> <MyComponent src="/image.png" alt="my image" /> -</template> - -<Story name="WithAnImage" /> +</Story> ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -180,7 +194,23 @@ export const WithAnImage: Story = { }; ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story name="WithAnImage"> + <MyComponent src="/image.png" alt="my image" /> +</Story> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -287,4 +317,3 @@ export const WithAnImage: Story = { render: () => html`<img src="/image.png" alt="image" />`, }; ``` - diff --git a/docs/_snippets/component-story-with-accessibility.md b/docs/_snippets/component-story-with-accessibility.md index be41f9d28d46..173cbbf06018 100644 --- a/docs/_snippets/component-story-with-accessibility.md +++ b/docs/_snippets/component-story-with-accessibility.md @@ -211,7 +211,28 @@ export const Inaccessible: Story = { }; ``` -```js filename="Button.stories.js" renderer="svelte" language="js" +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + backgroundColor: { control: 'color' }, + }, + }); +</script> + +<!-- This is an accessible story --> +<Story name="Accessible" args={{ primary: false, label: 'Button' }} /> + +<!-- This is not --> +<Story name="Inaccessible" args={{ primary: false, label: 'Button', backgroundColor: 'red' }} /> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" import Button from './Button.svelte'; export default { @@ -223,10 +244,6 @@ export default { // This is an accessible story export const Accessible = { - render: (args) => ({ - Component: Button, - props: args, - }), args: { primary: false, label: 'Button', @@ -235,10 +252,6 @@ export const Accessible = { // This is not export const Inaccessible = { - render: (args) => ({ - Component: Button, - props: args, - }), args: { ...Accessible.args, backgroundColor: 'red', @@ -246,7 +259,28 @@ export const Inaccessible = { }; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + backgroundColor: { control: 'color' }, + }, + }); +</script> + +<!-- This is an accessible story --> +<Story name="Accessible" args={{ primary: false, label: 'Button' }} /> + +<!-- This is not --> +<Story name="Inaccessible" args={{ primary: false, label: 'Button', backgroundColor: 'red' }} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -278,7 +312,28 @@ export const Inaccessible: Story = { }; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + argTypes: { + backgroundColor: { control: 'color' }, + }, + }); +</script> + +<!-- This is an accessible story --> +<Story name="Accessible" args={{ primary: false, label: 'Button' }} /> + +<!-- This is not --> +<Story name="Inaccessible" args={{ primary: false, label: 'Button', backgroundColor: 'red' }} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -310,7 +365,7 @@ export const Inaccessible: Story = { }; ``` -```js filename="Button.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="Button.stories.js" renderer="vue" language="js" import Button from './Button.vue'; export default { @@ -337,7 +392,7 @@ export const Inaccessible = { }; ``` -```ts filename="Button.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="Button.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -368,7 +423,7 @@ export const Inaccessible: Story = { }; ``` -```ts filename="Button.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="Button.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -467,4 +522,3 @@ export const Inaccessible: Story = { }, }; ``` - diff --git a/docs/_snippets/component-story-with-custom-render-function.md b/docs/_snippets/component-story-with-custom-render-function.md index 0fb274bc56d9..f09079e91e86 100644 --- a/docs/_snippets/component-story-with-custom-render-function.md +++ b/docs/_snippets/component-story-with-custom-render-function.md @@ -371,4 +371,3 @@ export const Example: Story = { `, }; ``` - diff --git a/docs/_snippets/component-styled-variables-object-notation.md b/docs/_snippets/component-styled-variables-object-notation.md index 0253c4dbb2e4..bfff3a901641 100644 --- a/docs/_snippets/component-styled-variables-object-notation.md +++ b/docs/_snippets/component-styled-variables-object-notation.md @@ -4,4 +4,3 @@ const Component = styled.div(({ theme }) => ({ width: 0, })); ``` - diff --git a/docs/_snippets/component-styled-variables-template-literals.md b/docs/_snippets/component-styled-variables-template-literals.md index 504fcf06c8f9..501e5211f2c4 100644 --- a/docs/_snippets/component-styled-variables-template-literals.md +++ b/docs/_snippets/component-styled-variables-template-literals.md @@ -4,4 +4,3 @@ const Component = styled.div` width: 0; `; ``` - diff --git a/docs/_snippets/component-test-with-testing-library.md b/docs/_snippets/component-test-with-testing-library.md index 0ac1e206d6b1..7688b694f45d 100644 --- a/docs/_snippets/component-test-with-testing-library.md +++ b/docs/_snippets/component-test-with-testing-library.md @@ -104,7 +104,7 @@ it('Checks if the form is valid', async () => { }); ``` -```js filename="tests/Form.test.js" renderer="vue" language="js" tabTitle="3" +```js filename="tests/Form.test.js" renderer="vue" language="js" import { fireEvent, render, screen } from '@testing-library/vue'; import { composeStories } from '@storybook/vue3'; @@ -128,7 +128,7 @@ test('Checks if the form is valid', async () => { }); ``` -```ts filename="tests/Form.test.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="tests/Form.test.ts" renderer="vue" language="ts" import { fireEvent, render, screen } from '@testing-library/vue'; import { composeStories } from '@storybook/vue3'; diff --git a/docs/_snippets/configure-mock-provider-with-story-parameter.md b/docs/_snippets/configure-mock-provider-with-story-parameter.md index f58b7b441096..a9b4b310b034 100644 --- a/docs/_snippets/configure-mock-provider-with-story-parameter.md +++ b/docs/_snippets/configure-mock-provider-with-story-parameter.md @@ -61,4 +61,3 @@ export const Dark: Story = { }, }; ``` - diff --git a/docs/_snippets/csf-2-example-primary-dark-story.md b/docs/_snippets/csf-2-example-primary-dark-story.md index 5c0f1397e870..ea013974f52c 100644 --- a/docs/_snippets/csf-2-example-primary-dark-story.md +++ b/docs/_snippets/csf-2-example-primary-dark-story.md @@ -1,6 +1,5 @@ -```js filename="CSF 2" renderer="common" language="js" +```js filename="CSF 2 - Button.stories.js|jsx|ts|tsx" renderer="common" language="js" export const PrimaryOnDark = Primary.bind({}); PrimaryOnDark.args = Primary.args; PrimaryOnDark.parameters = { background: { default: 'dark' } }; ``` - diff --git a/docs/_snippets/csf-2-example-starter.md b/docs/_snippets/csf-2-example-starter.md index e56d985beede..ba9340e6cd89 100644 --- a/docs/_snippets/csf-2-example-starter.md +++ b/docs/_snippets/csf-2-example-starter.md @@ -1,4 +1,4 @@ -```ts filename="CSF 2" renderer="angular" language="ts" +```ts filename="CSF 2 - Button.stories.ts" renderer="angular" language="ts" import { Meta, Story } from '@storybook/angular'; import { Button } from './button.component'; @@ -14,7 +14,7 @@ export const Primary: Story = (args) => ({ Primary.args = { primary: true }; ``` -```js filename="CSF 2" renderer="react" language="js" +```js filename="CSF 2 - Button.stories.js|jsx" renderer="react" language="js" import { Button } from './Button'; export default { @@ -26,7 +26,7 @@ export const Primary = (args) => <Button {...args} />; Primary.args = { primary: true }; ``` -```tsx filename="CSF 2" renderer="react" language="ts" +```tsx filename="CSF 2 - Button.stories.ts|tsx" renderer="react" language="ts" import { ComponentStory, ComponentMeta } from '@storybook/react'; import { Button } from './Button'; @@ -40,7 +40,7 @@ export const Primary: ComponentStory<typeof Button> = (args) => <Button {...args Primary.args = { primary: true }; ``` -```js filename="CSF 2" renderer="solid" language="js" +```js filename="CSF 2 - Button.stories.js|jsx" renderer="solid" language="js" import { Button } from './Button'; export default { @@ -52,7 +52,7 @@ export const Primary = (args) => <Button {...args} />; Primary.args = { primary: true }; ``` -```tsx filename="CSF 2" renderer="solid" language="ts" +```tsx filename="CSF 2 - Button.stories.ts|tsx" renderer="solid" language="ts" import { ComponentStory, ComponentMeta } from 'storybook-solidjs'; import { Button } from './Button'; @@ -66,7 +66,7 @@ export const Primary: ComponentStory<typeof Button> = (args) => <Button {...args Primary.args = { primary: true }; ``` -```js filename="Button.stories.js" renderer="svelte" language="js" +```js filename="CSF 2 - Button.stories.js" renderer="svelte" language="js" import Button from './Button.svelte'; export default { @@ -81,7 +81,7 @@ export const Primary = (args) => ({ Primary.args = { primary: true }; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```ts filename="CSF 2 - Button.stories.ts" renderer="svelte" language="ts" import type { Meta, StoryFn } from '@storybook/svelte'; import Button from './Button.svelte'; @@ -98,7 +98,7 @@ export const Primary: StoryFn<typeof Button> = (args) => ({ Primary.args = { primary: true }; ``` -```js filename="CSF 2" renderer="vue" language="js" tabTitle="3" +```js filename="CSF 2 - Button.stories.js" renderer="vue" language="js" import Button from './Button.vue'; export default { @@ -116,7 +116,7 @@ export const Primary = (args) => ({ Primary.args = { primary: true }; ``` -```ts filename="CSF 2" renderer="vue" language="ts" tabTitle="3" +```ts filename="CSF 2 - Button.stories.ts" renderer="vue" language="ts" import { Meta, StoryFn } from '@storybook/vue3'; import Button from './Button.vue'; @@ -136,7 +136,7 @@ export const Primary: StoryFn<typeof Button> = (args) => ({ Primary.args = { primary: true }; ``` -```js filename="CSF 2" renderer="web-components" language="js" +```js filename="CSF 2 - Button.stories.js" renderer="web-components" language="js" import { html } from 'lit'; export default { @@ -150,7 +150,7 @@ Primary.args = { }; ``` -```ts filename="CSF 2" renderer="web-components" language="ts" +```ts filename="CSF 2 - Button.stories.ts" renderer="web-components" language="ts" import type { Meta, Story } from '@storybook/web-components'; import { html } from 'lit'; @@ -166,4 +166,3 @@ Primary.args = { primary: true, }; ``` - diff --git a/docs/_snippets/csf-2-example-story.md b/docs/_snippets/csf-2-example-story.md index fe9a90055ecd..5126e303f653 100644 --- a/docs/_snippets/csf-2-example-story.md +++ b/docs/_snippets/csf-2-example-story.md @@ -1,31 +1,31 @@ -```ts filename="CSF 2" renderer="angular" language="ts" +```ts filename="CSF 2 - Button.stories.ts" renderer="angular" language="ts" // Other imports and story implementation export const Default: Story = (args) => ({ props: args, }); ``` -```js filename="CSF 2" renderer="react" language="js" +```js filename="CSF 2 - Button.stories.js|jsx" renderer="react" language="js" // Other imports and story implementation export const Default = (args) => <Button {...args} />; ``` -```ts filename="CSF 2" renderer="react" language="ts" +```ts filename="CSF 2 - Button.stories.ts|tsx" renderer="react" language="ts" // Other imports and story implementation export const Default: ComponentStory<typeof Button> = (args) => <Button {...args} />; ``` -```js filename="CSF 2" renderer="solid" language="js" +```js filename="CSF 2 - Button.stories.js|jsx" renderer="solid" language="js" // Other imports and story implementation export const Default = (args) => <Button {...args} />; ``` -```ts filename="CSF 2" renderer="solid" language="ts" +```ts filename="CSF 2 - Button.stories.ts|tsx" renderer="solid" language="ts" // Other imports and story implementation export const Default: ComponentStory<typeof Button> = (args) => <Button {...args} />; ``` -```js filename="CSF 2" renderer="svelte" language="js" +```js filename="CSF 2 - Button.stories.js" renderer="svelte" language="js" // Other imports and story implementation export const Default = (args) => ({ Component: Button, @@ -33,15 +33,15 @@ export const Default = (args) => ({ }); ``` -```ts filename="CSF 2" renderer="svelte" language="ts" +```ts filename="CSF 2 - Button.stories.ts" renderer="svelte" language="ts" // Other imports and story implementation -export const Primary: StoryFn<typeof Button> = (args) => ({ +export const Default: StoryFn<typeof Button> = (args) => ({ Component: Button, props: args, }); ``` -```js filename="CSF 2" renderer="vue" language="js" tabTitle="3" +```js filename="CSF 2 - Button.stories.js" renderer="vue" language="js" // Other imports and story implementation export const Default = (args) => ({ components: { Button }, @@ -52,7 +52,7 @@ export const Default = (args) => ({ }); ``` -```ts filename="CSF 2" renderer="vue" language="ts" tabTitle="3" +```ts filename="CSF 2 - Button.stories.ts" renderer="vue" language="ts" // Other imports and story implementation export const Default: StoryFn<typeof Button> = (args) => ({ components: { Button }, @@ -63,17 +63,16 @@ export const Default: StoryFn<typeof Button> = (args) => ({ }); ``` -```js filename="CSF 2" renderer="web-components" language="js" +```js filename="CSF 2 - Button.stories.js" renderer="web-components" language="js" // Other imports and story implementation -export const Default = ({ primary, backgroundColor, size, label }) => +export const Default = ({ primary, size, label }) => html`<custom-button ?primary="${primary}" size="${size}" label="${label}"></custom-button>`; ``` -```ts filename="CSF 2" renderer="web-components" language="ts" +```ts filename="CSF 2 - Button.stories.ts" renderer="web-components" language="ts" // Other imports and story implementation export const Default: Story = ({ primary, backgroundColor, size, label }) => html`<custom-button ?primary="${primary}" size="${size}" label="${label}"></custom-button>`; ``` - diff --git a/docs/_snippets/csf-2-example-title.md b/docs/_snippets/csf-2-example-title.md index 9c55eac4fa2f..3574e82822a1 100644 --- a/docs/_snippets/csf-2-example-title.md +++ b/docs/_snippets/csf-2-example-title.md @@ -1,7 +1,6 @@ -```js filename="CSF 2" renderer="common" language="js" +```js filename="CSF 2 - Button.stories.js|jsx|ts|tsx" renderer="common" language="js" export default { title: 'components/Button', component: Button, }; ``` - diff --git a/docs/_snippets/csf-3-example-auto-title.md b/docs/_snippets/csf-3-example-auto-title.md index 18d9531d5281..d98dfea7bbd1 100644 --- a/docs/_snippets/csf-3-example-auto-title.md +++ b/docs/_snippets/csf-3-example-auto-title.md @@ -1,4 +1,3 @@ -```js filename="CSF 3" renderer="common" language="js" +```js filename="CSF 3 - Button.stories.js|jsx|ts|tsx" renderer="common" language="js" export default { component: Button }; ``` - diff --git a/docs/_snippets/csf-3-example-default-render.md b/docs/_snippets/csf-3-example-default-render.md index 3382a97654cd..87fb0d060c3d 100644 --- a/docs/_snippets/csf-3-example-default-render.md +++ b/docs/_snippets/csf-3-example-default-render.md @@ -1,4 +1,3 @@ -```js filename="CSF 3 - default render function" renderer="common" language="js" +```js filename="CSF 3 - Button.stories.js|jsx|ts|tsx" renderer="common" language="js" export const Default = {}; ``` - diff --git a/docs/_snippets/csf-3-example-primary-dark-story.md b/docs/_snippets/csf-3-example-primary-dark-story.md index a4dea05d3606..850fd8bd21de 100644 --- a/docs/_snippets/csf-3-example-primary-dark-story.md +++ b/docs/_snippets/csf-3-example-primary-dark-story.md @@ -1,14 +1,13 @@ -```js filename="CSF 3" renderer="common" language="js" +```js filename="CSF 3 - Button.stories.js|jsx" renderer="common" language="js" export const PrimaryOnDark = { ...Primary, parameters: { background: { default: 'dark' } }, }; ``` -```ts filename="CSF 3" renderer="common" language="ts" +```ts filename="CSF 3 - Button.stories.ts|tsx" renderer="common" language="ts" export const PrimaryOnDark: Story = { ...Primary, parameters: { background: { default: 'dark' } }, }; ``` - diff --git a/docs/_snippets/csf-3-example-render.md b/docs/_snippets/csf-3-example-render.md index 4f41716a33eb..0eba075462f4 100644 --- a/docs/_snippets/csf-3-example-render.md +++ b/docs/_snippets/csf-3-example-render.md @@ -1,4 +1,4 @@ -```ts filename="CSF 3 - explicit render function" renderer="angular" language="ts" +```ts filename="CSF 3 - Button.stories.ts" renderer="angular" language="ts" // Other imports and story implementation export const Default: Story = { render: (args) => ({ @@ -7,35 +7,35 @@ export const Default: Story = { }; ``` -```js filename="CSF 3 - explicit render function" renderer="react" language="js" +```js filename="CSF 3 - Button.stories.js|jsx" renderer="react" language="js" // Other imports and story implementation export const Default = { render: (args) => <Button {...args} />, }; ``` -```ts filename="CSF 3 - explicit render function" renderer="react" language="ts" +```ts filename="CSF 3 - Button.stories.ts|tsx" renderer="react" language="ts" // Other imports and story implementation export const Default: Story = { render: (args) => <Button {...args} />, }; ``` -```js filename="CSF 3 - explicit render function" renderer="solid" language="js" +```js filename="CSF 3 - Button.stories.js|jsx" renderer="solid" language="js" // Other imports and story implementation export const Default = { render: (args) => <Button {...args} />, }; ``` -```ts filename="CSF 3 - explicit render function" renderer="solid" language="ts" +```ts filename="CSF 3 - Button.stories.ts|tsx" renderer="solid" language="ts" // Other imports and story implementation export const Default: Story = { render: (args) => <Button {...args} />, }; ``` -```js filename="CSF 3 - explicit render function" renderer="svelte" language="js" +```js filename="CSF 3 - Button.stories.js" renderer="svelte" language="js" // Other imports and story implementation export const Default = { render: (args) => ({ @@ -45,7 +45,7 @@ export const Default = { }; ``` -```ts filename="CSF 3 - explicit render function" renderer="svelte" language="ts" +```ts filename="CSF 3 - Button.stories.ts" renderer="svelte" language="ts" // Other imports and story implementation export const Default: Story = { render: (args) => ({ @@ -55,7 +55,7 @@ export const Default: Story = { }; ``` -```js filename="CSF 3 - explicit render function" renderer="vue" language="js" tabTitle="3" +```js filename="CSF 3 - Button.stories.js" renderer="vue" language="js" // Other imports and story implementation export const Default = { render: (args) => ({ @@ -68,7 +68,7 @@ export const Default = { }; ``` -```ts filename="CSF 3 - explicit render function" renderer="vue" language="ts" tabTitle="3" +```ts filename="CSF 3 - Button.stories.ts" renderer="vue" language="ts" // Other imports and story implementation export const Default: Story = { render: (args) => ({ @@ -81,19 +81,18 @@ export const Default: Story = { }; ``` -```js filename="CSF 3" renderer="web-components" language="js" +```js filename="CSF 3 - Button.stories.js" renderer="web-components" language="js" // Other imports and story implementation export const Default = { - render: (args) => html`<demo-button label="Hello" @click=${action('clicked')}></custom-button>`, + render: (args) => html`<demo-button label="Hello" @click=${action('clicked')}></demo-button>`, }; ``` -```js filename="CSF 3" renderer="web-components" language="ts" +```js filename="CSF 3 - Button.stories.ts" renderer="web-components" language="ts" // Other imports and story implementation export const Default: Story = { render: (args) => html`<custom-button label="Hello" @click=${action('clicked')}></custom-button>`, }; ``` - diff --git a/docs/_snippets/csf-3-example-starter.md b/docs/_snippets/csf-3-example-starter.md index 262cf7e4f454..2740454daba0 100644 --- a/docs/_snippets/csf-3-example-starter.md +++ b/docs/_snippets/csf-3-example-starter.md @@ -1,17 +1,17 @@ -```ts filename="CSF 3" renderer="angular" language="ts" +```ts filename="CSF 3 - Button.stories.ts" renderer="angular" language="ts" import type { Meta, StoryObj } from '@storybook/angular'; import { Button } from './button.component'; const meta: Meta<Button> = { component: Button }; -export default meta; +export default meta; type Story = StoryObj<Button>; export const Primary: Story = { args: { primary: true } }; ``` -```js filename="CSF 3" renderer="common" language="js" +```js filename="CSF 3 - Button.stories.js|jsx" renderer="react" language="js" import { Button } from './Button'; export default { component: Button }; @@ -19,7 +19,7 @@ export default { component: Button }; export const Primary = { args: { primary: true } }; ``` -```ts filename="CSF 3" renderer="react" language="ts-4-9" +```ts filename="CSF 3 - Button.stories.ts|tsx" renderer="react" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/react'; import { Button } from './Button'; @@ -27,27 +27,27 @@ import { Button } from './Button'; const meta = { component: Button, } satisfies Meta<typeof Button>; -export default meta; +export default meta; type Story = StoryObj<typeof meta>; export const Primary: Story = { args: { primary: true } }; ``` -```ts filename="CSF 3" renderer="react" language="ts" +```ts filename="CSF 3 - Button.stories.ts|tsx" renderer="react" language="ts" import type { Meta, StoryObj } from '@storybook/react'; import { Button } from './Button'; const meta: Meta<typeof Button> = { component: Button }; -export default meta; +export default meta; type Story = StoryObj<typeof Button>; export const Primary: Story = { args: { primary: true } }; ``` -```tsx filename="CSF 3" renderer="solid" language="ts-4-9" +```ts filename="CSF 3 - Button.stories.ts|tsx" renderer="solid" language="ts-4-9" import type { Meta, StoryObj } from 'storybook-solidjs'; import { Button } from './Button'; @@ -55,40 +55,64 @@ import { Button } from './Button'; const meta = { component: Button, } satisfies Meta<typeof Button>; -export default meta; +export default meta; type Story = StoryObj<typeof meta>; export const Primary: Story = { args: { primary: true } }; ``` -```ts filename="CSF 3" renderer="solid" language="ts" +```js filename="CSF 3 - Button.stories.js|jsx" renderer="solid" language="js" +import { Button } from './Button'; + +export default { component: Button }; + +export const Primary = { args: { primary: true } }; +``` + +```ts filename="CSF 3 - Button.stories.ts|tsx" renderer="solid" language="ts" import type { Meta, StoryObj } from 'storybook-solidjs'; import { Button } from './Button'; const meta: Meta<typeof Button> = { component: Button }; -export default meta; +export default meta; type Story = StoryObj<typeof Button>; export const Primary: Story = { args: { primary: true } }; ``` -```ts filename="Button.stories.ts" renderer="svelte" language="ts" +```js filename="CSF 3 - Button.stories.js" renderer="svelte" language="js" +import Button from './Button.svelte'; + +export default { component: Button }; + +export const Primary = { args: { primary: true } }; +``` + +```ts filename="CSF 3 - Button.stories.ts" renderer="svelte" language="ts" import type { Meta, StoryObj } from '@storybook/svelte'; import Button from './Button.svelte'; const meta: Meta<typeof Button> = { component: Button }; -export default meta; +export default meta; type Story = StoryObj<typeof meta>; export const Primary: Story = { args: { primary: true } }; ``` -```ts filename="CSF 3" renderer="vue" language="ts-4-9" +```js filename="CSF 3 - Button.stories.js" renderer="vue" language="js" +import Button from './Button.vue'; + +export default { component: Button }; + +export const Primary = { args: { primary: true } }; +``` + +```ts filename="CSF 3 - Button.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -101,7 +125,7 @@ type Story = StoryObj<typeof meta>; export const Primary: Story = { args: { primary: true } }; ``` -```ts filename="CSF 3" renderer="vue" language="ts" +```ts filename="CSF 3 - Button.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import Button from './Button.vue'; @@ -114,7 +138,7 @@ type Story = StoryObj<typeof Button>; export const Primary: Story = { args: { primary: true } }; ``` -```js filename="CSF 3" renderer="web-components" language="js" +```js filename="CSF 3 - Button.stories.js" renderer="web-components" language="js" export default { title: 'components/Button', component: 'demo-button', @@ -123,7 +147,7 @@ export default { export const Primary = { args: { primary: true } }; ``` -```ts filename="CSF 3" renderer="web-components" language="ts" +```ts filename="CSF 3 - Button.stories.ts" renderer="web-components" language="ts" import type { Meta, StoryObj } from '@storybook/web-components'; const meta: Meta = { @@ -136,4 +160,3 @@ type Story = StoryObj; export const Primary: Story = { args: { primary: true } }; ``` - diff --git a/docs/_snippets/csf-3-example-title.md b/docs/_snippets/csf-3-example-title.md index 66a2d9d8f215..4b5d0039ba2f 100644 --- a/docs/_snippets/csf-3-example-title.md +++ b/docs/_snippets/csf-3-example-title.md @@ -1,19 +1,39 @@ -```mdx renderer="common" language="mdx" -{/* src/components/Button/Button.mdx */} - -import { Meta } from '@storybook/blocks'; +```mdx filename="src/components/Button/Button.mdx" renderer="common" language="mdx" +import { Meta, Story } from '@storybook/blocks'; {/* 👇 Documentation-only page */} -<Meta title="Documentation" /> +<Meta title="Documentation" /> {/* 👇 Component documentation page */} -import * as ExampleComponentStories from './ExampleComponent.stories'; +import * as ButtonStories from './Button.stories'; + +<Meta of={ButtonStories} /> + +<Story of={ButtonStories.Primary} /> +``` + +```js filename="src/components/Button/Button.stories.js|jsx" renderer="common" language="js" +import { Button } from './Button'; + +export default { + // Sets the name for the stories container + title: 'components/Button', + // The component name will be used if `title` is not set + component: Button, +}; -<Meta of={ExampleComponentStories} /> +// The story variable name will be used if `name` is not set +const Primary = { + // Sets the name for that particular story + name: 'Primary', + args: { + label: 'Button', + }, +}; ``` -```ts filename="src/components/Button/Button.stories.tsx" renderer="common" language="ts-4-9" +```ts filename="src/components/Button/Button.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -39,7 +59,7 @@ const Primary: Story = { }; ``` -```ts filename="src/components/Button/Button.stories.tsx" renderer="common" language="ts" +```ts filename="src/components/Button/Button.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -64,4 +84,3 @@ const Primary: Story = { }, }; ``` - diff --git a/docs/_snippets/document-screen-fetch.md b/docs/_snippets/document-screen-fetch.md index a80c7ec9035f..8c49340ffacb 100644 --- a/docs/_snippets/document-screen-fetch.md +++ b/docs/_snippets/document-screen-fetch.md @@ -45,7 +45,7 @@ export class DocumentScreen implements OnInit { } ``` -```js filename="YourPage.js|jsx|mjs|ts|tsx" renderer="react" language="js" +```js filename="YourPage.jsx" renderer="react" language="js" import React, { useState, useEffect } from 'react'; import { PageLayout } from './PageLayout'; @@ -155,7 +155,7 @@ export function DocumentScreen() { } ``` -```js filename="YourPage.js|jsx|mjs|ts|tsx" renderer="solid" language="js" +```js filename="YourPage.jsx" renderer="solid" language="js" import { createSignal, Match, Switch } from 'solid-js'; import { PageLayout } from './PageLayout'; @@ -211,9 +211,7 @@ export function DocumentScreen() { } ``` -```html renderer="svelte" language="js" -{/* YourPage.svelte */} - +```svelte filename="YourPage.svelte" renderer="svelte" language="js" <script> import { onMount } from 'svelte'; @@ -259,9 +257,7 @@ export function DocumentScreen() { {/if} ``` -```html renderer="svelte" language="ts" -{/* YourPage.svelte */} - +```svelte filename="YourPage.svelte" renderer="svelte" language="ts" <script lang="ts"> import { onMount } from 'svelte'; @@ -307,9 +303,7 @@ export function DocumentScreen() { {/if} ``` -```html renderer="vue" language="js" tabTitle="3" -{/* YourPage.vue */} - +```html filename="YourPage.vue" renderer="vue" language="js" <template> <div v-if="!loading && data && data.subdocuments.length"> <PageLayout :user="data.user"> @@ -358,9 +352,7 @@ export function DocumentScreen() { </script> ``` -```html renderer="vue" language="ts" tabTitle="3" -{/* YourPage.vue */} - +```html filename="YourPage.vue" renderer="vue" language="ts" <template> <div v-if="!loading && data && data.subdocuments.length"> <PageLayout :user="data.user"> @@ -474,4 +466,3 @@ class DocumentScreen extends LitElement { customElements.define('demo-document-screen', DocumentScreen); ``` - diff --git a/docs/_snippets/document-screen-with-graphql.md b/docs/_snippets/document-screen-with-graphql.md index d0368e4d3a82..07421281063a 100644 --- a/docs/_snippets/document-screen-with-graphql.md +++ b/docs/_snippets/document-screen-with-graphql.md @@ -66,7 +66,7 @@ export class SampleGraphqlComponent implements OnInit { } ``` -```js filename="YourPage.js|jsx" renderer="react" language="js" +```js filename="YourPage.jsx" renderer="react" language="js" import { useQuery, gql } from '@apollo/client'; import { PageLayout } from './PageLayout'; @@ -122,7 +122,7 @@ export function DocumentScreen() { } ``` -```ts filename="YourPage.ts|tsx" renderer="react" language="ts" +```ts filename="YourPage.tsx" renderer="react" language="ts" import { useQuery, gql } from '@apollo/client'; import { PageLayout } from './PageLayout'; @@ -202,7 +202,7 @@ export function DocumentScreen() { } ``` -```js filename="YourPage.js|jsx" renderer="solid" language="js" +```js filename="YourPage.jsx" renderer="solid" language="js" import { Match, Switch } from 'solid-js'; import { createGraphQLClient, gql } from '@solid-primitives/graphql'; @@ -263,7 +263,7 @@ export function DocumentScreen() { } ``` -```ts filename="YourPage.ts|tsx" renderer="solid" language="ts" +```ts filename="YourPage.tsx" renderer="solid" language="ts" import { createGraphQLClient, gql } from '@solid-primitives/graphql'; import { PageLayout } from './PageLayout'; @@ -347,9 +347,7 @@ export function DocumentScreen() { } ``` -```html renderer="vue" language="js" tabTitle="3" -{/* YourPage.vue */} - +```html filename="YourPage.vue" renderer="vue" language="js" <template> <div v-if="loading">Loading...</div> @@ -406,9 +404,7 @@ export function DocumentScreen() { </script> ``` -```html renderer="vue" language="ts" tabTitle="3" -{/* YourPage.vue */} - +```html filename="YourPage.vue" renderer="vue" language="ts" <template> <div v-if="loading">Loading...</div> @@ -467,3 +463,92 @@ export function DocumentScreen() { </script> ``` +```svelte filename="YourPage.svelte" renderer="svelte" language="js" +<script> + import gql from 'graphql-tag'; + import { query } from 'svelte-apollo'; + import PageLayout from './PageLayout.svelte'; + import DocumentHeader from './DocumentHeader.svelte'; + import DocumentList from './DocumentList.svelte'; + + const AllInfoQuery = gql` + query AllInfoQuery { + user { + userID + name + } + document { + id + userID + title + brief + status + } + subdocuments { + id + userID + title + content + status + } + } + `; + const infoResult = query(AllInfoQuery); +</script> + +{#if $infoResult.loading} +<p>Loading...</p> +{:else if $infoResult.error} +<p>There was an error fetching the data!</p> +{:else} +<PageLayout {$infoResult.data.user}> + <DocumentHeader {$infoResult.data.document} /> + <DocumentList {$infoResult.data.subdocuments} /> +</PageLayout> +{/if} +``` + +```svelte filename="YourPage.svelte" renderer="svelte" language="ts" +<script lang="ts"> + import gql from 'graphql-tag'; + import { query } from 'svelte-apollo'; + import PageLayout from './PageLayout.svelte'; + import DocumentHeader from './DocumentHeader.svelte'; + import DocumentList from './DocumentList.svelte'; + + const AllInfoQuery = gql` + query AllInfoQuery { + user { + userID + name + } + document { + id + userID + title + brief + status + } + subdocuments { + id + userID + title + content + status + } + } + `; + const infoResult = query(AllInfoQuery); +</script> + +{#if $infoResult.loading} +<p>Loading...</p> +{:else if $infoResult.error} +<p>There was an error fetching the data!</p> +{:else} +<PageLayout {$infoResult.data.user}> + <DocumentHeader {$infoResult.data.document} /> + <DocumentList {$infoResult.data.subdocuments} /> +</PageLayout> +{/if} +``` diff --git a/docs/_snippets/document-screen-with-grapqhl.md b/docs/_snippets/document-screen-with-grapqhl.md deleted file mode 100644 index d5642453b112..000000000000 --- a/docs/_snippets/document-screen-with-grapqhl.md +++ /dev/null @@ -1,94 +0,0 @@ -```html renderer="svelte" language="js" -{/* YourPage.svelte */} - -<script> - import gql from 'graphql-tag'; - import { query } from 'svelte-apollo'; - import PageLayout from './PageLayout.svelte'; - import DocumentHeader from './DocumentHeader.svelte'; - import DocumentList from './DocumentList.svelte'; - - const AllInfoQuery = gql` - query AllInfoQuery { - user { - userID - name - } - document { - id - userID - title - brief - status - } - subdocuments { - id - userID - title - content - status - } - } - `; - const infoResult = query(AllInfoQuery); -</script> - -{#if $infoResult.loading} -<p>Loading...</p> -{:else if $infoResult.error} -<p>There was an error fetching the data!</p> -{:else} -<PageLayout {$infoResult.data.user}> - <DocumentHeader {$infoResult.data.document} /> - <DocumentList {$infoResult.data.subdocuments} /> -</PageLayout> -{/if} -``` - -```html renderer="svelte" language="ts" -{/* YourPage.svelte */} - -<script lang="ts"> - import gql from 'graphql-tag'; - import { query } from 'svelte-apollo'; - import PageLayout from './PageLayout.svelte'; - import DocumentHeader from './DocumentHeader.svelte'; - import DocumentList from './DocumentList.svelte'; - - const AllInfoQuery = gql` - query AllInfoQuery { - user { - userID - name - } - document { - id - userID - title - brief - status - } - subdocuments { - id - userID - title - content - status - } - } - `; - const infoResult = query(AllInfoQuery); -</script> - -{#if $infoResult.loading} -<p>Loading...</p> -{:else if $infoResult.error} -<p>There was an error fetching the data!</p> -{:else} -<PageLayout {$infoResult.data.user}> - <DocumentHeader {$infoResult.data.document} /> - <DocumentList {$infoResult.data.subdocuments} /> -</PageLayout> -{/if} -``` - diff --git a/docs/_snippets/foo-bar-baz-story.md b/docs/_snippets/foo-bar-baz-story.md index bf54630002f1..c510d93af9bf 100644 --- a/docs/_snippets/foo-bar-baz-story.md +++ b/docs/_snippets/foo-bar-baz-story.md @@ -74,4 +74,3 @@ type Story = StoryObj<typeof Foo>; export const Baz: Story = {}; ``` - diff --git a/docs/_snippets/ghp-github-action.md b/docs/_snippets/ghp-github-action.md index 34e407e0615f..975f2af2a473 100644 --- a/docs/_snippets/ghp-github-action.md +++ b/docs/_snippets/ghp-github-action.md @@ -1,6 +1,4 @@ -```yml renderer="common" language="ts" tabTitle="yml" -# .github/workflows/deploy-github-pages.yaml - +```yml filename=".github/workflows/deploy-github-pages.yml" renderer="common" language="js" # Workflow name name: Build and Publish Storybook to GitHub Pages @@ -23,12 +21,12 @@ jobs: steps: # Manual Checkout - uses: actions/checkout@v4 - + with: + fetch-depth: 0 # Set up Node - uses: actions/setup-node@v4 with: - node-version: '20.x' - + node-version: '20' #👇 Add Storybook build and deploy to GitHub Pages as a step in the workflow - uses: bitovi/github-actions-storybook-to-github-pages@v1.0.3 with: @@ -37,4 +35,3 @@ jobs: path: storybook-static # default: dist/storybook checkout: false # default: true ``` - diff --git a/docs/_snippets/gizmo-story-controls-customization.md b/docs/_snippets/gizmo-story-controls-customization.md index 66b09953a883..62d00837517c 100644 --- a/docs/_snippets/gizmo-story-controls-customization.md +++ b/docs/_snippets/gizmo-story-controls-customization.md @@ -57,6 +57,120 @@ const meta: Meta<Gizmo> = { export default meta; ``` +```svelte filename="Gizmo.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Gizmo from './Gizmo.svelte'; + + const { Story } = defineMeta({ + component: Gizmo, + argTypes: { + canRotate: { + control: 'boolean', + }, + width: { + control: { type: 'number', min: 400, max: 1200, step: 50 }, + }, + height: { + control: { type: 'range', min: 200, max: 1500, step: 50 }, + }, + rawData: { + control: 'object', + }, + coordinates: { + control: 'object', + }, + texture: { + control: { + type: 'file', + accept: '.png', + }, + }, + position: { + control: 'radio', + options: ['left', 'right', 'center'], + }, + rotationAxis: { + control: 'check', + options: ['x', 'y', 'z'], + }, + scaling: { + control: 'select', + options: [10, 50, 75, 100, 200], + }, + label: { + control: 'text', + }, + meshColors: { + control: { + type: 'color', + presetColors: ['#ff0000', '#00ff00', '#0000ff'], + }, + }, + revisionDate: { + control: 'date', + }, + }, + }); +</script> +``` + +```js filename="Gizmo.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Gizmo from './Gizmo.svelte'; + +export default { + component: Gizmo, + argTypes: { + canRotate: { + control: 'boolean', + }, + width: { + control: { type: 'number', min: 400, max: 1200, step: 50 }, + }, + height: { + control: { type: 'range', min: 200, max: 1500, step: 50 }, + }, + rawData: { + control: 'object', + }, + coordinates: { + control: 'object', + }, + texture: { + control: { + type: 'file', + accept: '.png', + }, + }, + position: { + control: 'radio', + options: ['left', 'right', 'center'], + }, + rotationAxis: { + control: 'check', + options: ['x', 'y', 'z'], + }, + scaling: { + control: 'select', + options: [10, 50, 75, 100, 200], + }, + label: { + control: 'text', + }, + meshColors: { + control: { + type: 'color', + presetColors: ['#ff0000', '#00ff00', '#0000ff'], + }, + }, + revisionDate: { + control: 'date', + }, + }, +}; +``` + ```js filename="Gizmo.stories.js|jsx" renderer="common" language="js" import { Gizmo } from './Gizmo'; @@ -112,6 +226,124 @@ export default { }; ``` +```svelte filename="Gizmo.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Gizmo from './Gizmo.svelte'; + + const { Story } = defineMeta({ + component: Gizmo, + argTypes: { + canRotate: { + control: 'boolean', + }, + width: { + control: { type: 'number', min: 400, max: 1200, step: 50 }, + }, + height: { + control: { type: 'range', min: 200, max: 1500, step: 50 }, + }, + rawData: { + control: 'object', + }, + coordinates: { + control: 'object', + }, + texture: { + control: { + type: 'file', + accept: '.png', + }, + }, + position: { + control: 'radio', + options: ['left', 'right', 'center'], + }, + rotationAxis: { + control: 'check', + options: ['x', 'y', 'z'], + }, + scaling: { + control: 'select', + options: [10, 50, 75, 100, 200], + }, + label: { + control: 'text', + }, + meshColors: { + control: { + type: 'color', + presetColors: ['#ff0000', '#00ff00', '#0000ff'], + }, + }, + revisionDate: { + control: 'date', + }, + }, + }); +</script> +``` + +```ts filename="Gizmo.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Gizmo from './Gizmo.svelte'; + +const meta = { + component: Gizmo, + argTypes: { + canRotate: { + control: 'boolean', + }, + width: { + control: { type: 'number', min: 400, max: 1200, step: 50 }, + }, + height: { + control: { type: 'range', min: 200, max: 1500, step: 50 }, + }, + rawData: { + control: 'object', + }, + coordinates: { + control: 'object', + }, + texture: { + control: { + type: 'file', + accept: '.png', + }, + }, + position: { + control: 'radio', + options: ['left', 'right', 'center'], + }, + rotationAxis: { + control: 'check', + options: ['x', 'y', 'z'], + }, + scaling: { + control: 'select', + options: [10, 50, 75, 100, 200], + }, + label: { + control: 'text', + }, + meshColors: { + control: { + type: 'color', + presetColors: ['#ff0000', '#00ff00', '#0000ff'], + }, + }, + revisionDate: { + control: 'date', + }, + }, +} satisfies Meta<typeof Gizmo>; + +export default meta; +``` + ```ts filename="Gizmo.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -172,6 +404,124 @@ const meta = { export default meta; ``` +```svelte filename="Gizmo.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Gizmo from './Gizmo.svelte'; + + const { Story } = defineMeta({ + component: Gizmo, + argTypes: { + canRotate: { + control: 'boolean', + }, + width: { + control: { type: 'number', min: 400, max: 1200, step: 50 }, + }, + height: { + control: { type: 'range', min: 200, max: 1500, step: 50 }, + }, + rawData: { + control: 'object', + }, + coordinates: { + control: 'object', + }, + texture: { + control: { + type: 'file', + accept: '.png', + }, + }, + position: { + control: 'radio', + options: ['left', 'right', 'center'], + }, + rotationAxis: { + control: 'check', + options: ['x', 'y', 'z'], + }, + scaling: { + control: 'select', + options: [10, 50, 75, 100, 200], + }, + label: { + control: 'text', + }, + meshColors: { + control: { + type: 'color', + presetColors: ['#ff0000', '#00ff00', '#0000ff'], + }, + }, + revisionDate: { + control: 'date', + }, + }, + }); +</script> +``` + +```ts filename="Gizmo.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Gizmo from './Gizmo.svelte'; + +const meta: Meta<typeof Gizmo> = { + component: Gizmo, + argTypes: { + canRotate: { + control: 'boolean', + }, + width: { + control: { type: 'number', min: 400, max: 1200, step: 50 }, + }, + height: { + control: { type: 'range', min: 200, max: 1500, step: 50 }, + }, + rawData: { + control: 'object', + }, + coordinates: { + control: 'object', + }, + texture: { + control: { + type: 'file', + accept: '.png', + }, + }, + position: { + control: 'radio', + options: ['left', 'right', 'center'], + }, + rotationAxis: { + control: 'check', + options: ['x', 'y', 'z'], + }, + scaling: { + control: 'select', + options: [10, 50, 75, 100, 200], + }, + label: { + control: 'text', + }, + meshColors: { + control: { + type: 'color', + presetColors: ['#ff0000', '#00ff00', '#0000ff'], + }, + }, + revisionDate: { + control: 'date', + }, + }, +}; + +export default meta; +``` + ```ts filename="Gizmo.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -341,4 +691,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/highlight-addon-custom-style.md b/docs/_snippets/highlight-addon-custom-style.md index 835ea2f966ef..05c3e9603180 100644 --- a/docs/_snippets/highlight-addon-custom-style.md +++ b/docs/_snippets/highlight-addon-custom-style.md @@ -249,4 +249,3 @@ export const StyledHighlight: Story = { ], }; ``` - diff --git a/docs/_snippets/histogram-story.md b/docs/_snippets/histogram-story.md index 7571d7ad7e78..fd6464be9432 100644 --- a/docs/_snippets/histogram-story.md +++ b/docs/_snippets/histogram-story.md @@ -227,23 +227,36 @@ export const Default: Story = { }; ``` -```js filename="Histogram.stories.js" renderer="svelte" language="js" +```svelte filename="Histogram.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Histogram from './Histogram.svelte'; + + const { Story } = defineMeta({ + component: Histogram, + }); +</script> + +<Story + name="Default" + args={{ + dataType: 'latency', + showHistogramLabels: true, + histogramAccentColor: '#1EA7FD', + label: 'Latency distribution', + }} +/> +``` + +```js filename="Histogram.stories.js" renderer="svelte" language="js" tabTitle="CSF" import Histogram from './Histogram.svelte'; export default { component: Histogram, }; -/* - *👇 Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const Default = { - render: (args) => ({ - Component: Histogram, - props: args, - }), args: { dataType: 'latency', showHistogramLabels: true, @@ -253,7 +266,29 @@ export const Default = { }; ``` -```ts filename="Histogram.stories.ts" renderer="svelte" language="ts-4-9" +```svelte filename="Histogram.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Histogram from './Histogram.svelte'; + + const { Story } = defineMeta({ + component: Histogram, + }); +</script> + +<Story + name="Default" + args={{ + dataType: 'latency', + showHistogramLabels: true, + histogramAccentColor: '#1EA7FD', + label: 'Latency distribution', + }} +/> +``` + +```ts filename="Histogram.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Histogram from './Histogram.svelte'; @@ -265,16 +300,7 @@ const meta = { export default meta; type Story = StoryObj<typeof meta>; -/* - *👇 Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const Default: Story = { - render: (args) => ({ - Component: Histogram, - props: args, - }), args: { dataType: 'latency', showHistogramLabels: true, @@ -284,7 +310,29 @@ export const Default: Story = { }; ``` -```ts filename="Histogram.stories.ts" renderer="svelte" language="ts" +```svelte filename="Histogram.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Histogram from './Histogram.svelte'; + + const { Story } = defineMeta({ + component: Histogram, + }); +</script> + +<Story + name="Default" + args={{ + dataType: 'latency', + showHistogramLabels: true, + histogramAccentColor: '#1EA7FD', + label: 'Latency distribution', + }} +/> +``` + +```ts filename="Histogram.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Histogram from './Histogram.svelte'; @@ -296,16 +344,7 @@ const meta: Meta<typeof Histogram> = { export default meta; type Story = StoryObj<typeof meta>; -/* - *👇 Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const Default: Story = { - render: (args) => ({ - Component: Histogram, - props: args, - }), args: { dataType: 'latency', showHistogramLabels: true, @@ -315,7 +354,7 @@ export const Default: Story = { }; ``` -```js filename="Histogram.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="Histogram.stories.js" renderer="vue" language="js" import Histogram from './Histogram.vue'; export default { @@ -344,7 +383,7 @@ export const Default = { }; ``` -```ts filename="Histogram.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="Histogram.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import Histogram from './Histogram.vue'; @@ -378,7 +417,7 @@ export const Default: Story = { }; ``` -```ts filename="Histogram.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="Histogram.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import Histogram from './Histogram.vue'; @@ -446,4 +485,3 @@ export const Default: Story = { }, }; ``` - diff --git a/docs/_snippets/init-command-custom-package-manager.md b/docs/_snippets/init-command-custom-package-manager.md index da6d52b3b49b..d7729e174ecd 100644 --- a/docs/_snippets/init-command-custom-package-manager.md +++ b/docs/_snippets/init-command-custom-package-manager.md @@ -1,4 +1,4 @@ -```shell renderer="common" language="js" packageManager="npx" +```shell renderer="common" language="js" packageManager="npm" npx storybook@latest init --package-manager=npm ``` @@ -9,4 +9,3 @@ pnpm dlx storybook@latest init --package-manager=npm ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@latest init --package-manager=npm ``` - diff --git a/docs/_snippets/init-command-manual-framework.md b/docs/_snippets/init-command-manual-framework.md index f20a762ab79f..6818860a456d 100644 --- a/docs/_snippets/init-command-manual-framework.md +++ b/docs/_snippets/init-command-manual-framework.md @@ -1,4 +1,4 @@ -```shell renderer="common" language="js" packageManager="npx" +```shell renderer="common" language="js" packageManager="npm" npx storybook@latest init --type solid ``` @@ -9,4 +9,3 @@ pnpm dlx storybook@latest init --type solid ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@latest init --type solid ``` - diff --git a/docs/_snippets/init-command.md b/docs/_snippets/init-command.md index 4d6563e2ef84..db2da5924dfd 100644 --- a/docs/_snippets/init-command.md +++ b/docs/_snippets/init-command.md @@ -1,12 +1,11 @@ -```shell renderer="common" language="js" packageManager="npx" -npx storybook@latest init +```shell renderer="common" language="js" packageManager="npm" +npx storybook@next init ``` ```shell renderer="common" language="js" packageManager="pnpm" -pnpm dlx storybook@latest init +pnpm dlx storybook@next init ``` ```shell renderer="common" language="js" packageManager="yarn" -yarn dlx storybook@latest init +yarn dlx storybook@next init ``` - diff --git a/docs/_snippets/list-story-expanded.md b/docs/_snippets/list-story-expanded.md index d7a86fb93a14..f1c321b828d2 100644 --- a/docs/_snippets/list-story-expanded.md +++ b/docs/_snippets/list-story-expanded.md @@ -358,42 +358,103 @@ export const ManyItems: Story = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* List.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; +```svelte filename="List.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import List from './List.svelte'; + import ListItem from './ListItem.svelte'; + + const { Story } = defineMeta({ + component: List, + }); +</script> + +<Story name="Empty" /> + +<Story name="One Item"> + {#snippet children(args)} + <List {...args} > + <ListItem /> + </List> + {/snippet} +</Story> + +<Story name="Many Items"> + {#snippet children(args)} + <List {...args} > + <ListItem /> + <ListItem /> + <ListItem /> + </List> + {/snippet} +</Story> +``` +```svelte filename="List.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import List from './List.svelte'; import ListItem from './ListItem.svelte'; + + const { Story } = defineMeta({ + component: List, + }); </script> -<meta title="List" component="{List}" /> +<Story name="Empty" /> + +<Story name="One Item"> + {#snippet children(args)} + <List {...args} > + <ListItem /> + </List> + {/snippet} +</Story> -<template let:args id="Empty"> - <List {...args} /> -</template> +<Story name="Many Items"> + {#snippet children(args)} + <List {...args} > + <ListItem /> + <ListItem /> + <ListItem /> + </List> + {/snippet} +</Story> +``` -<template let:args id="OneItem"> - <List {...args}> - <ListItem /> - </List> -</template> +```svelte filename="List.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import List from './List.svelte'; + import ListItem from './ListItem.svelte'; -<template let:args id="ManyItems"> - <List {...args}> - <ListItem /> - <ListItem /> - <ListItem /> - </List> -</template> + const { Story } = defineMeta({ + component: List, + }); +</script> -<Story name="Empty" template="Empty" /> +<Story name="Empty" /> -<Story name="OneItem" template="OneItem" /> +<Story name="One Item"> + {#snippet children(args)} + <List {...args} > + <ListItem /> + </List> + {/snippet} +</Story> -<Story name="MultipleItems" template="ManyItems" /> +<Story name="Many Items"> + {#snippet children(args)} + <List {...args} > + <ListItem /> + <ListItem /> + <ListItem /> + </List> + {/snippet} +</Story> ``` ```js filename="List.stories.js" renderer="vue" language="js" @@ -599,4 +660,3 @@ export const ManyItems: Story = { `, }; ``` - diff --git a/docs/_snippets/list-story-reuse-data.md b/docs/_snippets/list-story-reuse-data.md index aae3098c609c..7de27f68a2e0 100644 --- a/docs/_snippets/list-story-reuse-data.md +++ b/docs/_snippets/list-story-reuse-data.md @@ -245,7 +245,7 @@ export const ManyItems: Story = { }; ``` -```js filename="List.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="List.stories.js" renderer="vue" language="js" import List from './ListComponent.vue'; import ListItem from './ListItem.vue'; @@ -276,7 +276,7 @@ export const ManyItems = { }; ``` -```ts filename="List.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="List.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import List from './ListComponent.vue'; @@ -312,7 +312,7 @@ export const ManyItems: Story = { }; ``` -```ts filename="List.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="List.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import List from './ListComponent.vue'; @@ -392,4 +392,3 @@ export const ManyItems: Story = { `, }; ``` - diff --git a/docs/_snippets/list-story-starter.md b/docs/_snippets/list-story-starter.md index e5111efdf5f4..09215a1d1dea 100644 --- a/docs/_snippets/list-story-starter.md +++ b/docs/_snippets/list-story-starter.md @@ -76,7 +76,6 @@ export default { }; // Always an empty list, not super interesting - export const Empty = {}; ``` @@ -92,7 +91,7 @@ const meta = { export default meta; type Story = StoryObj<typeof meta>; -//👇 Always an empty list, not super interesting +// Always an empty list, not super interesting export const Empty: Story = {}; ``` @@ -108,7 +107,7 @@ const meta: Meta<typeof List> = { export default meta; type Story = StoryObj<typeof List>; -//👇 Always an empty list, not super interesting +// Always an empty list, not super interesting export const Empty: Story = {}; ``` @@ -120,7 +119,6 @@ export default { }; // Always an empty list, not super interesting - export const Empty = {}; ``` @@ -136,7 +134,7 @@ const meta = { export default meta; type Story = StoryObj<typeof meta>; -//👇 Always an empty list, not super interesting +// Always an empty list, not super interesting export const Empty: Story = {}; ``` @@ -152,28 +150,96 @@ const meta: Meta<typeof List> = { export default meta; type Story = StoryObj<typeof List>; -//👇 Always an empty list, not super interesting +// Always an empty list, not super interesting export const Empty: Story = {}; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* List.stories.svelte */} +```svelte filename="List.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import List from './List.svelte'; + + const { Story } = defineMeta({ + component: List, + }); +</script> + +<!-- Always an empty list, not super interesting --> +<Story name="Empty" /> +``` + +```js filename="List.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import List from './List.svelte'; + +export default { + component: List, +}; + +// Always an empty list, not super interesting +export const Empty = {}; +``` + +```svelte filename="List.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import List from './List.svelte'; + + const { Story } = defineMeta({ + component: List, + }); +</script> + +<!-- Always an empty list, not super interesting --> +<Story name="Empty" /> +``` + +```ts filename="List.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import List from './List.svelte'; + +const meta = { + component: List, +} satisfies Meta<typeof List>; + +export default meta; +type Story = StoryObj<typeof meta>; + +// Always an empty list, not super interesting +export const Empty: Story = {}; +``` -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; +```svelte filename="List.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import List from './List.svelte'; + + const { Story } = defineMeta({ + component: List, + }); </script> -<meta title="List" component="{List}" /> +<!-- Always an empty list, not super interesting --> +<Story name="Empty" /> +``` + +```ts filename="List.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import List from './List.svelte'; -<template let:args> - <List {...args} /> -</template> +const meta: Meta<typeof List> = { + component: List, +}; -<Story name="Empty"> - <List {...args} /> -</Story> +export default meta; +type Story = StoryObj<typeof List>; + +// Always an empty list, not super interesting +export const Empty: Story = {}; ``` ```js filename="List.stories.js" renderer="vue" language="js" @@ -262,4 +328,3 @@ export const Empty: Story = { render: () => html`<demo-list></demo-list>`, }; ``` - diff --git a/docs/_snippets/list-story-template.md b/docs/_snippets/list-story-template.md index b92ee09399ff..31c6ca75d8cc 100644 --- a/docs/_snippets/list-story-template.md +++ b/docs/_snippets/list-story-template.md @@ -352,7 +352,7 @@ export const OneItem = { }; ``` -```js filename="List.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="List.stories.js" renderer="vue" language="js" import List from './List.vue'; import ListItem from './ListItem.vue'; @@ -403,7 +403,7 @@ export const OneItem = { }; ``` -```ts filename="List.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="List.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import List from './List.vue'; @@ -459,7 +459,7 @@ export const OneItem: Story = { }; ``` -```ts filename="List.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="List.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import List from './List.vue'; @@ -598,4 +598,3 @@ export const OneItem: Story = { }, }; ``` - diff --git a/docs/_snippets/list-story-unchecked.md b/docs/_snippets/list-story-unchecked.md index fd51261b9f1c..5fe08eeffdfb 100644 --- a/docs/_snippets/list-story-unchecked.md +++ b/docs/_snippets/list-story-unchecked.md @@ -213,7 +213,7 @@ export const OneItem: Story = { }; ``` -```js filename="List.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="List.stories.js" renderer="vue" language="js" import List from './List.vue'; import ListItem from './ListItem.vue'; @@ -249,7 +249,7 @@ export const OneItem = { }; ``` -```ts filename="List.stories.js" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="List.stories.js" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import List from './List.vue'; @@ -290,7 +290,7 @@ export const OneItem: Story = { }; ``` -```ts filename="List.stories.js" renderer="vue" language="ts" tabTitle="3" +```ts filename="List.stories.js" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import List from './List.vue'; @@ -367,4 +367,3 @@ export const OneItem: Story = { render: () => html` <List> ${Unchecked({ ...Unchecked.args })} </List> `, }; ``` - diff --git a/docs/_snippets/list-story-with-sub-components.md b/docs/_snippets/list-story-with-sub-components.md deleted file mode 100644 index 27b866230d51..000000000000 --- a/docs/_snippets/list-story-with-sub-components.md +++ /dev/null @@ -1,91 +0,0 @@ -```js filename="List.stories.js" renderer="vue" language="js" -import List from './List.vue'; -import ListItem from './ListItem.vue'; - -export default { - component: List, - subcomponents: { ListItem }, //👈 Adds the ListItem component as a subcomponent -}; - -export const Empty = { - render: () => ({ - components: { List }, - template: '<List/>', - }), -}; - -export const OneItem = { - render: (args) => ({ - components: { List, ListItem }, - setup() { - return { args } - } - template: '<List v-bind="args"><ListItem /></List>', - }), -}; -``` - -```ts filename="List.stories.ts" renderer="vue" language="ts-4-9" -import type { Meta, StoryObj } from '@storybook/vue3'; - -import List from './List.vue'; -import ListItem from './ListItem.vue'; - -const meta = { - component: List, - subcomponents: { ListItem }, //👈 Adds the ListItem component as a subcomponent -} satisfies Meta<typeof List>; -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Empty: Story = { - render: () => ({ - components: { List }, - template: '<List />', - }), -}; - -export const OneItem: Story = { - render: (args) => ({ - components: { List, ListItem }, - setup() { - return { args } - } - template: '<List v-bind="args"><ListItem /></List>', - }), -}; -``` - -```ts filename="List.stories.ts" renderer="vue" language="ts" -import type { Meta, StoryObj } from '@storybook/vue3'; - -import List from './List.vue'; -import ListItem from './ListItem.vue'; - -const meta: Meta<typeof List> = { - component: List, - subcomponents: { ListItem }, //👈 Adds the ListItem component as a subcomponent -}; -export default meta; - -type Story = StoryObj<typeof List>; - -export const Empty: Story = { - render: () => ({ - components: { List }, - template: '<List />', - }), -}; - -export const OneItem: Story = { - render: (args) => ({ - components: { List, ListItem }, - setup() { - return { args } - } - template: '<List v-bind="args"><ListItem /></List>', - }), -}; -``` - diff --git a/docs/_snippets/list-story-with-subcomponents.md b/docs/_snippets/list-story-with-subcomponents.md index e0a7fdf53a7d..44a05aade665 100644 --- a/docs/_snippets/list-story-with-subcomponents.md +++ b/docs/_snippets/list-story-with-subcomponents.md @@ -242,3 +242,93 @@ export const OneItem: Story = { }; ``` +```js filename="List.stories.js" renderer="vue" language="js" +import List from './List.vue'; +import ListItem from './ListItem.vue'; + +export default { + component: List, + subcomponents: { ListItem }, //👈 Adds the ListItem component as a subcomponent +}; + +export const Empty = { + render: () => ({ + components: { List }, + template: '<List/>', + }), +}; + +export const OneItem = { + render: (args) => ({ + components: { List, ListItem }, + setup() { + return { args } + } + template: '<List v-bind="args"><ListItem /></List>', + }), +}; +``` + +```ts filename="List.stories.ts" renderer="vue" language="ts-4-9" +import type { Meta, StoryObj } from '@storybook/vue3'; + +import List from './List.vue'; +import ListItem from './ListItem.vue'; + +const meta = { + component: List, + subcomponents: { ListItem }, //👈 Adds the ListItem component as a subcomponent +} satisfies Meta<typeof List>; +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Empty: Story = { + render: () => ({ + components: { List }, + template: '<List />', + }), +}; + +export const OneItem: Story = { + render: (args) => ({ + components: { List, ListItem }, + setup() { + return { args } + } + template: '<List v-bind="args"><ListItem /></List>', + }), +}; +``` + +```ts filename="List.stories.ts" renderer="vue" language="ts" +import type { Meta, StoryObj } from '@storybook/vue3'; + +import List from './List.vue'; +import ListItem from './ListItem.vue'; + +const meta: Meta<typeof List> = { + component: List, + subcomponents: { ListItem }, //👈 Adds the ListItem component as a subcomponent +}; +export default meta; + +type Story = StoryObj<typeof List>; + +export const Empty: Story = { + render: () => ({ + components: { List }, + template: '<List />', + }), +}; + +export const OneItem: Story = { + render: (args) => ({ + components: { List, ListItem }, + setup() { + return { args } + } + template: '<List v-bind="args"><ListItem /></List>', + }), +}; +``` diff --git a/docs/_snippets/list-story-with-unchecked-children.md b/docs/_snippets/list-story-with-unchecked-children.md index 7f2843705a94..695ec926432a 100644 --- a/docs/_snippets/list-story-with-unchecked-children.md +++ b/docs/_snippets/list-story-with-unchecked-children.md @@ -149,4 +149,3 @@ export const OneItem: Story = { }, }; ``` - diff --git a/docs/_snippets/loader-story.md b/docs/_snippets/loader-story.md index d0b4706e0095..a777c0e2e922 100644 --- a/docs/_snippets/loader-story.md +++ b/docs/_snippets/loader-story.md @@ -424,4 +424,3 @@ export const Primary: Story = { ], }; ``` - diff --git a/docs/_snippets/login-form-with-play-function.md b/docs/_snippets/login-form-with-play-function.md index 12a24031604f..50cb48daa0d9 100644 --- a/docs/_snippets/login-form-with-play-function.md +++ b/docs/_snippets/login-form-with-play-function.md @@ -33,8 +33,8 @@ export const FilledForm: Story = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; @@ -70,8 +70,8 @@ export const FilledForm = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; @@ -112,8 +112,8 @@ export const FilledForm: Story = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; @@ -154,8 +154,8 @@ export const FilledForm: Story = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; @@ -191,8 +191,8 @@ export const FilledForm = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; @@ -235,8 +235,8 @@ export const FilledForm: Story = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; @@ -279,14 +279,55 @@ export const FilledForm: Story = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; ``` -```js filename="LoginForm.stories.js" renderer="svelte" language="js" +```svelte filename="LoginForm.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + import { expect, userEvent, within } from '@storybook/test'; + + import LoginForm from './LoginForm.svelte'; + + const { Story } = defineMeta({ + component: LoginForm, + }); +</script> + +<Story name="EmptyForm" /> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="FilledForm" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // 👇 Simulate interactions with the component + await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); + + await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + + // 👇 Assert DOM structure + await expect( + canvas.getByText( + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) + ).toBeInTheDocument(); + }} +/> +``` + +```js filename="LoginForm.stories.js" renderer="svelte" language="js" tabTitle="CSF" import { expect, userEvent, within } from '@storybook/test'; import LoginForm from './LoginForm.svelte'; @@ -316,14 +357,55 @@ export const FilledForm = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; ``` -```ts filename="LoginForm.stories.ts" renderer="svelte" language="ts-4-9" +```svelte filename="LoginForm.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + import { expect, userEvent, within } from '@storybook/test'; + + import LoginForm from './LoginForm.svelte'; + + const { Story } = defineMeta({ + component: LoginForm, + }); +</script> + +<Story name="EmptyForm" /> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="FilledForm" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // 👇 Simulate interactions with the component + await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); + + await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + + // 👇 Assert DOM structure + await expect( + canvas.getByText( + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) + ).toBeInTheDocument(); + }} +/> +``` + +```ts filename="LoginForm.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import { expect, userEvent, within } from '@storybook/test'; @@ -357,14 +439,56 @@ export const FilledForm: Story = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; ``` -```ts filename="LoginForm.stories.ts" renderer="svelte" language="ts" +```svelte filename="LoginForm.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + import { expect, userEvent, within } from '@storybook/test'; + + import LoginForm from './LoginForm.svelte'; + + const { Story } = defineMeta({ + component: LoginForm, + }); + +</script> + +<Story name="EmptyForm" /> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="FilledForm" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // 👇 Simulate interactions with the component + await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); + + await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + + // 👇 Assert DOM structure + await expect( + canvas.getByText( + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) + ).toBeInTheDocument(); + }} +/> +``` + +```ts filename="LoginForm.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import { expect, userEvent, within } from '@storybook/test'; @@ -398,8 +522,8 @@ export const FilledForm: Story = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; @@ -444,8 +568,8 @@ export const FilledForm = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; @@ -495,8 +619,8 @@ export const FilledForm: Story = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; @@ -546,8 +670,8 @@ export const FilledForm: Story = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; @@ -581,8 +705,8 @@ export const FilledForm = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; @@ -620,10 +744,9 @@ export const FilledForm: Story = { // 👇 Assert DOM structure await expect( canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!', - ), + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) ).toBeInTheDocument(); }, }; ``` - diff --git a/docs/_snippets/main-config-addons.md b/docs/_snippets/main-config-addons.md index d7a0ee94fd90..497402137c04 100644 --- a/docs/_snippets/main-config-addons.md +++ b/docs/_snippets/main-config-addons.md @@ -63,4 +63,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-babel.md b/docs/_snippets/main-config-babel.md index a84c1b8e7fbf..461b07c96f80 100644 --- a/docs/_snippets/main-config-babel.md +++ b/docs/_snippets/main-config-babel.md @@ -35,4 +35,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-builder-custom-config.md b/docs/_snippets/main-config-builder-custom-config.md index d7e77531b4b2..42ee9456cb46 100644 --- a/docs/_snippets/main-config-builder-custom-config.md +++ b/docs/_snippets/main-config-builder-custom-config.md @@ -11,4 +11,3 @@ export default { }, }; ``` - diff --git a/docs/_snippets/main-config-core-builder.md b/docs/_snippets/main-config-core-builder.md index 3f99dd9a7854..59bac17fdfe6 100644 --- a/docs/_snippets/main-config-core-builder.md +++ b/docs/_snippets/main-config-core-builder.md @@ -53,4 +53,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-core-cross-origin-isolated.md b/docs/_snippets/main-config-core-cross-origin-isolated.md index 0220b9279e86..9dd3de4a0c14 100644 --- a/docs/_snippets/main-config-core-cross-origin-isolated.md +++ b/docs/_snippets/main-config-core-cross-origin-isolated.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-core-disable-project-json.md b/docs/_snippets/main-config-core-disable-project-json.md index ec0479ff729d..a3ee05092236 100644 --- a/docs/_snippets/main-config-core-disable-project-json.md +++ b/docs/_snippets/main-config-core-disable-project-json.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-core-disable-telemetry.md b/docs/_snippets/main-config-core-disable-telemetry.md index da71438e89ad..7ae7d19ce9ad 100644 --- a/docs/_snippets/main-config-core-disable-telemetry.md +++ b/docs/_snippets/main-config-core-disable-telemetry.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-core-disable-update-notifications.md b/docs/_snippets/main-config-core-disable-update-notifications.md index 79f13ab69fbd..4690f91dff3b 100644 --- a/docs/_snippets/main-config-core-disable-update-notifications.md +++ b/docs/_snippets/main-config-core-disable-update-notifications.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-core-disable-webpack-defaults.md b/docs/_snippets/main-config-core-disable-webpack-defaults.md index 9de06b3e3e49..872865235bb7 100644 --- a/docs/_snippets/main-config-core-disable-webpack-defaults.md +++ b/docs/_snippets/main-config-core-disable-webpack-defaults.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-core-enable-crash-reports.md b/docs/_snippets/main-config-core-enable-crash-reports.md index 50d44d8a7c31..32f436b273ae 100644 --- a/docs/_snippets/main-config-core-enable-crash-reports.md +++ b/docs/_snippets/main-config-core-enable-crash-reports.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-csf-addon-register.md b/docs/_snippets/main-config-csf-addon-register.md deleted file mode 100644 index d38fecb2ffa1..000000000000 --- a/docs/_snippets/main-config-csf-addon-register.md +++ /dev/null @@ -1,28 +0,0 @@ -```js filename=".storybook/main.js" renderer="svelte" language="js" -export default { - // Replace sveltekit with svelte-vite if you are not working with SvelteKit - framework: '@storybook/sveltekit', - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx|svelte)'], - addons: [ - // Other Storybook addons - '@storybook/addon-svelte-csf', //👈 The Svelte CSF addon goes here - ], -}; -``` - -```ts filename=".storybook/main.ts" renderer="svelte" language="ts" -// Replace sveltekit with svelte-vite if you are not working with SvelteKit -import type { StorybookConfig } from '@storybook/sveltekit'; - -const config: StorybookConfig = { - framework: '@storybook/sveltekit', - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx|svelte)'], - addons: [ - // Other Storybook addons - '@storybook/addon-svelte-csf', //👈 The Svelte CSF addon goes here - ], -}; - -export default config; -``` - diff --git a/docs/_snippets/main-config-docs-autodocs.md b/docs/_snippets/main-config-docs-autodocs.md index eab7ca0e6959..7fef4184f37e 100644 --- a/docs/_snippets/main-config-docs-autodocs.md +++ b/docs/_snippets/main-config-docs-autodocs.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-docs-default-name.md b/docs/_snippets/main-config-docs-default-name.md index 7f37237c76ec..181354867f7e 100644 --- a/docs/_snippets/main-config-docs-default-name.md +++ b/docs/_snippets/main-config-docs-default-name.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-docs-docs-mode.md b/docs/_snippets/main-config-docs-docs-mode.md index 7b93d17627ed..8e90c952e9b2 100644 --- a/docs/_snippets/main-config-docs-docs-mode.md +++ b/docs/_snippets/main-config-docs-docs-mode.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-env.md b/docs/_snippets/main-config-env.md index 19d4f7e8f7a6..677be576fa72 100644 --- a/docs/_snippets/main-config-env.md +++ b/docs/_snippets/main-config-env.md @@ -33,4 +33,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-features-arg-type-targets-v7.md b/docs/_snippets/main-config-features-arg-type-targets-v7.md index 72cb3cfce324..5b03ccd0090f 100644 --- a/docs/_snippets/main-config-features-arg-type-targets-v7.md +++ b/docs/_snippets/main-config-features-arg-type-targets-v7.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-features-legacy-decorator-file-order.md b/docs/_snippets/main-config-features-legacy-decorator-file-order.md index fc16fd76a9a0..f44c53f53220 100644 --- a/docs/_snippets/main-config-features-legacy-decorator-file-order.md +++ b/docs/_snippets/main-config-features-legacy-decorator-file-order.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-framework.md b/docs/_snippets/main-config-framework.md index 4b7e64958921..b2701eeb52a2 100644 --- a/docs/_snippets/main-config-framework.md +++ b/docs/_snippets/main-config-framework.md @@ -27,4 +27,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-indexers-jsonstories.md b/docs/_snippets/main-config-indexers-jsonstories.md index 1e279464c9d7..8d0ea9c1b7f4 100644 --- a/docs/_snippets/main-config-indexers-jsonstories.md +++ b/docs/_snippets/main-config-indexers-jsonstories.md @@ -101,4 +101,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-indexers-title.md b/docs/_snippets/main-config-indexers-title.md index febd48d4c8d6..33f3ad714c30 100644 --- a/docs/_snippets/main-config-indexers-title.md +++ b/docs/_snippets/main-config-indexers-title.md @@ -89,4 +89,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-indexers.md b/docs/_snippets/main-config-indexers.md index b86c0c7ddefa..544f8d2b98c9 100644 --- a/docs/_snippets/main-config-indexers.md +++ b/docs/_snippets/main-config-indexers.md @@ -65,4 +65,3 @@ const config: StorybookConfig = { export default config ``` - diff --git a/docs/_snippets/main-config-log-level.md b/docs/_snippets/main-config-log-level.md index 3f273bc15f7c..2d57e78eb994 100644 --- a/docs/_snippets/main-config-log-level.md +++ b/docs/_snippets/main-config-log-level.md @@ -19,4 +19,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-manager-head.md b/docs/_snippets/main-config-manager-head.md index af295c0b1247..363e168040a8 100644 --- a/docs/_snippets/main-config-manager-head.md +++ b/docs/_snippets/main-config-manager-head.md @@ -25,4 +25,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-preview-body.md b/docs/_snippets/main-config-preview-body.md index 5fbbcfac8e8f..0f8c36d65ebe 100644 --- a/docs/_snippets/main-config-preview-body.md +++ b/docs/_snippets/main-config-preview-body.md @@ -29,4 +29,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-preview-head.md b/docs/_snippets/main-config-preview-head.md index 3a95e2a7fdc6..c892c84164af 100644 --- a/docs/_snippets/main-config-preview-head.md +++ b/docs/_snippets/main-config-preview-head.md @@ -29,4 +29,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-preview.md b/docs/_snippets/main-config-preview.md index 706563a2ae96..2e849eabd534 100644 --- a/docs/_snippets/main-config-preview.md +++ b/docs/_snippets/main-config-preview.md @@ -55,4 +55,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-refs-disable.md b/docs/_snippets/main-config-refs-disable.md index 8b99555794a1..40d9830d9943 100644 --- a/docs/_snippets/main-config-refs-disable.md +++ b/docs/_snippets/main-config-refs-disable.md @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-refs-with-function.md b/docs/_snippets/main-config-refs-with-function.md index 5b48a9b60f16..b94608356b25 100644 --- a/docs/_snippets/main-config-refs-with-function.md +++ b/docs/_snippets/main-config-refs-with-function.md @@ -69,4 +69,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-static-dirs-with-object.md b/docs/_snippets/main-config-static-dirs-with-object.md index 3a0aa7954bb9..ae6e78369d91 100644 --- a/docs/_snippets/main-config-static-dirs-with-object.md +++ b/docs/_snippets/main-config-static-dirs-with-object.md @@ -19,4 +19,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-static-dirs.md b/docs/_snippets/main-config-static-dirs.md index 3d8514d18885..c4537d4f0e82 100644 --- a/docs/_snippets/main-config-static-dirs.md +++ b/docs/_snippets/main-config-static-dirs.md @@ -19,4 +19,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-stories-ordered.md b/docs/_snippets/main-config-stories-ordered.md index 41902cb5b140..972589b0ab42 100644 --- a/docs/_snippets/main-config-stories-ordered.md +++ b/docs/_snippets/main-config-stories-ordered.md @@ -20,4 +20,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-stories-with-logic.md b/docs/_snippets/main-config-stories-with-logic.md index 43021b00b526..2baa4ceb91a1 100644 --- a/docs/_snippets/main-config-stories-with-logic.md +++ b/docs/_snippets/main-config-stories-with-logic.md @@ -34,4 +34,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-stories-with-object.md b/docs/_snippets/main-config-stories-with-object.md index a26aebd7f425..a08c476c79c0 100644 --- a/docs/_snippets/main-config-stories-with-object.md +++ b/docs/_snippets/main-config-stories-with-object.md @@ -35,4 +35,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-stories.md b/docs/_snippets/main-config-stories.md index 5335c946d8aa..2d04f3a74d6f 100644 --- a/docs/_snippets/main-config-stories.md +++ b/docs/_snippets/main-config-stories.md @@ -17,4 +17,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-svelte-csf-register.md b/docs/_snippets/main-config-svelte-csf-register.md new file mode 100644 index 000000000000..7676d4f05ec2 --- /dev/null +++ b/docs/_snippets/main-config-svelte-csf-register.md @@ -0,0 +1,24 @@ +```js filename=".storybook/main.js" renderer="svelte" language="js" +export default { + stories: ['../src/**/*.stories.@(js|jsx|ts|tsx|svelte)'], + addons: [ + // Other Storybook addons + '@storybook/addon-svelte-csf', + ], +}; +``` + +```ts filename=".storybook/main.ts" renderer="svelte" language="ts" +// Replace your-framework with the name of your Svelte framework +import type { StorybookConfig } from '@storybook/your-framework'; + +const config: StorybookConfig = { + stories: ['../src/**/*.stories.@(js|jsx|ts|tsx|svelte)'], + addons: [ + // Other Storybook addons + '@storybook/addon-svelte-csf', + ], +}; + +export default config; +``` diff --git a/docs/_snippets/main-config-swc-jsx-transform.md b/docs/_snippets/main-config-swc-jsx-transform.md index b85848dcafd9..f942eee4e7fc 100644 --- a/docs/_snippets/main-config-swc-jsx-transform.md +++ b/docs/_snippets/main-config-swc-jsx-transform.md @@ -38,4 +38,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-swc.md b/docs/_snippets/main-config-swc.md index 6690e30ce924..670bdb51b922 100644 --- a/docs/_snippets/main-config-swc.md +++ b/docs/_snippets/main-config-swc.md @@ -33,4 +33,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-test-disable-autodocs.md b/docs/_snippets/main-config-test-disable-autodocs.md index 16df9af2dcfd..dab7b1ffb3cf 100644 --- a/docs/_snippets/main-config-test-disable-autodocs.md +++ b/docs/_snippets/main-config-test-disable-autodocs.md @@ -27,4 +27,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-test-disable-blocks.md b/docs/_snippets/main-config-test-disable-blocks.md index bcc85cfbaafa..d48c5e54c19a 100644 --- a/docs/_snippets/main-config-test-disable-blocks.md +++ b/docs/_snippets/main-config-test-disable-blocks.md @@ -27,4 +27,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-test-disable-docgen.md b/docs/_snippets/main-config-test-disable-docgen.md index c45c607fed59..029bece1e6fd 100644 --- a/docs/_snippets/main-config-test-disable-docgen.md +++ b/docs/_snippets/main-config-test-disable-docgen.md @@ -27,4 +27,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-test-disable-mdx.md b/docs/_snippets/main-config-test-disable-mdx.md index ee708b0b2a7a..013a85ee6af3 100644 --- a/docs/_snippets/main-config-test-disable-mdx.md +++ b/docs/_snippets/main-config-test-disable-mdx.md @@ -27,4 +27,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-test-disable-sourcemaps.md b/docs/_snippets/main-config-test-disable-sourcemaps.md index 8f581273dfbd..42da44e8fce8 100644 --- a/docs/_snippets/main-config-test-disable-sourcemaps.md +++ b/docs/_snippets/main-config-test-disable-sourcemaps.md @@ -27,4 +27,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-test-disable-treeshaking.md b/docs/_snippets/main-config-test-disable-treeshaking.md index e5f65383fbd4..a328ce28de7c 100644 --- a/docs/_snippets/main-config-test-disable-treeshaking.md +++ b/docs/_snippets/main-config-test-disable-treeshaking.md @@ -27,4 +27,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-typescript-check-options.md b/docs/_snippets/main-config-typescript-check-options.md index 2c41b5f53ad8..2850a3fb2f40 100644 --- a/docs/_snippets/main-config-typescript-check-options.md +++ b/docs/_snippets/main-config-typescript-check-options.md @@ -15,4 +15,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-typescript-check.md b/docs/_snippets/main-config-typescript-check.md index 043e01e26bde..a1ef1bcec0af 100644 --- a/docs/_snippets/main-config-typescript-check.md +++ b/docs/_snippets/main-config-typescript-check.md @@ -12,4 +12,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-typescript-react-docgen-typescript-options.md b/docs/_snippets/main-config-typescript-react-docgen-typescript-options.md index 47c800598e2e..57310d35a370 100644 --- a/docs/_snippets/main-config-typescript-react-docgen-typescript-options.md +++ b/docs/_snippets/main-config-typescript-react-docgen-typescript-options.md @@ -17,4 +17,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-typescript-react-docgen.md b/docs/_snippets/main-config-typescript-react-docgen.md index a49ccfeda3a9..94a73916a1ff 100644 --- a/docs/_snippets/main-config-typescript-react-docgen.md +++ b/docs/_snippets/main-config-typescript-react-docgen.md @@ -12,4 +12,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-typescript-skip-compiler.md b/docs/_snippets/main-config-typescript-skip-compiler.md index 3f338a05c724..57a0f21c359c 100644 --- a/docs/_snippets/main-config-typescript-skip-compiler.md +++ b/docs/_snippets/main-config-typescript-skip-compiler.md @@ -12,4 +12,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-typical.md b/docs/_snippets/main-config-typical.md index 342de3698437..eb2230a71ba7 100644 --- a/docs/_snippets/main-config-typical.md +++ b/docs/_snippets/main-config-typical.md @@ -32,4 +32,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/main-config-vite-final-env.md b/docs/_snippets/main-config-vite-final-env.md index b785329d0dbc..eaaed64eeef2 100644 --- a/docs/_snippets/main-config-vite-final-env.md +++ b/docs/_snippets/main-config-vite-final-env.md @@ -19,4 +19,3 @@ export default { }, }; ``` - diff --git a/docs/_snippets/main-config-vite-final.md b/docs/_snippets/main-config-vite-final.md index ca3566e5a91f..a6a1d2fd79f1 100644 --- a/docs/_snippets/main-config-vite-final.md +++ b/docs/_snippets/main-config-vite-final.md @@ -69,4 +69,3 @@ const config = { export default config; ``` - diff --git a/docs/_snippets/main-config-webpack-final.md b/docs/_snippets/main-config-webpack-final.md index 8ee96518d565..0d0c8b5e463c 100644 --- a/docs/_snippets/main-config-webpack-final.md +++ b/docs/_snippets/main-config-webpack-final.md @@ -35,4 +35,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/margindecorator.md b/docs/_snippets/margindecorator.md index 4cf91687525f..82545e73b08b 100644 --- a/docs/_snippets/margindecorator.md +++ b/docs/_snippets/margindecorator.md @@ -1,6 +1,4 @@ -```html renderer="svelte" language="js" tabTitle="with-margin-component" -{/* MarginDecorator.svelte */} - +```svelte filename="MarginDecorator.svelte" renderer="svelte" language="js" tabTitle="Svelte 4" <div> <slot /> </div> @@ -12,9 +10,23 @@ </style> ``` -```html renderer="svelte" language="ts" tabTitle="with-margin-component" -{/* MarginDecorator.svelte */} +```svelte filename="MarginDecorator.svelte" renderer="svelte" language="js" tabTitle="Svelte 5" +<script> + let { children } = $props(); +</script> + +<div> + {@render children()} +</div> + +<style> + div { + margin: 3em; + } +</style> +``` +```svelte filename="MarginDecorator.svelte" renderer="svelte" language="ts" tabTitle="Svelte 4" <div> <slot /> </div> @@ -26,3 +38,20 @@ </style> ``` +```svelte filename="MarginDecorator.svelte" renderer="svelte" language="ts" tabTitle="Svelte 5" +<script> + import type { Snippet } from 'svelte'; + + let { children }: { children: Snippet } = $props(); +</script> + +<div> + {@render children()} +</div> + +<style> + div { + margin: 3em; + } +</style> +``` diff --git a/docs/_snippets/mock-context-container-global.md b/docs/_snippets/mock-context-container-global.md index ada262d52e1c..447d1cd44b84 100644 --- a/docs/_snippets/mock-context-container-global.md +++ b/docs/_snippets/mock-context-container-global.md @@ -62,9 +62,7 @@ const AppDecorator = (storyFn) => { export const decorators = [AppDecorator]; ``` -```ts filename="Replace your-framework with the framework you are using (e.g., react, vue3)" renderer="solid" language="ts" -import { Preview } from '@storybook/your-framework'; - +```ts filename=".storybook/preview.ts" renderer="solid" language="ts" import { normal as NavigationNormal } from '../components/Navigation.stories'; import GlobalContainerContext from '../components/lib/GlobalContainerContext'; @@ -85,4 +83,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/mock-context-container-provider.md b/docs/_snippets/mock-context-container-provider.md index 81a3ce811fc1..533765ee4736 100644 --- a/docs/_snippets/mock-context-container-provider.md +++ b/docs/_snippets/mock-context-container-provider.md @@ -41,4 +41,3 @@ export const AppProfilePage = () => { ); }; ``` - diff --git a/docs/_snippets/mock-context-container.md b/docs/_snippets/mock-context-container.md index 2b3f1e92278b..716c68d31f26 100644 --- a/docs/_snippets/mock-context-container.md +++ b/docs/_snippets/mock-context-container.md @@ -71,4 +71,3 @@ export const Normal = { ), }; ``` - diff --git a/docs/_snippets/mock-context-create.md b/docs/_snippets/mock-context-create.md index 7954b4f8d71a..7d4b419079db 100644 --- a/docs/_snippets/mock-context-create.md +++ b/docs/_snippets/mock-context-create.md @@ -13,4 +13,3 @@ const ProfilePageContext = createContext(); export default ProfilePageContext; ``` - diff --git a/docs/_snippets/mock-context-in-use.md b/docs/_snippets/mock-context-in-use.md index 9176799db702..39fec5ba4a8c 100644 --- a/docs/_snippets/mock-context-in-use.md +++ b/docs/_snippets/mock-context-in-use.md @@ -33,4 +33,3 @@ export const ProfilePage = (props) => { ); }; ``` - diff --git a/docs/_snippets/mock-provider-in-preview.md b/docs/_snippets/mock-provider-in-preview.md index 2b13aa680e6d..31c0a23c9b91 100644 --- a/docs/_snippets/mock-provider-in-preview.md +++ b/docs/_snippets/mock-provider-in-preview.md @@ -48,4 +48,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/module-aliases-config.md b/docs/_snippets/module-aliases-config.md index 354538305779..097285e63efd 100644 --- a/docs/_snippets/module-aliases-config.md +++ b/docs/_snippets/module-aliases-config.md @@ -101,4 +101,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/msw-addon-configure-handlers-graphql.md b/docs/_snippets/msw-addon-configure-handlers-graphql.md index e3a0b167f1fd..8d41807db3f2 100644 --- a/docs/_snippets/msw-addon-configure-handlers-graphql.md +++ b/docs/_snippets/msw-addon-configure-handlers-graphql.md @@ -1,4 +1,4 @@ -```ts filename="YourPage.stories.ts" renderer="angular" language="ts" +```ts filename="YourPage.stories.ts" renderer="angular" language="ts" tabTitle="story" import type { Meta, StoryObj } from '@storybook/angular'; import { moduleMetadata } from '@storybook/angular'; @@ -89,6 +89,45 @@ export const MockedError: Story = { }; ``` +```ts filename="mock-graphql.module.ts" renderer="angular" language="ts" tabTitle="mock-apollo-module" +import { NgModule } from '@angular/core'; +import { APOLLO_OPTIONS } from 'apollo-angular'; + +import { ApolloClientOptions, InMemoryCache } from '@apollo/client/core'; +import { HttpLink } from 'apollo-angular/http'; + +// See here for docs https://apollo-angular.com/docs/get-started + +const uri = 'https://your-graphql-endpoint'; +export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> { + return { + link: httpLink.create({ uri }), + cache: new InMemoryCache(), + defaultOptions: { + watchQuery: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + query: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + }, + }; +} + +@NgModule({ + providers: [ + { + provide: APOLLO_OPTIONS, + useFactory: createApollo, + deps: [HttpLink], + }, + ], +}) +export class MockGraphQLModule {} +``` + ```js filename="YourPage.stories.js|jsx" renderer="react" language="js" import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client'; import { graphql, HttpResponse, delay } from 'msw'; @@ -255,7 +294,7 @@ export const MockedSuccess: Story = { allInfo: { ...TestData, }, - } + }, }); }), ], @@ -354,7 +393,7 @@ export const MockedSuccess: Story = { allInfo: { ...TestData, }, - } + }, }); }), ], @@ -382,7 +421,7 @@ export const MockedError: Story = { }; ``` -```js filename="YourPage.stories.js" renderer="svelte" language="js" +```js filename="YourPage.stories.js" renderer="svelte" language="js" tabTitle="story" import { graphql, HttpResponse, delay } from 'msw'; import MockApolloWrapperClient from './MockApolloWrapperClient.svelte'; @@ -456,7 +495,33 @@ export const MockedError = { }; ``` -```ts filename="YourPage.stories.ts" renderer="svelte" language="ts-4-9" +```svelte filename="MockApolloWrapperClient.svelte" renderer="svelte" language="js" tabTitle="apollo-wrapper-component" +<script> + import { ApolloClient, InMemoryCache } from '@apollo/client'; + + import { setClient } from 'svelte-apollo'; + + const mockedClient = new ApolloClient({ + uri: 'https://your-graphql-endpoint', + cache: new InMemoryCache(), + defaultOptions: { + watchQuery: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + query: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + }, + }); + setClient(mockedClient); +</script> + +<slot /> +``` + +```ts filename="YourPage.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="story" import type { Meta, StoryObj } from '@storybook/svelte'; import { graphql, HttpResponse, delay } from 'msw'; @@ -535,7 +600,33 @@ export const MockedError: Story = { }; ``` -```ts filename="YourPage.stories.ts" renderer="svelte" language="ts" +```svelte filename="MockApolloWrapperClient.svelte" renderer="svelte" language="ts-4-9" tabTitle="apollo-wrapper-component" +<script lang="ts"> + import { ApolloClient, InMemoryCache } from '@apollo/client'; + + import { setClient } from 'svelte-apollo'; + + const mockedClient = new ApolloClient({ + uri: 'https://your-graphql-endpoint', + cache: new InMemoryCache(), + defaultOptions: { + watchQuery: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + query: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + }, + }); + setClient(mockedClient); +</script> + +<slot /> +``` + +```ts filename="YourPage.stories.ts" renderer="svelte" language="ts" tabTitle="story" import type { Meta, StoryObj } from '@storybook/svelte'; import { graphql, HttpResponse, delay } from 'msw'; @@ -614,7 +705,33 @@ export const MockedError: Story = { }; ``` -```js filename="YourPage.stories.js" renderer="vue" language="js" +```svelte filename="MockApolloWrapperClient.svelte" renderer="svelte" language="ts" tabTitle="apollo-wrapper-component" +<script lang="ts"> + import { ApolloClient, InMemoryCache } from '@apollo/client'; + + import { setClient } from 'svelte-apollo'; + + const mockedClient = new ApolloClient({ + uri: 'https://your-graphql-endpoint', + cache: new InMemoryCache(), + defaultOptions: { + watchQuery: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + query: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + }, + }); + setClient(mockedClient); +</script> + +<slot /> +``` + +```js filename="YourPage.stories.js" renderer="vue" language="js" tabTitle="story" import { graphql, HttpResponse, delay } from 'msw'; import WrapperComponent from './ApolloWrapperClient.vue'; @@ -691,7 +808,47 @@ export const MockedError = { }; ``` -```ts filename="YourPage.stories.ts" renderer="vue" language="ts-4-9" +```html filename="ApolloWrapperClient.vue" renderer="vue" language="js" tabTitle="apollo-wrapper-component" +<template> + <div><slot /></div> +</template> + +<script> + import { defineComponent, provide } from 'vue'; + import { DefaultApolloClient } from '@vue/apollo-composable'; + import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core'; + + // Apollo client wrapper component that can be used within your app and Storybook + export default defineComponent({ + name: 'WrapperComponent', + setup() { + const httpLink = createHttpLink({ + // You should use an absolute URL here + uri: 'https://your-graphql-endpoint', + }); + const cache = new InMemoryCache(); + + const mockedClient = new ApolloClient({ + link: httpLink, + cache, + defaultOptions: { + watchQuery: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + query: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + }, + }); + provide(DefaultApolloClient, mockedClient); + }, + }); +</script> +``` + +```ts filename="YourPage.stories.ts" renderer="vue" language="ts-4-9" tabTitle="story" import type { Meta, StoryObj } from '@storybook/vue3'; import { graphql, HttpResponse, delay } from 'msw'; @@ -773,7 +930,47 @@ export const MockedError: Story = { }; ``` -```ts filename="YourPage.stories.ts" renderer="vue" language="ts" +```html filename="ApolloWrapperClient.vue" renderer="vue" language="ts-4-9" tabTitle="apollo-wrapper-component" +<template> + <div><slot /></div> +</template> + +<script> + import { defineComponent, provide } from 'vue'; + import { DefaultApolloClient } from '@vue/apollo-composable'; + import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core'; + + // Apollo client wrapper component that can be used within your app and Storybook + export default defineComponent({ + name: 'WrapperComponent', + setup() { + const httpLink = createHttpLink({ + // You should use an absolute URL here + uri: 'https://your-graphql-endpoint', + }); + const cache = new InMemoryCache(); + + const mockedClient = new ApolloClient({ + link: httpLink, + cache, + defaultOptions: { + watchQuery: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + query: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + }, + }); + provide(DefaultApolloClient, mockedClient); + }, + }); +</script> +``` + +```ts filename="YourPage.stories.ts" renderer="vue" language="ts" tabTitle="story" import type { Meta, StoryObj } from '@storybook/vue3'; import { graphql, HttpResponse, delay } from 'msw'; @@ -855,3 +1052,42 @@ export const MockedError: Story = { }; ``` +```html filename="ApolloWrapperClient.vue" renderer="vue" language="ts" tabTitle="apollo-wrapper-component" +<template> + <div><slot /></div> +</template> + +<script> + import { defineComponent, provide } from 'vue'; + import { DefaultApolloClient } from '@vue/apollo-composable'; + import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core'; + + // Apollo client wrapper component that can be used within your app and Storybook + export default defineComponent({ + name: 'WrapperComponent', + setup() { + const httpLink = createHttpLink({ + // You should use an absolute URL here + uri: 'https://your-graphql-endpoint', + }); + const cache = new InMemoryCache(); + + const mockedClient = new ApolloClient({ + link: httpLink, + cache, + defaultOptions: { + watchQuery: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + query: { + fetchPolicy: 'no-cache', + errorPolicy: 'all', + }, + }, + }); + provide(DefaultApolloClient, mockedClient); + }, + }); +</script> +``` diff --git a/docs/_snippets/msw-addon-initialize.md b/docs/_snippets/msw-addon-initialize.md index 71889c968f8e..af8abd264fd0 100644 --- a/docs/_snippets/msw-addon-initialize.md +++ b/docs/_snippets/msw-addon-initialize.md @@ -34,4 +34,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/msw-addon-install.md b/docs/_snippets/msw-addon-install.md index 72ee2a6fc2b0..2f9ce9a5f725 100644 --- a/docs/_snippets/msw-addon-install.md +++ b/docs/_snippets/msw-addon-install.md @@ -9,4 +9,3 @@ pnpm add msw msw-storybook-addon --save-dev ```sh renderer="common" language="js" packageManager="yarn" yarn add msw msw-storybook-addon --save-dev ``` - diff --git a/docs/_snippets/msw-generate-service-worker.md b/docs/_snippets/msw-generate-service-worker.md index 805ac7374b54..d8fdbeb6914d 100644 --- a/docs/_snippets/msw-generate-service-worker.md +++ b/docs/_snippets/msw-generate-service-worker.md @@ -1,8 +1,11 @@ -```shell renderer="common" language="js" packageManager="npx" +```shell renderer="common" language="js" packageManager="npm" npx msw init public/ ``` +```shell renderer="common" language="js" packageManager="yarn" +yarn dlx msw init public/ +``` + ```shell renderer="common" language="js" packageManager="pnpm" pnpm dlx msw init public/ ``` - diff --git a/docs/_snippets/multiple-stories-test.md b/docs/_snippets/multiple-stories-test.md index 5610d4c144cd..583b315863ef 100644 --- a/docs/_snippets/multiple-stories-test.md +++ b/docs/_snippets/multiple-stories-test.md @@ -70,7 +70,7 @@ test('Tests filled form', async () => { }); ``` -```js filename="tests/Form.test.js" renderer="vue" language="js" tabTitle="3" +```js filename="tests/Form.test.js" renderer="vue" language="js" import { fireEvent, screen } from '@testing-library/vue'; import { composeStories } from '@storybook/vue3'; @@ -106,7 +106,7 @@ test('Tests filled form', async () => { }); ``` -```ts filename="tests/Form.test.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="tests/Form.test.ts" renderer="vue" language="ts" import { fireEvent, screen } from '@testing-library/vue'; import { composeStories } from '@storybook/vue3'; diff --git a/docs/_snippets/my-component-disable-toc.md b/docs/_snippets/my-component-disable-toc.md index 57ce09e8074c..a9f684807f7c 100644 --- a/docs/_snippets/my-component-disable-toc.md +++ b/docs/_snippets/my-component-disable-toc.md @@ -18,7 +18,43 @@ const meta: Meta<MyComponent> = { export default meta; ``` -```js filename="MyComponent.stories.js|jsx" renderer="common" language="js" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + tags: ['autodocs'], + parameters: { + docs: { + toc: { + disable: true, // 👈 Disables the table of contents + }, + }, + }, + }); +</script> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, + tags: ['autodocs'], + parameters: { + docs: { + toc: { + disable: true, // 👈 Disables the table of contents + }, + }, + }, +}; +``` + +```js filename="MyComponent.stories.js" renderer="common" language="js" import { MyComponent } from './MyComponent'; export default { @@ -34,6 +70,46 @@ export default { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + tags: ['autodocs'], + parameters: { + docs: { + toc: { + disable: true, // 👈 Disables the table of contents + }, + }, + }, + }); +</script> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, + tags: ['autodocs'], + parameters: { + docs: { + toc: { + disable: true, // 👈 Disables the table of contents + }, + }, + }, +} satisfies Meta<typeof MyComponent>; + +export default meta; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -55,6 +131,46 @@ const meta = { export default meta; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + tags: ['autodocs'], + parameters: { + docs: { + toc: { + disable: true, // 👈 Disables the table of contents + }, + }, + }, + }); +</script> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import MyComponent from './MyComponent.svelte'; + +const meta: Meta<typeof MyComponent> = { + component: MyComponent, + tags: ['autodocs'], + parameters: { + docs: { + toc: { + disable: true, // 👈 Disables the table of contents + }, + }, + }, +}; + +export default meta; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -107,4 +223,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/my-component-env-var-config.md b/docs/_snippets/my-component-env-var-config.md index 538423a21e2b..d5e9bcb77e11 100644 --- a/docs/_snippets/my-component-env-var-config.md +++ b/docs/_snippets/my-component-env-var-config.md @@ -100,4 +100,3 @@ export const Default: Story = { }, }; ``` - diff --git a/docs/_snippets/my-component-exclude-tags.md b/docs/_snippets/my-component-exclude-tags.md index 3b0c9f6a007d..58768d7023bd 100644 --- a/docs/_snippets/my-component-exclude-tags.md +++ b/docs/_snippets/my-component-exclude-tags.md @@ -31,4 +31,3 @@ export const ExcludeStory: Story = { tags: ['no-tests'], }; ``` - diff --git a/docs/_snippets/my-component-include-tags.md b/docs/_snippets/my-component-include-tags.md index c77da4a37f0c..29a3b0b1bf83 100644 --- a/docs/_snippets/my-component-include-tags.md +++ b/docs/_snippets/my-component-include-tags.md @@ -31,4 +31,3 @@ export const IncludeStory: Story = { tags: ['test-only'], }; ``` - diff --git a/docs/_snippets/my-component-play-function-alt-queries.md b/docs/_snippets/my-component-play-function-alt-queries.md index 6a729e8f8d5e..4145c3cd2acc 100644 --- a/docs/_snippets/my-component-play-function-alt-queries.md +++ b/docs/_snippets/my-component-play-function-alt-queries.md @@ -26,6 +26,55 @@ export const ExampleWithRole: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ExampleWithRole" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); + }} /> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, +}; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ExampleWithRole = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); + }, +}; +``` + ```js filename="MyComponent.stories.js|jsx" renderer="common" language="js" import { userEvent, within } from '@storybook/test'; @@ -48,6 +97,60 @@ export const ExampleWithRole = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ExampleWithRole" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); + }} /> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, +} satisfies Meta<typeof MyComponent>; + +export default meta; +type Story = StoryObj<typeof meta>; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ExampleWithRole: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -76,6 +179,60 @@ export const ExampleWithRole: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ExampleWithRole" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); + }} /> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta: Meta<typeof MyComponent> = { + component: MyComponent, +}; + +export default meta; +type Story = StoryObj<typeof MyComponent>; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ExampleWithRole: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -147,4 +304,3 @@ export const ExampleWithRole: Story = { }, }; ``` - diff --git a/docs/_snippets/my-component-play-function-query-findby.md b/docs/_snippets/my-component-play-function-query-findby.md index 8ea6145a24ea..b3835f17926e 100644 --- a/docs/_snippets/my-component-play-function-query-findby.md +++ b/docs/_snippets/my-component-play-function-query-findby.md @@ -28,6 +28,59 @@ export const AsyncExample: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="AsyncExample" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Other steps + + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i }); + }} /> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, +}; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const AsyncExample = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Other steps + + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i }); + }, +}; +``` + ```js filename="MyComponent.stories.js|jsx" renderer="common" language="js" import { userEvent, within } from '@storybook/test'; @@ -47,7 +100,65 @@ export const AsyncExample = { // Other steps // Waits for the component to be rendered before querying the element - await canvas.findByRole('button', { name: / button label/i })); + await canvas.findByRole('button', { name: / button label/i }); + }, +}; +``` + +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="AsyncExample" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Other steps + + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i }); + }} /> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, +} satisfies Meta<typeof MyComponent>; + +export default meta; +type Story = StoryObj<typeof meta>; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const AsyncExample: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Other steps + + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i }); }, }; ``` @@ -82,6 +193,64 @@ export const AsyncExample: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="AsyncExample" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Other steps + + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i }); + }} /> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta: Meta<typeof MyComponent> = { + component: MyComponent, +}; + +export default meta; +type Story = StoryObj<typeof MyComponent>; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const AsyncExample: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Other steps + + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i }); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -129,7 +298,7 @@ export const AsyncExample = { // Other steps // Waits for the component to be rendered before querying the element - await canvas.findByRole('button', { name: / button label/i })); + await canvas.findByRole('button', { name: / button label/i }); }, }; ``` @@ -159,4 +328,3 @@ export const AsyncExample: Story = { }, }; ``` - diff --git a/docs/_snippets/my-component-play-function-waitfor.md b/docs/_snippets/my-component-play-function-waitfor.md index df40859aed4f..195096524fba 100644 --- a/docs/_snippets/my-component-play-function-waitfor.md +++ b/docs/_snippets/my-component-play-function-waitfor.md @@ -39,6 +39,81 @@ export const ExampleAsyncStory: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, waitFor, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ExampleAsyncStory" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); + + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); + }} /> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import { userEvent, waitFor, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, +}; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ExampleAsyncStory = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); + + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); + }, +}; +``` + ```js filename="MyComponent.stories.js|jsx" renderer="common" language="js" import { userEvent, waitFor, within } from '@storybook/test'; @@ -74,6 +149,86 @@ export const ExampleAsyncStory = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, waitFor, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ExampleAsyncStory" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); + + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); + }} /> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, waitFor, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, +} satisfies Meta<typeof MyComponent>; + +export default meta; +type Story = StoryObj<typeof meta>; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ExampleAsyncStory: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); + + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -115,6 +270,86 @@ export const ExampleAsyncStory: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, waitFor, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ExampleAsyncStory" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); + + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); + }} /> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, waitFor, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta: Meta<typeof MyComponent> = { + component: MyComponent, +}; + +export default meta; +type Story = StoryObj<typeof MyComponent>; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ExampleAsyncStory: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); + + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -225,4 +460,3 @@ export const ExampleAsyncStory: Story = { }, }; ``` - diff --git a/docs/_snippets/my-component-play-function-with-canvas.md b/docs/_snippets/my-component-play-function-with-canvas.md index d37ff14e0301..7d44ad477a74 100644 --- a/docs/_snippets/my-component-play-function-with-canvas.md +++ b/docs/_snippets/my-component-play-function-with-canvas.md @@ -24,6 +24,56 @@ export const ExampleStory: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ExampleStory" + play={async ({ canvasElement }) => { + // Assigns canvas to the component root element + const canvas = within(canvasElement); + + // Starts querying from the component's root element + await userEvent.type(canvas.getByTestId('example-element'), 'something'); + await userEvent.click(canvas.getByRole('another-element')); + }} /> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, +}; + +export const ExampleStory = { + play: async ({ canvasElement }) => { + // Assigns canvas to the component root element + const canvas = within(canvasElement); + + // Starts querying from the component's root element + await userEvent.type(canvas.getByTestId('example-element'), 'something'); + await userEvent.click(canvas.getByRole('another-element')); + }, +}; +``` + ```js filename="MyComponent.stories.js|jsx" renderer="common" language="js" import { userEvent, within } from '@storybook/test'; @@ -45,6 +95,57 @@ export const ExampleStory = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="ExampleStory" + play={async ({ canvasElement }) => { + // Assigns canvas to the component root element + const canvas = within(canvasElement); + + // Starts querying from the component's root element + await userEvent.type(canvas.getByTestId('example-element'), 'something'); + await userEvent.click(canvas.getByRole('another-element')); + }} /> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, +} satisfies Meta<typeof MyComponent>; + +export default meta; +type Story = StoryObj<typeof meta>; + +export const ExampleStory: Story = { + play: async ({ canvasElement }) => { + // Assigns canvas to the component root element + const canvas = within(canvasElement); + + // Starts querying from the component's root element + await userEvent.type(canvas.getByTestId('example-element'), 'something'); + await userEvent.click(canvas.getByRole('another-element')); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -72,6 +173,56 @@ export const ExampleStory: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="ExampleStory" + play={async ({ canvasElement }) => { + // Assigns canvas to the component root element + const canvas = within(canvasElement); + + // Starts querying from the component's root element + await userEvent.type(canvas.getByTestId('example-element'), 'something'); + await userEvent.click(canvas.getByRole('another-element')); + }} /> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta: Meta<typeof MyComponent> = { + component: MyComponent, +}; + +export default meta; +type Story = StoryObj<typeof MyComponent>; + +export const ExampleStory: Story = { + play: async ({ canvasElement }) => { + // Assigns canvas to the component root element + const canvas = within(canvasElement); + + // Starts querying from the component's root element + await userEvent.type(canvas.getByTestId('example-element'), 'something'); + await userEvent.click(canvas.getByRole('another-element')); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -140,4 +291,3 @@ export const ExampleStory: Story = { }, }; ``` - diff --git a/docs/_snippets/my-component-play-function-with-clickevent.md b/docs/_snippets/my-component-play-function-with-clickevent.md index af4f3789f540..bf4b5b8c47fa 100644 --- a/docs/_snippets/my-component-play-function-with-clickevent.md +++ b/docs/_snippets/my-component-play-function-with-clickevent.md @@ -35,6 +35,75 @@ export const FireEventExample: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { fireEvent, userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ClickExample" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + }} +/> + +<Story + name="FireEventExample" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); + }} +/> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import { fireEvent, userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, +}; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ClickExample = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + }, +}; + +export const FireEventExample = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); + }, +}; +``` + ```js filename="MyComponent.stories.js|jsx" renderer="common" language="js" import { fireEvent, userEvent, within } from '@storybook/test'; @@ -66,6 +135,80 @@ export const FireEventExample = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { fireEvent, userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ClickExample" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + }} +/> + +<Story + name="FireEventExample" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { fireEvent, userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, +} satisfies Meta<typeof MyComponent>; + +export default meta; +type Story = StoryObj<typeof meta>; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ClickExample: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + }, +}; + +export const FireEventExample: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -103,6 +246,80 @@ export const FireEventExample: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { fireEvent, userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ClickExample" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + }} +/> + +<Story + name="FireEventExample" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { fireEvent, userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta: Meta<typeof MyComponent> = { + component: MyComponent, +}; + +export default meta; +type Story = StoryObj<typeof MyComponent>; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ClickExample: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + }, +}; + +export const FireEventExample: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -201,4 +418,3 @@ export const FireEventExample: Story = { }, }; ``` - diff --git a/docs/_snippets/my-component-play-function-with-delay.md b/docs/_snippets/my-component-play-function-with-delay.md index 84b02a17e028..e4fd3ac06338 100644 --- a/docs/_snippets/my-component-play-function-with-delay.md +++ b/docs/_snippets/my-component-play-function-with-delay.md @@ -35,6 +35,74 @@ export const DelayedStory: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="DelayedStory" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement = canvas.getByLabelText('example-element'); + + // The delay option sets the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement = canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); + }} +/> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, +}; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const DelayedStory = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement = canvas.getByLabelText('example-element'); + + // The delay option sets the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement = canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); + }, +}; +``` + ```js filename="MyComponent.stories.js|jsx" renderer="common" language="js" import { userEvent, within } from '@storybook/test'; @@ -66,6 +134,79 @@ export const DelayedStory = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="DelayedStory" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement = canvas.getByLabelText('example-element'); + + // The delay option sets the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement = canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, +} satisfies Meta<typeof MyComponent>; + +export default meta; +type Story = StoryObj<typeof meta>; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const DelayedStory: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement = canvas.getByLabelText('example-element'); + + // The delay option sets the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement = canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -103,6 +244,79 @@ export const DelayedStory: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="DelayedStory" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement = canvas.getByLabelText('example-element'); + + // The delay option sets the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement = canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta: Meta<typeof MyComponent> = { + component: MyComponent, +}; + +export default meta; +type Story = StoryObj<typeof MyComponent>; + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const DelayedStory: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement = canvas.getByLabelText('example-element'); + + // The delay option sets the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement = canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -201,4 +415,3 @@ export const DelayedStory: Story = { }, }; ``` - diff --git a/docs/_snippets/my-component-play-function-with-selectevent.md b/docs/_snippets/my-component-play-function-with-selectevent.md index b8269e99687c..1892f1790d47 100644 --- a/docs/_snippets/my-component-play-function-with-selectevent.md +++ b/docs/_snippets/my-component-play-function-with-selectevent.md @@ -38,6 +38,79 @@ export const ExampleChangeEvent: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); + + function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ExampleChangeEvent" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); + + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); + }} +/> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, +}; + +// Function to emulate pausing between interactions +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ExampleChangeEvent = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); + + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); + }, +}; +``` + ```js filename="MyComponent.stories.js|jsx" renderer="common" language="js" import { userEvent, within } from '@storybook/test'; @@ -72,6 +145,84 @@ export const ExampleChangeEvent = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); + + function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ExampleChangeEvent" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); + + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, +} satisfies Meta<typeof MyComponent>; + +export default meta; +type Story = StoryObj<typeof meta>; + +// Function to emulate pausing between interactions +function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ExampleChangeEvent: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); + + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -112,6 +263,85 @@ export const ExampleChangeEvent: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); + + function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } +</script> + + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="ExampleChangeEvent" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); + + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import MyComponent from './MyComponent.svelte'; + +const meta: Meta<typeof MyComponent> = { + component: MyComponent, +}; + +export default meta; +type Story = StoryObj<typeof MyComponent>; + +// Function to emulate pausing between interactions +function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +/* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const ExampleChangeEvent: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); + + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -219,4 +449,3 @@ export const ExampleChangeEvent: Story = { }, }; ``` - diff --git a/docs/_snippets/my-component-skip-tags.md b/docs/_snippets/my-component-skip-tags.md index 507cd09a91b4..5134cf9e0422 100644 --- a/docs/_snippets/my-component-skip-tags.md +++ b/docs/_snippets/my-component-skip-tags.md @@ -31,4 +31,3 @@ export const SkipStory: Story = { tags: ['skip-test'], }; ``` - diff --git a/docs/_snippets/my-component-story-basic-and-props.md b/docs/_snippets/my-component-story-basic-and-props.md index 42ac3f0c5f1d..c4ad00503ea3 100644 --- a/docs/_snippets/my-component-story-basic-and-props.md +++ b/docs/_snippets/my-component-story-basic-and-props.md @@ -125,7 +125,27 @@ export const WithProp: Story = { }; ``` -```js filename="MyComponent.stories.js" renderer="svelte" language="js" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story name="Basic"> + <MyComponent /> +</Story> + +<Story name="WithProp"> + <MyComponent prop="value" /> +</Story> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" import MyComponent from './MyComponent.svelte'; export default { @@ -149,12 +169,15 @@ export const WithProp = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* MyComponent.stories.svelte */} +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; -<script> - import { Meta, Story } from '@storybook/addon-svelte-csf'; import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); </script> <Story name="Basic"> @@ -166,7 +189,7 @@ export const WithProp = { </Story> ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -195,7 +218,27 @@ export const WithProp: Story = { }; ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story name="Basic"> + <MyComponent /> +</Story> + +<Story name="WithProp"> + <MyComponent prop="value" /> +</Story> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -333,4 +376,3 @@ export const WithProp: Story = { render: () => html`<my-component prop="value" />`, }; ``` - diff --git a/docs/_snippets/my-component-story-import-json.md b/docs/_snippets/my-component-story-import-json.md index c4efc85f6930..d2fa224234f3 100644 --- a/docs/_snippets/my-component-story-import-json.md +++ b/docs/_snippets/my-component-story-import-json.md @@ -2,4 +2,3 @@ // This will automatically be parsed to the contents of `data.json` import data from './data.json'; ``` - diff --git a/docs/_snippets/my-component-story-mandatory-export.md b/docs/_snippets/my-component-story-mandatory-export.md index 0bc760cbec91..2e49f0c50359 100644 --- a/docs/_snippets/my-component-story-mandatory-export.md +++ b/docs/_snippets/my-component-story-mandatory-export.md @@ -93,4 +93,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/my-component-story-use-globaltype.md b/docs/_snippets/my-component-story-use-globaltype.md index 91aeace22707..d1904249e559 100644 --- a/docs/_snippets/my-component-story-use-globaltype.md +++ b/docs/_snippets/my-component-story-use-globaltype.md @@ -523,4 +523,3 @@ export const StoryWithLocale: Story = { }, }; ``` - diff --git a/docs/_snippets/my-component-story-with-nonstory.md b/docs/_snippets/my-component-story-with-nonstory.md index 0751ca526403..f581820552e4 100644 --- a/docs/_snippets/my-component-story-with-nonstory.md +++ b/docs/_snippets/my-component-story-with-nonstory.md @@ -445,4 +445,3 @@ export const ComplexStory: Story = { }, }; ``` - diff --git a/docs/_snippets/my-component-story-with-storyname.md b/docs/_snippets/my-component-story-with-storyname.md index 8f14f67391bc..8a37ebaa137f 100644 --- a/docs/_snippets/my-component-story-with-storyname.md +++ b/docs/_snippets/my-component-story-with-storyname.md @@ -99,4 +99,3 @@ export const Simple: Story = { parameters: {}, }; ``` - diff --git a/docs/_snippets/my-component-vite-env-variables.md b/docs/_snippets/my-component-vite-env-variables.md index 8b72972f0f83..d3b873cdac1d 100644 --- a/docs/_snippets/my-component-vite-env-variables.md +++ b/docs/_snippets/my-component-vite-env-variables.md @@ -1,3 +1,38 @@ +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="ExampleStory" + args={{ + propertyA: import.meta.env.STORYBOOK_DATA_KEY, + propertyB: import.meta.env.VITE_CUSTOM_VAR, + }} +/> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, +}; + +export const ExampleStory = { + args: { + propertyA: import.meta.env.STORYBOOK_DATA_KEY, + propertyB: import.meta.env.VITE_CUSTOM_VAR, + }, +}; +``` + ```js filename="MyComponent.stories.js|jsx" renderer="common" language="js" import { MyComponent } from './MyComponent'; @@ -13,6 +48,46 @@ export const ExampleStory = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="ExampleStory" + args={{ + propertyA: import.meta.env.STORYBOOK_DATA_KEY, + propertyB: import.meta.env.VITE_CUSTOM_VAR, + }} +/> +``` + +```tsx filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, +} satisfies Meta<typeof MyComponent>; + +export default meta; +type Story = StoryObj<typeof meta>; + +export const ExampleStory: Story = { + args: { + propertyA: import.meta.env.STORYBOOK_DATA_KEY, + propertyB: import.meta.env.VITE_CUSTOM_VAR, + }, +}; +``` + ```tsx filename="MyComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -34,6 +109,46 @@ export const ExampleStory: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="ExampleStory" + args={{ + propertyA: import.meta.env.STORYBOOK_DATA_KEY, + propertyB: import.meta.env.VITE_CUSTOM_VAR, + }} +/> +``` + +```tsx filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import MyComponent from './MyComponent.svelte'; + +const meta: Meta<typeof MyComponent> = { + component: MyComponent, +}; + +export default meta; +type Story = StoryObj<typeof MyComponent>; + +export const ExampleStory: Story = { + args: { + propertyA: import.meta.env.STORYBOOK_DATA_KEY, + propertyB: import.meta.env.VITE_CUSTOM_VAR, + }, +}; +``` + ```tsx filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -85,4 +200,3 @@ export const ExampleStory: Story = { }, }; ``` - diff --git a/docs/_snippets/my-component-with-env-variables.md b/docs/_snippets/my-component-with-env-variables.md index 5becbe876f27..81f0ad36f505 100644 --- a/docs/_snippets/my-component-with-env-variables.md +++ b/docs/_snippets/my-component-with-env-variables.md @@ -17,6 +17,39 @@ export const ExampleStory: Story = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="ExampleStory" + args={{ + propertyA: process.env.STORYBOOK_DATA_KEY + }} +/> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, +}; + +export const ExampleStory = { + args: { + propertyA: process.env.STORYBOOK_DATA_KEY, + }, +}; +``` + ```js filename="MyComponent.stories.js|jsx" renderer="common" language="js" import { MyComponent } from './MyComponent'; @@ -31,6 +64,44 @@ export const ExampleStory = { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="ExampleStory" + args={{ + propertyA: process.env.STORYBOOK_DATA_KEY + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, +} satisfies Meta<typeof MyComponent>; + +export default meta; +type Story = StoryObj<typeof meta>; + +export const ExampleStory: Story = { + args: { + propertyA: process.env.STORYBOOK_DATA_KEY, + }, +}; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -51,11 +122,29 @@ export const ExampleStory: Story = { }; ``` -```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" -// Replace your-framework with the name of your framework -import type { Meta, StoryObj } from '@storybook/your-framework'; +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; -import { MyComponent } from './MyComponent'; + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="ExampleStory" + args={{ + propertyA: process.env.STORYBOOK_DATA_KEY + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import MyComponent from './MyComponent.svelte'; const meta: Meta<typeof MyComponent> = { component: MyComponent, @@ -71,22 +160,24 @@ export const ExampleStory: Story = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* MyComponent.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; +```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" +// Replace your-framework with the name of your framework +import type { Meta, StoryObj } from '@storybook/your-framework'; - import MyComponent from './MyComponent.svelte'; -</script> +import { MyComponent } from './MyComponent'; -<meta title="MyComponent" component="{MyComponent}" /> +const meta: Meta<typeof MyComponent> = { + component: MyComponent, +}; -<template let:args> - <MyComponent {...args} /> -</template> +export default meta; +type Story = StoryObj<typeof MyComponent>; -<Story name="ExampleStory" args={{ propertyA: process.env.STORYBOOK_DATA_KEY, }} /> +export const ExampleStory: Story = { + args: { + propertyA: process.env.STORYBOOK_DATA_KEY, + }, +}; ``` ```js filename="MyComponent.stories.js" renderer="web-components" language="js" @@ -117,4 +208,3 @@ export const ExampleStory: Story = { }, }; ``` - diff --git a/docs/_snippets/nextjs-app-directory-in-meta.md b/docs/_snippets/nextjs-app-directory-in-meta.md index 47d283ae59fc..1613ce50d507 100644 --- a/docs/_snippets/nextjs-app-directory-in-meta.md +++ b/docs/_snippets/nextjs-app-directory-in-meta.md @@ -42,4 +42,3 @@ const meta: Meta<typeof NavigationBasedComponent> = { }; export default meta; ``` - diff --git a/docs/_snippets/nextjs-app-directory-in-preview.md b/docs/_snippets/nextjs-app-directory-in-preview.md index 75652a5bcd72..44d0166b296b 100644 --- a/docs/_snippets/nextjs-app-directory-in-preview.md +++ b/docs/_snippets/nextjs-app-directory-in-preview.md @@ -25,4 +25,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/nextjs-cache-mock.md b/docs/_snippets/nextjs-cache-mock.md index b404e1625809..8c310d086aca 100644 --- a/docs/_snippets/nextjs-cache-mock.md +++ b/docs/_snippets/nextjs-cache-mock.md @@ -75,4 +75,3 @@ export const Submitted: Story = { }, }; ``` - diff --git a/docs/_snippets/nextjs-configure-svgr.md b/docs/_snippets/nextjs-configure-svgr.md index dcf45222c54e..18bb44b1b07a 100644 --- a/docs/_snippets/nextjs-configure-svgr.md +++ b/docs/_snippets/nextjs-configure-svgr.md @@ -51,4 +51,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/nextjs-headers-mock.md b/docs/_snippets/nextjs-headers-mock.md index 4e7916f1417a..bbc0e7901d6c 100644 --- a/docs/_snippets/nextjs-headers-mock.md +++ b/docs/_snippets/nextjs-headers-mock.md @@ -87,4 +87,3 @@ export const LoggedInEurope: Story = { }, }; ``` - diff --git a/docs/_snippets/nextjs-image-static-dirs.md b/docs/_snippets/nextjs-image-static-dirs.md index d70202edc512..7485f467397d 100644 --- a/docs/_snippets/nextjs-image-static-dirs.md +++ b/docs/_snippets/nextjs-image-static-dirs.md @@ -25,4 +25,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/nextjs-install.md b/docs/_snippets/nextjs-install.md index 7779659a3e37..0e6cb2d09ecc 100644 --- a/docs/_snippets/nextjs-install.md +++ b/docs/_snippets/nextjs-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/nextjs ```shell renderer="react" language="js" packageManager="yarn" yarn add --dev @storybook/nextjs ``` - diff --git a/docs/_snippets/nextjs-navigation-mock.md b/docs/_snippets/nextjs-navigation-mock.md index 635d822a883d..003fdee91a48 100644 --- a/docs/_snippets/nextjs-navigation-mock.md +++ b/docs/_snippets/nextjs-navigation-mock.md @@ -114,4 +114,3 @@ export const GoBack: Story = { }, }; ``` - diff --git a/docs/_snippets/nextjs-navigation-override-in-story.md b/docs/_snippets/nextjs-navigation-override-in-story.md index 417f5c104c7c..a2afcfbfdd36 100644 --- a/docs/_snippets/nextjs-navigation-override-in-story.md +++ b/docs/_snippets/nextjs-navigation-override-in-story.md @@ -41,7 +41,7 @@ const meta = { } satisfies Meta<typeof NavigationBasedComponent>; export default meta; -type Story = StoryObj<typeof Meta>; +type Story = StoryObj<typeof meta>; // If you have the actions addon, // you can interact with the links and see the route change events there @@ -91,4 +91,3 @@ export const Example: Story = { }, }; ``` - diff --git a/docs/_snippets/nextjs-navigation-segments-for-use-params-override-in-meta.md b/docs/_snippets/nextjs-navigation-segments-for-use-params-override-in-meta.md index abd429265068..194ea482b5a5 100644 --- a/docs/_snippets/nextjs-navigation-segments-for-use-params-override-in-meta.md +++ b/docs/_snippets/nextjs-navigation-segments-for-use-params-override-in-meta.md @@ -60,4 +60,3 @@ const meta: Meta<typeof NavigationBasedComponent> = { }; export default meta; ``` - diff --git a/docs/_snippets/nextjs-navigation-segments-override-in-meta.md b/docs/_snippets/nextjs-navigation-segments-override-in-meta.md index 3e494fb4dcf6..848f9530c164 100644 --- a/docs/_snippets/nextjs-navigation-segments-override-in-meta.md +++ b/docs/_snippets/nextjs-navigation-segments-override-in-meta.md @@ -51,4 +51,3 @@ const meta: Meta<typeof NavigationBasedComponent> = { }; export default meta; ``` - diff --git a/docs/_snippets/nextjs-remove-addons.md b/docs/_snippets/nextjs-remove-addons.md index 8daf79ac7d95..007e6fe14733 100644 --- a/docs/_snippets/nextjs-remove-addons.md +++ b/docs/_snippets/nextjs-remove-addons.md @@ -25,4 +25,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/nextjs-router-mock.md b/docs/_snippets/nextjs-router-mock.md index 4d3c35fba720..83e83aee5e02 100644 --- a/docs/_snippets/nextjs-router-mock.md +++ b/docs/_snippets/nextjs-router-mock.md @@ -76,4 +76,3 @@ export const GoBack: Story = { }, }; ``` - diff --git a/docs/_snippets/nextjs-router-override-in-story.md b/docs/_snippets/nextjs-router-override-in-story.md index bdf1d0718209..cac0babd2688 100644 --- a/docs/_snippets/nextjs-router-override-in-story.md +++ b/docs/_snippets/nextjs-router-override-in-story.md @@ -32,7 +32,7 @@ const meta = { } satisfies Meta<typeof RouterBasedComponent>; export default meta; -type Story = StoryObj<typeof Meta>; +type Story = StoryObj<typeof meta>; // If you have the actions addon, // you can interact with the links and see the route change events there @@ -79,4 +79,3 @@ export const Example: Story = { }, }; ``` - diff --git a/docs/_snippets/other-foo-bar-story.md b/docs/_snippets/other-foo-bar-story.md index c2a5393ef7b7..eab030321c8e 100644 --- a/docs/_snippets/other-foo-bar-story.md +++ b/docs/_snippets/other-foo-bar-story.md @@ -115,4 +115,3 @@ export const Baz: Story = { name: 'Insert name here', }; ``` - diff --git a/docs/_snippets/page-story-args-within-story.md b/docs/_snippets/page-story-args-within-story.md index 9a33cdefb1e2..a890b871ffbc 100644 --- a/docs/_snippets/page-story-args-within-story.md +++ b/docs/_snippets/page-story-args-within-story.md @@ -95,4 +95,3 @@ export const Example: Story = { }, }; ``` - diff --git a/docs/_snippets/page-story-slots.md b/docs/_snippets/page-story-slots.md index bf8f8b3253c7..c32f96c7cd8e 100644 --- a/docs/_snippets/page-story-slots.md +++ b/docs/_snippets/page-story-slots.md @@ -171,27 +171,67 @@ export const CustomFooter: Story = { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* Page.stories.svelte */} +```svelte filename="Page.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; + import Page from './Page.svelte'; + + const { Story } = defineMeta({ + component: Page + }); +</script> + +<Story name="CustomFooter" args={{ footer: 'Built with Storybook' }}> + {#snippet children(args)} + <Page {...args} > + <footer>{args.footer}</footer> + </Page> + {/snippet} +</Story> +``` + +```svelte filename="Page.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import Page from './Page.svelte'; + + const { Story } = defineMeta({ + component: Page + }); </script> -<meta title="Page" component="{Page}" /> +<Story name="CustomFooter" args={{ footer: 'Built with Storybook' }}> + {#snippet children(args)} + <Page {...args} > + <footer>{args.footer}</footer> + </Page> + {/snippet} +</Story> +``` + +```svelte filename="Page.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Page from './Page.svelte'; -<template let:args> - <Page {...args}> - <footer>{args.footer}</footer> - </Page> -</template> + const { Story } = defineMeta({ + component: Page + }); +</script> -<Story name="CustomFooter" args={{ footer: 'Built with Storybook', }} /> +<Story name="CustomFooter" args={{ footer: 'Built with Storybook' }}> + {#snippet children(args)} + <Page {...args} > + <footer>{args.footer}</footer> + </Page> + {/snippet} +</Story> ``` -```js filename="Page.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="Page.stories.js" renderer="vue" language="js" import Page from './Page.vue'; export default { @@ -218,7 +258,7 @@ export const CustomFooter = { }; ``` -```ts filename="Page.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="Page.stories.ts" renderer="vue" language="ts-4-9" // https://www.npmjs.com/package/vue-component-type-helpers import type { ComponentProps } from 'vue-component-type-helpers'; import type { Meta, StoryObj } from '@storybook/vue3'; @@ -254,7 +294,7 @@ export const Primary = { } satisfies Story; ``` -```ts filename="Page.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="Page.stories.ts" renderer="vue" language="ts" // https://www.npmjs.com/package/vue-component-type-helpers import type { ComponentProps } from 'vue-component-type-helpers'; import type { Meta, StoryObj } from '@storybook/vue3'; @@ -336,4 +376,3 @@ export const CustomFooter: Story = { }, }; ``` - diff --git a/docs/_snippets/page-story-with-args-composition.md b/docs/_snippets/page-story-with-args-composition.md index de13cb80a08b..a12fc28740de 100644 --- a/docs/_snippets/page-story-with-args-composition.md +++ b/docs/_snippets/page-story-with-args-composition.md @@ -141,4 +141,3 @@ export const Simple: Story = { }, }; ``` - diff --git a/docs/_snippets/page-story.md b/docs/_snippets/page-story.md index 3d3ff8c6bc92..24868f858f30 100644 --- a/docs/_snippets/page-story.md +++ b/docs/_snippets/page-story.md @@ -154,7 +154,23 @@ export const LoggedIn: Story = { }; ``` -```js filename="Page.stories.js" renderer="svelte" language="js" +```svelte filename="Page.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Page from './Page.svelte'; + //👇 Imports all Header stories + import * as HeaderStories from './Header.stories.svelte'; + + const { Story } = defineMeta({ + component: Page, + }); +</script> + +<Story name="LoggedIn" args={{ ...HeaderStories.LoggedIn.args }} /> +``` + +```js filename="Page.stories.js" renderer="svelte" language="js" tabTitle="CSF" import Page from './Page.svelte'; //👇 Imports all Header stories @@ -171,7 +187,23 @@ export const LoggedIn = { }; ``` -```ts filename="Page.stories.ts" renderer="svelte" language="ts-4-9" +```svelte filename="Page.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Page from './Page.svelte'; + //👇 Imports all Header stories + import * as HeaderStories from './Header.stories.svelte'; + + const { Story } = defineMeta({ + component: Page, + }); +</script> + +<Story name="LoggedIn" args={{ ...HeaderStories.LoggedIn.args }} /> +``` + +```ts filename="Page.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Page from './Page.svelte'; @@ -193,7 +225,23 @@ export const LoggedIn: Story = { }; ``` -```ts filename="Page.stories.ts" renderer="svelte" language="ts" +```svelte filename="Page.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Page from './Page.svelte'; + //👇 Imports all Header stories + import * as HeaderStories from './Header.stories.svelte'; + + const { Story } = defineMeta({ + component: Page, + }); +</script> + +<Story name="LoggedIn" args={{ ...HeaderStories.LoggedIn.args }} /> +``` + +```ts filename="Page.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import Page from './Page.svelte'; @@ -215,7 +263,7 @@ export const LoggedIn: Story = { }; ``` -```js filename="Page.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="Page.stories.js" renderer="vue" language="js" import Page from './Page.vue'; //👇 Imports all Header stories @@ -244,7 +292,7 @@ export const LoggedIn = { }; ``` -```ts filename="Page.stories.ts" renderer="vue" language="ts-4-9" tabTitle="3" +```ts filename="Page.stories.ts" renderer="vue" language="ts-4-9" import type { Meta, StoryObj } from '@storybook/vue3'; import Page from './Page.vue'; @@ -278,7 +326,7 @@ export const Primary: Story = { }; ``` -```ts filename="Page.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="Page.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import Page from './Page.vue'; @@ -346,4 +394,3 @@ export const LoggedIn: Story = { }, }; ``` - diff --git a/docs/_snippets/parameters-in-meta.md b/docs/_snippets/parameters-in-meta.md index 7abf1b58804d..9037dc413549 100644 --- a/docs/_snippets/parameters-in-meta.md +++ b/docs/_snippets/parameters-in-meta.md @@ -5,14 +5,10 @@ import { Button } from './button.component'; const meta: Meta<Button> = { component: Button, - //👇 Creates specific parameters for the story + //👇 Creates specific parameters at the component level parameters: { backgrounds: { - values: [ - { name: 'red', value: '#f00' }, - { name: 'green', value: '#0f0' }, - { name: 'blue', value: '#00f' }, - ], + default: 'dark', }, }, }; @@ -20,77 +16,169 @@ const meta: Meta<Button> = { export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + //👇 Creates specific parameters at the component level + parameters: { + backgrounds: { + default: 'dark', + }, + }, + }); +</script> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, + //👇 Creates specific parameters at the component level + parameters: { + backgrounds: { + default: 'dark', + }, + }, +}; +``` + ```js filename="Button.stories.js|jsx" renderer="common" language="js" import { Button } from './Button'; export default { component: Button, - // 👇 Meta-level parameters + //👇 Creates specific parameters at the component level parameters: { backgrounds: { default: 'dark', }, }, }; +``` + +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; -export const Basic = {}; + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + //👇 Creates specific parameters at the component level + parameters: { + backgrounds: { + default: 'dark', + }, + }, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, + //👇 Creates specific parameters at the component level + parameters: { + backgrounds: { + default: 'dark', + }, + }, +} satisfies Meta<typeof Button>; + +export default meta; ``` ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) -import type { Meta, StoryObj } from '@storybook/your-framework'; +import type { Meta } from '@storybook/your-framework'; import { Button } from './Button'; const meta = { component: Button, - // 👇 Meta-level parameters + //👇 Creates specific parameters at the component level parameters: { backgrounds: { default: 'dark', }, }, } satisfies Meta<typeof Button>; + export default meta; +``` + +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; -type Story = StoryObj<typeof Meta>; + import Button from './Button.svelte'; -export const Basic: Story = {}; + const { Story } = defineMeta({ + component: Button, + //👇 Creates specific parameters at the component level + parameters: { + backgrounds: { + default: 'dark', + }, + }, + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, + //👇 Creates specific parameters at the component level + parameters: { + backgrounds: { + default: 'dark', + }, + }, +}; + +export default meta; ``` ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) -import type { Meta, StoryObj } from '@storybook/your-framework'; +import type { Meta } from '@storybook/your-framework'; import { Button } from './Button'; const meta: Meta<typeof Button> = { component: Button, - // 👇 Meta-level parameters + //👇 Creates specific parameters at the component level parameters: { backgrounds: { default: 'dark', }, }, }; -export default meta; -type Story = StoryObj<typeof Button>; - -export const Basic: Story = {}; +export default meta; ``` ```js filename="Button.stories.js" renderer="web-components" language="js" export default { component: 'demo-button', - //👇 Creates specific parameters for the story + //👇 Creates specific parameters at the component level parameters: { backgrounds: { - values: [ - { name: 'red', value: '#f00' }, - { name: 'green', value: '#0f0' }, - { name: 'blue', value: '#00f' }, - ], + default: 'dark', }, }, }; @@ -101,18 +189,13 @@ import type { Meta } from '@storybook/web-components'; const meta: Meta = { component: 'demo-button', - //👇 Creates specific parameters for the story + //👇 Creates specific parameters at the component level parameters: { backgrounds: { - values: [ - { name: 'red', value: '#f00' }, - { name: 'green', value: '#0f0' }, - { name: 'blue', value: '#00f' }, - ], + default: 'dark', }, }, }; export default meta; ``` - diff --git a/docs/_snippets/parameters-in-preview.md b/docs/_snippets/parameters-in-preview.md index 06c35eae5a79..b017899e0316 100644 --- a/docs/_snippets/parameters-in-preview.md +++ b/docs/_snippets/parameters-in-preview.md @@ -28,4 +28,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/parameters-in-story.md b/docs/_snippets/parameters-in-story.md index 277c2d5fc2c5..77dfdf57459c 100644 --- a/docs/_snippets/parameters-in-story.md +++ b/docs/_snippets/parameters-in-story.md @@ -23,6 +23,43 @@ export const Primary: Story = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<!-- 👇 Story-level parameters--> +<Story + name="OnDark" + parameters={{ + backgrounds: { default: 'dark' } + }} +/> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, +}; + +export const OnDark = { + // 👇 Story-level parameters + parameters: { + backgrounds: { + default: 'dark', + }, + }, +}; +``` + ```js filename="Button.stories.js|jsx" renderer="common" language="js" import { Button } from './Button'; @@ -40,6 +77,48 @@ export const OnDark = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<!-- 👇 Story-level parameters--> +<Story + name="OnDark" + parameters={{ + backgrounds: { default: 'dark' } + }} +/> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, +} satisfies Meta<typeof Button>; + +export default meta; +type Story = StoryObj<typeof meta>; + +export const OnDark: Story = { + // 👇 Story-level parameters + parameters: { + backgrounds: { + default: 'dark', + }, + }, +}; +``` + ```ts filename="Button.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -49,9 +128,51 @@ import { Button } from './Button'; const meta = { component: Button, } satisfies Meta<typeof Button>; + export default meta; +type Story = StoryObj<typeof meta>; -type Story = StoryObj<typeof Meta>; +export const OnDark: Story = { + // 👇 Story-level parameters + parameters: { + backgrounds: { + default: 'dark', + }, + }, +}; +``` + +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<!-- 👇 Story-level parameters--> +<Story + name="OnDark" + parameters={{ + backgrounds: { default: 'dark' } + }} +/> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, +}; + +export default meta; +type Story = StoryObj<typeof Button>; export const OnDark: Story = { // 👇 Story-level parameters @@ -72,8 +193,8 @@ import { Button } from './Button'; const meta: Meta<typeof Button> = { component: Button, }; -export default meta; +export default meta; type Story = StoryObj<typeof Button>; export const OnDark: Story = { @@ -134,4 +255,3 @@ export const Primary: Story = { }, }; ``` - diff --git a/docs/_snippets/portable-stories-jest-compose-stories.md b/docs/_snippets/portable-stories-jest-compose-stories.md index 044ff413695d..cce7ff58c1af 100644 --- a/docs/_snippets/portable-stories-jest-compose-stories.md +++ b/docs/_snippets/portable-stories-jest-compose-stories.md @@ -50,4 +50,3 @@ test('renders primary button with overridden props', () => { expect(buttonElement).not.toBeNull(); }); ``` - diff --git a/docs/_snippets/portable-stories-jest-set-project-annotations.md b/docs/_snippets/portable-stories-jest-set-project-annotations.md index c17f1b25f2d3..022464514648 100644 --- a/docs/_snippets/portable-stories-jest-set-project-annotations.md +++ b/docs/_snippets/portable-stories-jest-set-project-annotations.md @@ -5,10 +5,7 @@ import { setProjectAnnotations } from '@storybook/react'; import * as addonAnnotations from 'my-addon/preview'; import * as previewAnnotations from './.storybook/preview'; -const annotations = setProjectAnnotations([ - previewAnnotations, - addonAnnotations, -]); +const annotations = setProjectAnnotations([previewAnnotations, addonAnnotations]); // Supports beforeAll hook from Storybook beforeAll(annotations.beforeAll); @@ -21,10 +18,7 @@ import { setProjectAnnotations } from '@storybook/vue3'; import * as addonAnnotations from 'my-addon/preview'; import * as previewAnnotations from './.storybook/preview'; -const annotations = setProjectAnnotations([ - previewAnnotations, - addonAnnotations, -]); +const annotations = setProjectAnnotations([previewAnnotations, addonAnnotations]); // Supports beforeAll hook from Storybook beforeAll(annotations.beforeAll); diff --git a/docs/_snippets/portable-stories-playwright-ct.md b/docs/_snippets/portable-stories-playwright-ct.md index c423a2ef1ff8..7f5b0eeb7589 100644 --- a/docs/_snippets/portable-stories-playwright-ct.md +++ b/docs/_snippets/portable-stories-playwright-ct.md @@ -45,4 +45,3 @@ test('renders primary button with overridden props', async ({ mount }) => { await expect(component.getByRole('button')).toHaveClass(/storybook-button--primary/); }); ``` - diff --git a/docs/_snippets/react-native-web-vite-add-framework.md b/docs/_snippets/react-native-web-vite-add-framework.md new file mode 100644 index 000000000000..afe03d4844a6 --- /dev/null +++ b/docs/_snippets/react-native-web-vite-add-framework.md @@ -0,0 +1,23 @@ +```js filename=".storybook/main.js" renderer="react-native-web" language="js" +export default { + addons: [ + '@storybook/addon-react-native-web', // 👈 Remove the addon + ], + // Replace @storybook/react-webpack5 with the Vite framework + framework: '@storybook/react-native-web-vite', +}; +``` + +```ts filename=".storybook/main.ts" renderer="react-native-web" language="ts" +import { StorybookConfig } from '@storybook/react-native-web-vite'; + +const config: StorybookConfig = { + addons: [ + '@storybook/addon-react-native-web', // 👈 Remove the addon + ], + // Replace @storybook/react-webpack5 with the Vite framework + framework: '@storybook/react-native-web-vite', +}; + +export default config; +``` diff --git a/docs/_snippets/react-native-web-vite-install.md b/docs/_snippets/react-native-web-vite-install.md new file mode 100644 index 000000000000..719993c04e77 --- /dev/null +++ b/docs/_snippets/react-native-web-vite-install.md @@ -0,0 +1,11 @@ +```shell renderer="react-native-web" language="js" packageManager="npm" +npm install --save-dev @storybook/react-native-web-vite vite +``` + +```shell renderer="react-native-web" language="js" packageManager="pnpm" +pnpm add --save-dev @storybook/react-native-web-vite vite +``` + +```shell renderer="react-native-web" language="js" packageManager="yarn" +yarn add --dev @storybook/react-native-web-vite vite +``` diff --git a/docs/_snippets/react-test-scripts-optional-config-scripts.md b/docs/_snippets/react-test-scripts-optional-config-scripts.md deleted file mode 100644 index a819f2dcce00..000000000000 --- a/docs/_snippets/react-test-scripts-optional-config-scripts.md +++ /dev/null @@ -1,8 +0,0 @@ -```json renderer="react" language="json" -{ - "scripts": { - "test": "react-scripts test --setupFiles ./setupFile.js" - } -} -``` - diff --git a/docs/_snippets/react-vite-add-framework.md b/docs/_snippets/react-vite-add-framework.md index e0989e989ed9..239b6c661bbd 100644 --- a/docs/_snippets/react-vite-add-framework.md +++ b/docs/_snippets/react-vite-add-framework.md @@ -17,4 +17,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/react-vite-framework-options.md b/docs/_snippets/react-vite-framework-options.md new file mode 100644 index 000000000000..dc37a8dd5ecf --- /dev/null +++ b/docs/_snippets/react-vite-framework-options.md @@ -0,0 +1,25 @@ +```js filename=".storybook/main.js" renderer="react" language="js" +export default { + framework: { + name: '@storybook/react-vite', + options: { + // ... + }, + }, +}; +``` + +```ts filename=".storybook/main.ts" renderer="react" language="ts" +import type { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { + framework: { + name: '@storybook/react-vite', + options: { + // ... + }, + }, +}; + +export default config; +``` diff --git a/docs/_snippets/react-vite-install.md b/docs/_snippets/react-vite-install.md index 1a9b6a3439b7..92880b1a4255 100644 --- a/docs/_snippets/react-vite-install.md +++ b/docs/_snippets/react-vite-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/react-vite ```shell renderer="react" language="js" packageManager="yarn" yarn add --dev @storybook/react-vite ``` - diff --git a/docs/_snippets/react-webpack5-add-framework.md b/docs/_snippets/react-webpack5-add-framework.md index 14bd2e484f8a..9dea87af6bc6 100644 --- a/docs/_snippets/react-webpack5-add-framework.md +++ b/docs/_snippets/react-webpack5-add-framework.md @@ -15,4 +15,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/react-webpack5-framework-options.md b/docs/_snippets/react-webpack5-framework-options.md new file mode 100644 index 000000000000..6a251f4d19ff --- /dev/null +++ b/docs/_snippets/react-webpack5-framework-options.md @@ -0,0 +1,25 @@ +```js filename=".storybook/main.js" renderer="react" language="js" +export default { + framework: { + name: '@storybook/react-webpack5', + options: { + // ... + }, + }, +}; +``` + +```ts filename=".storybook/main.ts" renderer="react" language="ts" +import type { StorybookConfig } from '@storybook/react-webpack5'; + +const config: StorybookConfig = { + framework: { + name: '@storybook/react-webpack5', + options: { + // ... + }, + }, +}; + +export default config; +``` diff --git a/docs/_snippets/react-webpack5-install.md b/docs/_snippets/react-webpack5-install.md index 999a6dd52824..05c4082f05df 100644 --- a/docs/_snippets/react-webpack5-install.md +++ b/docs/_snippets/react-webpack5-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/react-webpack5 ```shell renderer="react" language="js" packageManager="yarn" yarn add --dev @storybook/react-webpack5 ``` - diff --git a/docs/_snippets/register-component-with-play-function.md b/docs/_snippets/register-component-with-play-function.md index a5851e727f61..177564a6205a 100644 --- a/docs/_snippets/register-component-with-play-function.md +++ b/docs/_snippets/register-component-with-play-function.md @@ -43,6 +43,92 @@ export const FilledForm: Story = { }; ``` +```svelte filename="RegistrationForm.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import RegistrationForm from './RegistrationForm.svelte'; + + const { Story } = defineMeta({ + component: RegistrationForm, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="FilledForm" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { + selector: 'input', + }); + + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); + + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + + await userEvent.click(submitButton); + }} +/> +``` + +```js filename="RegistrationForm.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import { userEvent, within } from '@storybook/test'; + +import RegistrationForm from './RegistrationForm.svelte'; + +export default { + component: RegistrationForm, +}; + +/* + * See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const FilledForm = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { + selector: 'input', + }); + + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); + + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + + await userEvent.click(submitButton); + }, +}; +``` + ```js filename="RegistrationForm.stories.js|jsx" renderer="common" language="js" import { userEvent, within } from '@storybook/test'; @@ -83,6 +169,97 @@ export const FilledForm = { }; ``` +```svelte filename="RegistrationForm.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import RegistrationForm from './RegistrationForm.svelte'; + + const { Story } = defineMeta({ + component: RegistrationForm, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="FilledForm" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { + selector: 'input', + }); + + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); + + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + + await userEvent.click(submitButton); + }} +/> +``` + +```ts filename="RegistrationForm.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import RegistrationForm from './RegistrationForm.svelte'; + +const meta = { + component: RegistrationForm, +} satisfies Meta<typeof RegistrationForm>; + +export default meta; +type Story = StoryObj<typeof meta>; + +/* + * See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const FilledForm: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { + selector: 'input', + }); + + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); + + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + + await userEvent.click(submitButton); + }, +}; +``` + ```ts filename="RegistrationForm.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -129,6 +306,97 @@ export const FilledForm: Story = { }; ``` +```svelte filename="RegistrationForm.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import { userEvent, within } from '@storybook/test'; + + import RegistrationForm from './RegistrationForm.svelte'; + + const { Story } = defineMeta({ + component: RegistrationForm, + }); +</script> + +<!-- + See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + to learn more about using the canvasElement to query the DOM +--> +<Story + name="FilledForm" + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { + selector: 'input', + }); + + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); + + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + + await userEvent.click(submitButton); + }} +/> +``` + +```ts filename="RegistrationForm.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import { userEvent, within } from '@storybook/test'; + +import RegistrationForm from './RegistrationForm.svelte'; + +const meta: Meta<typeof RegistrationForm> = { + component: RegistrationForm, +}; + +export default meta; +type Story = StoryObj<typeof RegistrationForm>; + +/* + * See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas + * to learn more about using the canvasElement to query the DOM + */ +export const FilledForm: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { + selector: 'input', + }); + + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); + + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + // See https://storybook.js.org/docs/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + + await userEvent.click(submitButton); + }, +}; +``` + ```ts filename="RegistrationForm.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -215,6 +483,7 @@ export const FilledForm = { ```ts filename="RegistrationForm.stories.ts" renderer="web-components" language="ts" import type { Meta, StoryObj } from '@storybook/web-components'; + import { userEvent, within } from '@storybook/test'; const meta: Meta = { @@ -254,4 +523,3 @@ export const FilledForm: Story = { }, }; ``` - diff --git a/docs/_snippets/reuse-args-test.md b/docs/_snippets/reuse-args-test.md index 77784d643a8d..a394512e6eb5 100644 --- a/docs/_snippets/reuse-args-test.md +++ b/docs/_snippets/reuse-args-test.md @@ -34,7 +34,7 @@ test('reuses args from composed story', () => { }); ``` -```js filename="tests/Button.test.js" renderer="vue" language="js" tabTitle="3" +```js filename="tests/Button.test.js" renderer="vue" language="js" import { render, screen } from '@testing-library/vue'; import { composeStories } from '@storybook/vue3'; @@ -52,7 +52,7 @@ test('reuses args from composed story', () => { }); ``` -```ts filename="tests/Button.test.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="tests/Button.test.ts" renderer="vue" language="ts" import { render, screen } from '@testing-library/vue'; import { composeStories } from '@storybook/vue3'; @@ -69,4 +69,3 @@ test('reuses args from composed story', () => { expect(buttonElement.textContent).toEqual(Primary.args.label); }); ``` - diff --git a/docs/_snippets/rsc-feature-flag.md b/docs/_snippets/rsc-feature-flag.md index 4d0178c9ae03..9a2db0873a33 100644 --- a/docs/_snippets/rsc-feature-flag.md +++ b/docs/_snippets/rsc-feature-flag.md @@ -19,4 +19,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/rsc-parameter-in-meta.md b/docs/_snippets/rsc-parameter-in-meta.md index cf593965f0f4..0820be0dd2ba 100644 --- a/docs/_snippets/rsc-parameter-in-meta.md +++ b/docs/_snippets/rsc-parameter-in-meta.md @@ -36,4 +36,3 @@ const meta: Meta<typeof MyServerComponent> = { }; export default meta; ``` - diff --git a/docs/_snippets/seo-description.md b/docs/_snippets/seo-description.md index 04542626f0f6..ddb3af5fe47a 100644 --- a/docs/_snippets/seo-description.md +++ b/docs/_snippets/seo-description.md @@ -1,6 +1,3 @@ -```html renderer="common" language="ts" tabTitle="html" -{/* .storybook/manager-head.html */} - +```html filename=".storybook/manager-head.html" renderer="common" language="js" <meta name="description" content="Components for my awesome project" key="desc" /> ``` - diff --git a/docs/_snippets/seo-noindex.md b/docs/_snippets/seo-noindex.md index a373cb5d3bd1..2904002fef54 100644 --- a/docs/_snippets/seo-noindex.md +++ b/docs/_snippets/seo-noindex.md @@ -1,6 +1,3 @@ -```html renderer="common" language="ts" tabTitle="html" -{/* .storybook/manager-head.html */} - +```html filename=".storybook/manager-head.html" renderer="common" language="js" <meta name="robots" content="noindex" /> ``` - diff --git a/docs/_snippets/simple-page-implementation.md b/docs/_snippets/simple-page-implementation.md index 33b6dd0e246a..a44ac8ab1b16 100644 --- a/docs/_snippets/simple-page-implementation.md +++ b/docs/_snippets/simple-page-implementation.md @@ -100,9 +100,7 @@ function DocumentScreen({ user, document, subdocuments }) { } ``` -```html renderer="svelte" language="js" -{/* YourPage.svelte */} - +```svelte filename="YourPage.svelte" renderer="svelte" language="js" <script> import PageLayout from './PageLayout.svelte'; import DocumentHeader from './DocumentHeader.svelte'; @@ -121,9 +119,7 @@ function DocumentScreen({ user, document, subdocuments }) { </div> ``` -```html renderer="svelte" language="ts" -{/* YourPage.svelte */} - +```svelte filename="YourPage.svelte" renderer="svelte" language="ts" <script lang="ts"> import PageLayout from './PageLayout.svelte'; import DocumentHeader from './DocumentHeader.svelte'; @@ -142,9 +138,7 @@ function DocumentScreen({ user, document, subdocuments }) { </div> ``` -```html renderer="vue" language="js" tabTitle="3" -{/* YourPage.vue */} - +```html filename="YourPage.vue" renderer="vue" language="js" <template> <PageLayout :user="user"> <DocumentHeader :document="document" /> @@ -254,4 +248,3 @@ declare global { } } ``` - diff --git a/docs/_snippets/single-story-test.md b/docs/_snippets/single-story-test.md index 5ba0de1dbef4..77466b35b67b 100644 --- a/docs/_snippets/single-story-test.md +++ b/docs/_snippets/single-story-test.md @@ -44,7 +44,7 @@ test('Validates form', async () => { }); ``` -```js filename="tests/Form.test.js" renderer="vue" language="js" tabTitle="3" +```js filename="tests/Form.test.js" renderer="vue" language="js" import { fireEvent, screen } from '@testing-library/vue'; import { composeStory } from '@storybook/vue3'; @@ -67,7 +67,7 @@ test('Validates form', async () => { }); ``` -```ts filename="tests/Form.test.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="tests/Form.test.ts" renderer="vue" language="ts" import { fireEvent, screen } from '@testing-library/vue'; import { composeStory } from '@storybook/vue3'; diff --git a/docs/_snippets/storybook-add-command.md b/docs/_snippets/storybook-add-command.md index b05aae7b3e19..efc1547b33ea 100644 --- a/docs/_snippets/storybook-add-command.md +++ b/docs/_snippets/storybook-add-command.md @@ -9,4 +9,3 @@ pnpm dlx storybook@latest add @storybook/addon-a11y ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@latest add @storybook/addon-a11y ``` - diff --git a/docs/_snippets/storybook-addon-a11y-component-config.md b/docs/_snippets/storybook-addon-a11y-component-config.md index 3b54d8d96e63..d0b5ab9fee65 100644 --- a/docs/_snippets/storybook-addon-a11y-component-config.md +++ b/docs/_snippets/storybook-addon-a11y-component-config.md @@ -32,6 +32,70 @@ const meta: Meta<MyComponent> = { export default meta; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + parameters: { + a11y: { + // Optional selector to inspect + element: '#storybook-root', + config: { + rules: [ + { + // The autocomplete rule will not run based on the CSS selector provided + id: 'autocomplete-valid', + selector: '*:not([autocomplete="nope"])', + }, + { + // Setting the enabled option to false will disable checks for this particular rule on all stories. + id: 'image-alt', + enabled: false, + }, + ], + }, + options: {}, + manual: true, + }, + }, + }); +</script> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, + parameters: { + a11y: { + // Optional selector to inspect + element: '#storybook-root', + config: { + rules: [ + { + // The autocomplete rule will not run based on the CSS selector provided + id: 'autocomplete-valid', + selector: '*:not([autocomplete="nope"])', + }, + { + // Setting the enabled option to false will disable checks for this particular rule on all stories. + id: 'image-alt', + enabled: false, + }, + ], + }, + options: {}, + manual: true, + }, + }, +}; +``` + ```js filename="MyComponent.stories.js|jsx" renderer="common" language="js" import { MyComponent } from './MyComponent'; @@ -62,6 +126,74 @@ export default { }; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + parameters: { + a11y: { + // Optional selector to inspect + element: '#storybook-root', + config: { + rules: [ + { + // The autocomplete rule will not run based on the CSS selector provided + id: 'autocomplete-valid', + selector: '*:not([autocomplete="nope"])', + }, + { + // Setting the enabled option to false will disable checks for this particular rule on all stories. + id: 'image-alt', + enabled: false, + }, + ], + }, + options: {}, + manual: true, + }, + }, + }); +</script> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, + parameters: { + a11y: { + // Optional selector to inspect + element: '#storybook-root', + config: { + rules: [ + { + // The autocomplete rule will not run based on the CSS selector provided + id: 'autocomplete-valid', + selector: '*:not([autocomplete="nope"])', + }, + { + // Setting the enabled option to false will disable checks for this particular rule on all stories. + id: 'image-alt', + enabled: false, + }, + ], + }, + options: {}, + manual: true, + }, + }, +} satisfies Meta<typeof MyComponent>; + +export default meta; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts-4-9" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -97,6 +229,74 @@ const meta = { export default meta; ``` +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + parameters: { + a11y: { + // Optional selector to inspect + element: '#storybook-root', + config: { + rules: [ + { + // The autocomplete rule will not run based on the CSS selector provided + id: 'autocomplete-valid', + selector: '*:not([autocomplete="nope"])', + }, + { + // Setting the enabled option to false will disable checks for this particular rule on all stories. + id: 'image-alt', + enabled: false, + }, + ], + }, + options: {}, + manual: true, + }, + }, + }); +</script> +``` + +```ts filename="MyComponent.stories.ts|tsx" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import MyComponent from './MyComponent.svelte'; + +const meta: Meta<typeof MyComponent> = { + component: MyComponent, + parameters: { + a11y: { + // Optional selector to inspect + element: '#storybook-root', + config: { + rules: [ + { + // The autocomplete rule will not run based on the CSS selector provided + id: 'autocomplete-valid', + selector: '*:not([autocomplete="nope"])', + }, + { + // Setting the enabled option to false will disable checks for this particular rule on all stories. + id: 'image-alt', + enabled: false, + }, + ], + }, + options: {}, + manual: true, + }, + }, +}; + +export default meta; +``` + ```ts filename="MyComponent.stories.ts|tsx" renderer="common" language="ts" // Replace your-framework with the name of your framework import type { Meta } from '@storybook/your-framework'; @@ -191,4 +391,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/storybook-addon-a11y-disable.md b/docs/_snippets/storybook-addon-a11y-disable.md index 21df7df27a7f..083c3d108cbb 100644 --- a/docs/_snippets/storybook-addon-a11y-disable.md +++ b/docs/_snippets/storybook-addon-a11y-disable.md @@ -81,7 +81,29 @@ export const NonA11yStory: Story = { }; ``` -```js filename="MyComponent.stories.js" renderer="svelte" language="js" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="NonA11yStory" + parameters={{ + a11y: { + // This option disables all a11y checks on this story + disable: true, + }, + }} +/> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" import MyComponent from './MyComponent.svelte'; export default { @@ -98,7 +120,29 @@ export const NonA11yStory = { }; ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="NonA11yStory" + parameters={{ + a11y: { + // This option disables all a11y checks on this story + disable: true, + }, + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -120,7 +164,29 @@ export const NonA11yStory: Story = { }; ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="NonA11yStory" + parameters={{ + a11y: { + // This option disables all a11y checks on this story + disable: true, + }, + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -237,4 +303,3 @@ export const ExampleStory: Story = { }, }; ``` - diff --git a/docs/_snippets/storybook-addon-a11y-global-config.md b/docs/_snippets/storybook-addon-a11y-global-config.md index aca1ec05390a..9477dbcd23db 100644 --- a/docs/_snippets/storybook-addon-a11y-global-config.md +++ b/docs/_snippets/storybook-addon-a11y-global-config.md @@ -60,4 +60,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-addon-a11y-story-config.md b/docs/_snippets/storybook-addon-a11y-story-config.md index 5d556fb37551..5f9e31e99615 100644 --- a/docs/_snippets/storybook-addon-a11y-story-config.md +++ b/docs/_snippets/storybook-addon-a11y-story-config.md @@ -141,7 +141,44 @@ export const ExampleStory: Story = { }; ``` -```js filename="MyComponent.stories.js" renderer="svelte" language="js" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="ExampleStory" + parameters={{ + a11y: { + element: '#storybook-root', + config: { + rules: [ + { + // The autocomplete rule will not run based on the CSS selector provided + id: 'autocomplete-valid', + selector: '*:not([autocomplete="nope"])', + }, + { + // Setting the enabled option to false will disable checks for this particular rule on all stories. + id: 'image-alt', + enabled: false, + }, + ], + }, + options: {}, + manual: true, + }, + }} +/> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" import MyComponent from './MyComponent.svelte'; export default { @@ -173,7 +210,44 @@ export const ExampleStory = { }; ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="ExampleStory" + parameters={{ + a11y: { + element: '#storybook-root', + config: { + rules: [ + { + // The autocomplete rule will not run based on the CSS selector provided + id: 'autocomplete-valid', + selector: '*:not([autocomplete="nope"])', + }, + { + // Setting the enabled option to false will disable checks for this particular rule on all stories. + id: 'image-alt', + enabled: false, + }, + ], + }, + options: {}, + manual: true, + }, + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -210,7 +284,44 @@ export const ExampleStory: Story = { }; ``` -```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); +</script> + +<Story + name="ExampleStory" + parameters={{ + a11y: { + element: '#storybook-root', + config: { + rules: [ + { + // The autocomplete rule will not run based on the CSS selector provided + id: 'autocomplete-valid', + selector: '*:not([autocomplete="nope"])', + }, + { + // Setting the enabled option to false will disable checks for this particular rule on all stories. + id: 'image-alt', + enabled: false, + }, + ], + }, + options: {}, + manual: true, + }, + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import MyComponent from './MyComponent.svelte'; @@ -417,4 +528,3 @@ export const ExampleStory: Story = { }, }; ``` - diff --git a/docs/_snippets/storybook-addon-actions-install.md b/docs/_snippets/storybook-addon-actions-install.md index 65b3d1f57f51..67330880ee57 100644 --- a/docs/_snippets/storybook-addon-actions-install.md +++ b/docs/_snippets/storybook-addon-actions-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/addon-actions ```shell renderer="common" language="js" packageManager="yarn" yarn add --dev @storybook/addon-actions ``` - diff --git a/docs/_snippets/storybook-addon-compiler-babel-auto-install.md b/docs/_snippets/storybook-addon-compiler-babel-auto-install.md index 7b16b4eff4ac..21d3cac26c54 100644 --- a/docs/_snippets/storybook-addon-compiler-babel-auto-install.md +++ b/docs/_snippets/storybook-addon-compiler-babel-auto-install.md @@ -9,4 +9,3 @@ pnpm dlx storybook@latest add @storybook/addon-webpack5-compiler-babel ```sh renderer="common" language="js" packageManager="yarn" yarn dlx storybook@latest add @storybook/addon-webpack5-compiler-babel ``` - diff --git a/docs/_snippets/storybook-addon-compiler-swc-auto-install.md b/docs/_snippets/storybook-addon-compiler-swc-auto-install.md index 6514413071b4..eeb0fd91effd 100644 --- a/docs/_snippets/storybook-addon-compiler-swc-auto-install.md +++ b/docs/_snippets/storybook-addon-compiler-swc-auto-install.md @@ -9,4 +9,3 @@ pnpm dlx storybook@latest add @storybook/addon-webpack5-compiler-swc ```sh renderer="common" language="js" packageManager="yarn" yarn dlx storybook@latest add @storybook/addon-webpack5-compiler-swc ``` - diff --git a/docs/_snippets/storybook-addon-controls-custom-matchers.md b/docs/_snippets/storybook-addon-controls-custom-matchers.md index b3034ecc8fb4..80b0358eedc7 100644 --- a/docs/_snippets/storybook-addon-controls-custom-matchers.md +++ b/docs/_snippets/storybook-addon-controls-custom-matchers.md @@ -28,4 +28,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-addon-css-example.md b/docs/_snippets/storybook-addon-css-example.md index aa1804c4345a..43717ddff9b7 100644 --- a/docs/_snippets/storybook-addon-css-example.md +++ b/docs/_snippets/storybook-addon-css-example.md @@ -400,4 +400,3 @@ export default function outlineCSS(selector: string) { }`; } ``` - diff --git a/docs/_snippets/storybook-addon-css-helpers.md b/docs/_snippets/storybook-addon-css-helpers.md index ca26b48c96aa..6042092b8a4d 100644 --- a/docs/_snippets/storybook-addon-css-helpers.md +++ b/docs/_snippets/storybook-addon-css-helpers.md @@ -28,4 +28,3 @@ export const addOutlineStyles = (selector: string, css: string) => { } }; ``` - diff --git a/docs/_snippets/storybook-addon-disable-addon.md b/docs/_snippets/storybook-addon-disable-addon.md index ab13eb19dd0c..14425334d383 100644 --- a/docs/_snippets/storybook-addon-disable-addon.md +++ b/docs/_snippets/storybook-addon-disable-addon.md @@ -8,4 +8,3 @@ addons.register(ADDON_ID, () => { }); }); ``` - diff --git a/docs/_snippets/storybook-addon-essentials-install.md b/docs/_snippets/storybook-addon-essentials-install.md index 9356730d029f..bdae3e81827d 100644 --- a/docs/_snippets/storybook-addon-essentials-install.md +++ b/docs/_snippets/storybook-addon-essentials-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/addon-essentials ```shell renderer="common" language="js" packageManager="yarn" yarn add --dev @storybook/addon-essentials ``` - diff --git a/docs/_snippets/storybook-addon-interactions-addon-full-install.md b/docs/_snippets/storybook-addon-interactions-addon-full-install.md index 52fee5c9399c..7b1fdf2b596c 100644 --- a/docs/_snippets/storybook-addon-interactions-addon-full-install.md +++ b/docs/_snippets/storybook-addon-interactions-addon-full-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/test @storybook/addon-interactions ```shell renderer="common" language="js" packageManager="yarn" yarn add --dev @storybook/test @storybook/addon-interactions ``` - diff --git a/docs/_snippets/storybook-addon-load-external-addons-preset.md b/docs/_snippets/storybook-addon-load-external-addons-preset.md index c5ab753a784e..2f269cc80d89 100644 --- a/docs/_snippets/storybook-addon-load-external-addons-preset.md +++ b/docs/_snippets/storybook-addon-load-external-addons-preset.md @@ -12,4 +12,3 @@ export default { config, }; ``` - diff --git a/docs/_snippets/storybook-addon-manager-initial-state.md b/docs/_snippets/storybook-addon-manager-initial-state.md index edfc8c4cebad..71d9fed8fc99 100644 --- a/docs/_snippets/storybook-addon-manager-initial-state.md +++ b/docs/_snippets/storybook-addon-manager-initial-state.md @@ -14,4 +14,3 @@ addons.register(ADDON_ID, () => { }); }); ``` - diff --git a/docs/_snippets/storybook-addon-panel-example.md b/docs/_snippets/storybook-addon-panel-example.md index d4a238b56d29..d3ad9292c3c9 100644 --- a/docs/_snippets/storybook-addon-panel-example.md +++ b/docs/_snippets/storybook-addon-panel-example.md @@ -18,4 +18,3 @@ addons.register('my/panel', () => { }); }); ``` - diff --git a/docs/_snippets/storybook-addon-panel-initial.md b/docs/_snippets/storybook-addon-panel-initial.md index db5a41c043d3..cf333e77f909 100644 --- a/docs/_snippets/storybook-addon-panel-initial.md +++ b/docs/_snippets/storybook-addon-panel-initial.md @@ -20,4 +20,3 @@ addons.register(ADDON_ID, (api) => { }); }); ``` - diff --git a/docs/_snippets/storybook-addon-preset-example.md b/docs/_snippets/storybook-addon-preset-example.md index a3d1576ff187..15e574b8afdc 100644 --- a/docs/_snippets/storybook-addon-preset-example.md +++ b/docs/_snippets/storybook-addon-preset-example.md @@ -18,4 +18,3 @@ export default { }, }; ``` - diff --git a/docs/_snippets/storybook-addon-release.md b/docs/_snippets/storybook-addon-release.md index 9f259853945a..ec5283958eb2 100644 --- a/docs/_snippets/storybook-addon-release.md +++ b/docs/_snippets/storybook-addon-release.md @@ -9,4 +9,3 @@ pnpm run release ```shell renderer="common" language="js" packageManager="yarn" yarn release ``` - diff --git a/docs/_snippets/storybook-addon-run-dev-mode.md b/docs/_snippets/storybook-addon-run-dev-mode.md index 5d42f499948f..5970f3f10942 100644 --- a/docs/_snippets/storybook-addon-run-dev-mode.md +++ b/docs/_snippets/storybook-addon-run-dev-mode.md @@ -9,4 +9,3 @@ pnpm run start ```sh renderer="common" language="js" packageManager="yarn" yarn start ``` - diff --git a/docs/_snippets/storybook-addon-tab-example.md b/docs/_snippets/storybook-addon-tab-example.md index 3a8bfe4e8c99..018512d70638 100644 --- a/docs/_snippets/storybook-addon-tab-example.md +++ b/docs/_snippets/storybook-addon-tab-example.md @@ -15,4 +15,3 @@ addons.register('my-addon', () => { }); }); ``` - diff --git a/docs/_snippets/storybook-addon-themes-classname-decorator.md b/docs/_snippets/storybook-addon-themes-classname-decorator.md index e631a59d6018..9537c10e27fe 100644 --- a/docs/_snippets/storybook-addon-themes-classname-decorator.md +++ b/docs/_snippets/storybook-addon-themes-classname-decorator.md @@ -61,4 +61,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-addon-themes-data-attribute-decorator.md b/docs/_snippets/storybook-addon-themes-data-attribute-decorator.md index df1c98a1ba4a..80f962858e22 100644 --- a/docs/_snippets/storybook-addon-themes-data-attribute-decorator.md +++ b/docs/_snippets/storybook-addon-themes-data-attribute-decorator.md @@ -64,4 +64,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-addon-themes-jsx-provider-decorator.md b/docs/_snippets/storybook-addon-themes-jsx-provider-decorator.md index d1410d95fff9..2a6fa61d7e4a 100644 --- a/docs/_snippets/storybook-addon-themes-jsx-provider-decorator.md +++ b/docs/_snippets/storybook-addon-themes-jsx-provider-decorator.md @@ -87,4 +87,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-addon-tool-initial-setup.md b/docs/_snippets/storybook-addon-tool-initial-setup.md index 41d49160894f..c022750dbf69 100644 --- a/docs/_snippets/storybook-addon-tool-initial-setup.md +++ b/docs/_snippets/storybook-addon-tool-initial-setup.md @@ -36,4 +36,3 @@ export const Tool = memo(function MyAddonSelector() { ); }); ``` - diff --git a/docs/_snippets/storybook-addon-toolbar-example.md b/docs/_snippets/storybook-addon-toolbar-example.md index 07085331198e..1909cd698b03 100644 --- a/docs/_snippets/storybook-addon-toolbar-example.md +++ b/docs/_snippets/storybook-addon-toolbar-example.md @@ -20,4 +20,3 @@ addons.register('my-addon', () => { }); }); ``` - diff --git a/docs/_snippets/storybook-addon-toolkit-panel-example.md b/docs/_snippets/storybook-addon-toolkit-panel-example.md deleted file mode 100644 index 9a4a9f3ebd01..000000000000 --- a/docs/_snippets/storybook-addon-toolkit-panel-example.md +++ /dev/null @@ -1,42 +0,0 @@ -```tsx filename="src/Panel.tsx" renderer="common" language="ts" tabTitle="panel" -import React from 'react'; - -import { useAddonState, useChannel } from '@storybook/manager-api'; -import { AddonPanel } from '@storybook/components'; -import { ADDON_ID, EVENTS } from './constants'; - -// See https://github.com/storybookjs/addon-kit/blob/main/src/components/PanelContent.tsx for an example of a PanelContent component -import { PanelContent } from './components/PanelContent'; - -interface PanelProps { - active: boolean; -} - -export const Panel: React.FC<PanelProps> = (props) => { - // https://storybook.js.org/docs/addons/addons-api#useaddonstate - const [results, setState] = useAddonState(ADDON_ID, { - danger: [], - warning: [], - }); - - // https://storybook.js.org/docs/addons/addons-api#usechannel - const emit = useChannel({ - [EVENTS.RESULT]: (newResults) => setState(newResults), - }); - - return ( - <AddonPanel {...props}> - <PanelContent - results={results} - fetchData={() => { - emit(EVENTS.REQUEST); - }} - clearData={() => { - emit(EVENTS.CLEAR); - }} - /> - </AddonPanel> - ); -}; -``` - diff --git a/docs/_snippets/storybook-addon-toolkit-tab-example.md b/docs/_snippets/storybook-addon-toolkit-tab-example.md deleted file mode 100644 index 414873d12743..000000000000 --- a/docs/_snippets/storybook-addon-toolkit-tab-example.md +++ /dev/null @@ -1,21 +0,0 @@ -```tsx filename="src/Tab.tsx" renderer="common" language="ts" tabTitle="tab" -import React from 'react'; - -import { useParameter } from '@storybook/manager-api'; -import { PARAM_KEY } from './constants'; - -// See https://github.com/storybookjs/addon-kit/blob/main/src/components/TabContent.tsx for an example of a TabContent component -import { TabContent } from './components/TabContent'; - -interface TabProps { - active: boolean; -} - -export const Tab: React.FC<TabProps> = ({ active }) => { - // https://storybook.js.org/docs/addons/addons-api#useparameter - const paramData = useParameter<string>(PARAM_KEY, ''); - - return active ? <TabContent code={paramData} /> : null; -}; -``` - diff --git a/docs/_snippets/storybook-addon-toolkit-toolbar-example.md b/docs/_snippets/storybook-addon-toolkit-toolbar-example.md deleted file mode 100644 index 6b1cbb481cf1..000000000000 --- a/docs/_snippets/storybook-addon-toolkit-toolbar-example.md +++ /dev/null @@ -1,39 +0,0 @@ -```tsx filename="src/Tool.tsx" renderer="common" language="ts" tabTitle="toolbar" -import React, { memo, useCallback, useEffect } from 'react'; - -import { useGlobals, useStorybookApi } from '@storybook/manager-api'; -import { IconButton } from '@storybook/components'; -import { LightningIcon } from '@storybook/icons'; - -import { ADDON_ID, PARAM_KEY, TOOL_ID } from './constants'; - -export const Tool = memo(function MyAddonSelector() { - const [globals, updateGlobals] = useGlobals(); - const api = useStorybookApi(); - - const isActive = [true, 'true'].includes(globals[PARAM_KEY]); - - const toggleMyTool = useCallback(() => { - updateGlobals({ - [PARAM_KEY]: !isActive, - }); - }, [isActive]); - - useEffect(() => { - api.setAddonShortcut(ADDON_ID, { - label: 'Toggle Measure [O]', - defaultShortcut: ['O'], - actionName: 'outline', - showInMenu: false, - action: toggleMyTool, - }); - }, [toggleMyTool, api]); - - return ( - <IconButton key={TOOL_ID} active={isActive} title="Enable my addon" onClick={toggleMyTool}> - <LightningIcon /> - </IconButton> - ); -}); -``` - diff --git a/docs/_snippets/storybook-addon-toolkit-types.md b/docs/_snippets/storybook-addon-toolkit-types.md new file mode 100644 index 000000000000..8f125c6384bd --- /dev/null +++ b/docs/_snippets/storybook-addon-toolkit-types.md @@ -0,0 +1,103 @@ +```tsx filename="src/Tool.tsx" renderer="common" language="ts" tabTitle="Toolbar" +import React, { memo, useCallback, useEffect } from 'react'; + +import { useGlobals, useStorybookApi } from '@storybook/manager-api'; +import { IconButton } from '@storybook/components'; +import { LightningIcon } from '@storybook/icons'; + +import { ADDON_ID, PARAM_KEY, TOOL_ID } from './constants'; + +export const Tool = memo(function MyAddonSelector() { + const [globals, updateGlobals] = useGlobals(); + const api = useStorybookApi(); + + const isActive = [true, 'true'].includes(globals[PARAM_KEY]); + + const toggleMyTool = useCallback(() => { + updateGlobals({ + [PARAM_KEY]: !isActive, + }); + }, [isActive]); + + useEffect(() => { + api.setAddonShortcut(ADDON_ID, { + label: 'Toggle Measure [O]', + defaultShortcut: ['O'], + actionName: 'outline', + showInMenu: false, + action: toggleMyTool, + }); + }, [toggleMyTool, api]); + + return ( + <IconButton key={TOOL_ID} active={isActive} title="Enable my addon" onClick={toggleMyTool}> + <LightningIcon /> + </IconButton> + ); +}); +``` + +```tsx filename="src/Panel.tsx" renderer="common" language="ts" tabTitle="Panel" +import React from 'react'; + +import { useAddonState, useChannel } from '@storybook/manager-api'; +import { AddonPanel } from '@storybook/components'; + +import { ADDON_ID, EVENTS } from './constants'; + +// See https://github.com/storybookjs/addon-kit/blob/main/src/components/PanelContent.tsx for an example of a PanelContent component +import { PanelContent } from './components/PanelContent'; + +interface PanelProps { + active: boolean; +} + +export const Panel: React.FC<PanelProps> = (props) => { + // https://storybook.js.org/docs/addons/addons-api#useaddonstate + const [results, setState] = useAddonState(ADDON_ID, { + danger: [], + warning: [], + }); + + // https://storybook.js.org/docs/addons/addons-api#usechannel + const emit = useChannel({ + [EVENTS.RESULT]: (newResults) => setState(newResults), + }); + + return ( + <AddonPanel {...props}> + <PanelContent + results={results} + fetchData={() => { + emit(EVENTS.REQUEST); + }} + clearData={() => { + emit(EVENTS.CLEAR); + }} + /> + </AddonPanel> + ); +}; +``` + +```tsx filename="src/Tab.tsx" renderer="common" language="ts" tabTitle="Tab" +import React from 'react'; + +import { useParameter } from '@storybook/manager-api'; + +import { PARAM_KEY } from './constants'; + +// See https://github.com/storybookjs/addon-kit/blob/main/src/components/TabContent.tsx for an example of a TabContent component +import { TabContent } from './components/TabContent'; + +interface TabProps { + active: boolean; +} + +export const Tab: React.FC<TabProps> = ({ active }) => { + // https://storybook.js.org/docs/addons/addons-api#useparameter + const paramData = useParameter<string>(PARAM_KEY, ''); + + return active ? <TabContent code={paramData} /> : null; +}; +``` diff --git a/docs/_snippets/storybook-addon-use-global.md b/docs/_snippets/storybook-addon-use-global.md index d76efaa58d02..013cdc2424c0 100644 --- a/docs/_snippets/storybook-addon-use-global.md +++ b/docs/_snippets/storybook-addon-use-global.md @@ -39,4 +39,3 @@ export const withGlobals = (StoryFn: StoryFunction<Renderer>, context: StoryCont return StoryFn(); }; ``` - diff --git a/docs/_snippets/storybook-addons-api-disablequeryparams.md b/docs/_snippets/storybook-addons-api-disablequeryparams.md index 8821abe7b9bc..c4751243c004 100644 --- a/docs/_snippets/storybook-addons-api-disablequeryparams.md +++ b/docs/_snippets/storybook-addons-api-disablequeryparams.md @@ -5,4 +5,3 @@ addons.register('my-organisation/my-addon', (api) => { }); }); ``` - diff --git a/docs/_snippets/storybook-addons-api-getchannel.md b/docs/_snippets/storybook-addons-api-getchannel.md index 1ede828b92b4..6fcaa6fe7441 100644 --- a/docs/_snippets/storybook-addons-api-getchannel.md +++ b/docs/_snippets/storybook-addons-api-getchannel.md @@ -35,4 +35,3 @@ const ExampleToolbar = () => { ); }; ``` - diff --git a/docs/_snippets/storybook-addons-api-getqueryparam.md b/docs/_snippets/storybook-addons-api-getqueryparam.md index fa8f7851a408..3ef6b29445d3 100644 --- a/docs/_snippets/storybook-addons-api-getqueryparam.md +++ b/docs/_snippets/storybook-addons-api-getqueryparam.md @@ -3,4 +3,3 @@ addons.register('my-organisation/my-addon', (api) => { api.getQueryParam('exampleParameter'); }); ``` - diff --git a/docs/_snippets/storybook-addons-api-geturlstate.md b/docs/_snippets/storybook-addons-api-geturlstate.md index f0cc2cad0298..4b4c499a91a5 100644 --- a/docs/_snippets/storybook-addons-api-geturlstate.md +++ b/docs/_snippets/storybook-addons-api-geturlstate.md @@ -6,4 +6,3 @@ addons.register('my-organisation/my-addon', (api) => { }).url; }); ``` - diff --git a/docs/_snippets/storybook-addons-api-imports.md b/docs/_snippets/storybook-addons-api-imports.md index 8781eb4e3294..8583f2557df1 100644 --- a/docs/_snippets/storybook-addons-api-imports.md +++ b/docs/_snippets/storybook-addons-api-imports.md @@ -3,4 +3,3 @@ import { addons } from '@storybook/preview-api'; import { useStorybookApi } from '@storybook/manager-api'; ``` - diff --git a/docs/_snippets/storybook-addons-api-makedecorator.md b/docs/_snippets/storybook-addons-api-makedecorator.md index cf81e50a500a..253c85674afa 100644 --- a/docs/_snippets/storybook-addons-api-makedecorator.md +++ b/docs/_snippets/storybook-addons-api-makedecorator.md @@ -14,4 +14,3 @@ export const withAddonDecorator = makeDecorator({ }, }); ``` - diff --git a/docs/_snippets/storybook-addons-api-on.md b/docs/_snippets/storybook-addons-api-on.md index 2aeb8704466e..da4d48dfe1a2 100644 --- a/docs/_snippets/storybook-addons-api-on.md +++ b/docs/_snippets/storybook-addons-api-on.md @@ -4,4 +4,3 @@ addons.register('my-organisation/my-addon', (api) => { api.on('custom-addon-event', (eventData) => console.log(eventData)); }); ``` - diff --git a/docs/_snippets/storybook-addons-api-register.md b/docs/_snippets/storybook-addons-api-register.md index 24dc8753428f..a1d007bf85da 100644 --- a/docs/_snippets/storybook-addons-api-register.md +++ b/docs/_snippets/storybook-addons-api-register.md @@ -4,4 +4,3 @@ import { addons } from '@storybook/preview-api'; // Register the addon with a unique name. addons.register('my-organisation/my-addon', (api) => {}); ``` - diff --git a/docs/_snippets/storybook-addons-api-selectincurrentkind.md b/docs/_snippets/storybook-addons-api-selectincurrentkind.md index ade4ddb672ba..81c2666b11e4 100644 --- a/docs/_snippets/storybook-addons-api-selectincurrentkind.md +++ b/docs/_snippets/storybook-addons-api-selectincurrentkind.md @@ -3,4 +3,3 @@ addons.register('my-organisation/my-addon', (api) => { api.selectInCurrentKind('Default'); }); ``` - diff --git a/docs/_snippets/storybook-addons-api-selectstory.md b/docs/_snippets/storybook-addons-api-selectstory.md index 82f9189e9fac..7527b6a414f2 100644 --- a/docs/_snippets/storybook-addons-api-selectstory.md +++ b/docs/_snippets/storybook-addons-api-selectstory.md @@ -3,4 +3,3 @@ addons.register('my-organisation/my-addon', (api) => { api.selectStory('Button', 'Default'); }); ``` - diff --git a/docs/_snippets/storybook-addons-api-setqueryparams.md b/docs/_snippets/storybook-addons-api-setqueryparams.md index 6bcff839dcd6..0bada2cc3872 100644 --- a/docs/_snippets/storybook-addons-api-setqueryparams.md +++ b/docs/_snippets/storybook-addons-api-setqueryparams.md @@ -6,4 +6,3 @@ addons.register('my-organisation/my-addon', (api) => { }); }); ``` - diff --git a/docs/_snippets/storybook-addons-api-useaddonstate.md b/docs/_snippets/storybook-addons-api-useaddonstate.md index 1937c7430978..e93b21ab9555 100644 --- a/docs/_snippets/storybook-addons-api-useaddonstate.md +++ b/docs/_snippets/storybook-addons-api-useaddonstate.md @@ -31,4 +31,3 @@ export const Tool = () => { ); }; ``` - diff --git a/docs/_snippets/storybook-addons-api-useapi.md b/docs/_snippets/storybook-addons-api-useapi.md index ebb6ae16514f..4a814e88637a 100644 --- a/docs/_snippets/storybook-addons-api-useapi.md +++ b/docs/_snippets/storybook-addons-api-useapi.md @@ -29,4 +29,3 @@ export const Panel = () => { ); }; ``` - diff --git a/docs/_snippets/storybook-addons-api-usechannel.md b/docs/_snippets/storybook-addons-api-usechannel.md index d937a578f9b5..41d62c63362a 100644 --- a/docs/_snippets/storybook-addons-api-usechannel.md +++ b/docs/_snippets/storybook-addons-api-usechannel.md @@ -22,4 +22,3 @@ export const Panel = () => { ); }; ``` - diff --git a/docs/_snippets/storybook-addons-api-useglobal.md b/docs/_snippets/storybook-addons-api-useglobal.md index d38006e0c6d7..c865aa0c77a5 100644 --- a/docs/_snippets/storybook-addons-api-useglobal.md +++ b/docs/_snippets/storybook-addons-api-useglobal.md @@ -19,4 +19,3 @@ export const Panel = () => { ); }; ``` - diff --git a/docs/_snippets/storybook-addons-api-useparameter.md b/docs/_snippets/storybook-addons-api-useparameter.md index 0ec10728e7a4..589da852e380 100644 --- a/docs/_snippets/storybook-addons-api-useparameter.md +++ b/docs/_snippets/storybook-addons-api-useparameter.md @@ -20,4 +20,3 @@ export const Panel = () => { ); }; ``` - diff --git a/docs/_snippets/storybook-addons-api-usestorybookstate.md b/docs/_snippets/storybook-addons-api-usestorybookstate.md index 33de5d43a452..81b58b77e276 100644 --- a/docs/_snippets/storybook-addons-api-usestorybookstate.md +++ b/docs/_snippets/storybook-addons-api-usestorybookstate.md @@ -18,4 +18,3 @@ export const Panel = () => { ); }; ``` - diff --git a/docs/_snippets/storybook-addons-local-preset.md b/docs/_snippets/storybook-addons-local-preset.md index 9b550fac5beb..63f298ae2da6 100644 --- a/docs/_snippets/storybook-addons-local-preset.md +++ b/docs/_snippets/storybook-addons-local-preset.md @@ -21,4 +21,3 @@ export const viteFinal = vite as any; export const babelDefault = babel as any; ``` - diff --git a/docs/_snippets/storybook-addons-preset-babelDefault.md b/docs/_snippets/storybook-addons-preset-babelDefault.md index afb8140b74a7..b353cf4ff3d0 100644 --- a/docs/_snippets/storybook-addons-preset-babelDefault.md +++ b/docs/_snippets/storybook-addons-preset-babelDefault.md @@ -23,4 +23,3 @@ export function babelDefault(config: TransformOptions) { }; } ``` - diff --git a/docs/_snippets/storybook-addons-preset-preview.md b/docs/_snippets/storybook-addons-preset-preview.md index 427ba4b3e27a..7c76b2b544de 100644 --- a/docs/_snippets/storybook-addons-preset-preview.md +++ b/docs/_snippets/storybook-addons-preset-preview.md @@ -27,4 +27,3 @@ const preview: ProjectAnnotations<Renderer> = { export default preview; ``` - diff --git a/docs/_snippets/storybook-addons-preset-viteFinal.md b/docs/_snippets/storybook-addons-preset-viteFinal.md index 1bd9a2b364e7..90e285529f0f 100644 --- a/docs/_snippets/storybook-addons-preset-viteFinal.md +++ b/docs/_snippets/storybook-addons-preset-viteFinal.md @@ -3,7 +3,7 @@ export function ViteFinal(config, options = {}) { config.plugins.push( new MyCustomPlugin({ someOption: true, - }), + }) ); return config; @@ -15,10 +15,9 @@ export function ViteFinal(config: any, options: any = {}) { config.plugins.push( new MyCustomPlugin({ someOption: true, - }), + }) ); return config; } ``` - diff --git a/docs/_snippets/storybook-addons-preset-webpackFinal.md b/docs/_snippets/storybook-addons-preset-webpackFinal.md index 7b9f572720fa..f9bc01b4cd48 100644 --- a/docs/_snippets/storybook-addons-preset-webpackFinal.md +++ b/docs/_snippets/storybook-addons-preset-webpackFinal.md @@ -29,4 +29,3 @@ export function webpackFinal(config: WebpackConfig, options: any = {}) { return config; } ``` - diff --git a/docs/_snippets/storybook-addons-preset.md b/docs/_snippets/storybook-addons-preset.md index ce5b88059d76..5520d1601cdb 100644 --- a/docs/_snippets/storybook-addons-preset.md +++ b/docs/_snippets/storybook-addons-preset.md @@ -9,4 +9,3 @@ export const previewAnnotations = (entry = [], options) => { return [...entry, require.resolve('./dist/preview')]; }; ``` - diff --git a/docs/_snippets/storybook-addons-root-preset-manager-entries.md b/docs/_snippets/storybook-addons-root-preset-manager-entries.md index 69b6fb88d02d..4fcba6772427 100644 --- a/docs/_snippets/storybook-addons-root-preset-manager-entries.md +++ b/docs/_snippets/storybook-addons-root-preset-manager-entries.md @@ -1,8 +1,5 @@ -```js renderer="common" language="js" -//example-addon/preset.js - +```js filename="example-addon/preset.js" renderer="common" language="js" export const managerEntries = (entry = []) => { return [...entry, require.resolve('path-to-third-party-addon')]; }; ``` - diff --git a/docs/_snippets/storybook-addons-root-preset-preview-annotations.md b/docs/_snippets/storybook-addons-root-preset-preview-annotations.md index af473955e722..e4cda76b90c1 100644 --- a/docs/_snippets/storybook-addons-root-preset-preview-annotations.md +++ b/docs/_snippets/storybook-addons-root-preset-preview-annotations.md @@ -3,4 +3,3 @@ export const previewAnnotations = (entry = [], options) => { return [...entry, require.resolve('./dist/preview')]; }; ``` - diff --git a/docs/_snippets/storybook-addons-root-preset.md b/docs/_snippets/storybook-addons-root-preset.md index 8ac301891c48..2abfc784b82a 100644 --- a/docs/_snippets/storybook-addons-root-preset.md +++ b/docs/_snippets/storybook-addons-root-preset.md @@ -5,4 +5,3 @@ export const managerEntries = [require.resolve('./dist/manager')]; export * from './dist/preset'; ``` - diff --git a/docs/_snippets/storybook-args-url-params-converted.md b/docs/_snippets/storybook-args-url-params-converted.md index 1d42e5267ef1..5a8ec7a715bb 100644 --- a/docs/_snippets/storybook-args-url-params-converted.md +++ b/docs/_snippets/storybook-args-url-params-converted.md @@ -5,4 +5,3 @@ nil: null } ``` - diff --git a/docs/_snippets/storybook-argtypes-with-addon.md b/docs/_snippets/storybook-argtypes-with-addon.md index c7657e7dc142..1914326e61ed 100644 --- a/docs/_snippets/storybook-argtypes-with-addon.md +++ b/docs/_snippets/storybook-argtypes-with-addon.md @@ -4,4 +4,3 @@ import { useArgTypes } from '@storybook/manager-api'; // inside your panel const { argTypes } = useArgTypes(); ``` - diff --git a/docs/_snippets/storybook-auto-docs-baseline-example.md b/docs/_snippets/storybook-auto-docs-baseline-example.md index fe87ee88e10a..cf9367ae7795 100644 --- a/docs/_snippets/storybook-auto-docs-baseline-example.md +++ b/docs/_snippets/storybook-auto-docs-baseline-example.md @@ -1,7 +1,4 @@ - renderer="common" language="mdx" tabTitle="custom-title" -```mdx -{/* Button.mdx */} - +```mdx filename="Button.mdx" renderer="common" language="mdx" tabTitle="custom-title" import { Meta, Controls } from '@storybook/blocks'; <Meta title="Button" /> @@ -25,41 +22,7 @@ Button has the following properties: <Controls /> ``` - renderer="common" language="mdx" -```mdx -{/* Button.mdx */} - -import { Meta } from '@storybook/blocks'; - -<Meta title="Button" /> - -# Definition - -Button is a clickable interactive element that triggers a response. - -You can place text and icons inside of a button. - -Buttons are often used for form submissions and to toggle elements into view. - -## Usage - -The component comes in different variants such as `primary`, `secondary`, `large` and `small` which you can use to alter the look and feel of the button. - -## Inputs - -Button has the following properties: - -- `primary` - If `true`, the button will have a primary style. -- `size` - The size of the button. -- `label` - The label of the button. -- `backgroundColor` - The background color of the button. -- `onClick` - Callback function when clicked. -``` - - renderer="common" language="mdx" tabTitle="of-prop" -```mdx -{/* Button.mdx */} - +```mdx filename="Button.mdx" renderer="common" language="mdx" tabTitle="of-prop" import { Meta, Controls } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; @@ -84,4 +47,3 @@ Button has the following properties: <Controls /> ``` - diff --git a/docs/_snippets/storybook-auto-docs-custom-file.md b/docs/_snippets/storybook-auto-docs-custom-file.md index 3f6d8f595084..62c9f39694db 100644 --- a/docs/_snippets/storybook-auto-docs-custom-file.md +++ b/docs/_snippets/storybook-auto-docs-custom-file.md @@ -1,12 +1,9 @@ - renderer="common" language="mdx" -```mdx -{/* src/components/Select.mdx */} - +```mdx filename="src/components/Select.mdx" renderer="common" language="mdx" # Select -Select is a type of input that allows users to choose one or more options from a list of choices. +Select is a type of input that allows users to choose one or more options from a list of choices. -The options are hidden by default and revealed when a user interacts with an element. +The options are hidden by default and revealed when a user interacts with an element. It shows the currently selected option in its default collapsed state. @@ -16,11 +13,9 @@ To help users get acquainted with the existing UI elements, it is recommended to ### When to use? -In a select input where there are less than 3-4 items, consider using radio boxes, or radio inputs instead. +In a select input where there are less than 3-4 items, consider using radio boxes, or radio inputs instead. ### How to use? To help users understand the options available in a select input, include a default option that is unselectable and acts as a label. - ``` - diff --git a/docs/_snippets/storybook-auto-docs-full-config.md b/docs/_snippets/storybook-auto-docs-full-config.md index 57c2f6a1537a..1a65731752cd 100644 --- a/docs/_snippets/storybook-auto-docs-full-config.md +++ b/docs/_snippets/storybook-auto-docs-full-config.md @@ -27,4 +27,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-auto-docs-main-mdx-config.md b/docs/_snippets/storybook-auto-docs-main-mdx-config.md index 64f09e55a3c6..2d14f86e3f29 100644 --- a/docs/_snippets/storybook-auto-docs-main-mdx-config.md +++ b/docs/_snippets/storybook-auto-docs-main-mdx-config.md @@ -28,4 +28,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-auto-docs-mdx-docs-docs-only-page.md b/docs/_snippets/storybook-auto-docs-mdx-docs-docs-only-page.md index 771daab8da92..ff0393c83549 100644 --- a/docs/_snippets/storybook-auto-docs-mdx-docs-docs-only-page.md +++ b/docs/_snippets/storybook-auto-docs-mdx-docs-docs-only-page.md @@ -1,6 +1,4 @@ -```mdx renderer="common" language="mdx" -{/* ExampleDocumentation.mdx */} - +```mdx filename="ExampleDocumentation.mdx" renderer="common" language="mdx" import { Meta } from '@storybook/blocks'; import * as ExampleComponentStories from './ExampleComponent.stories'; @@ -11,6 +9,33 @@ import * as ExampleComponentStories from './ExampleComponent.stories'; {/* 👇 Component documentation page */} -<Meta of={ExampleComponentStories} /> +<Meta of={ExampleComponentStories} /> +``` + +```mdx filename="ExampleDocumentation.mdx" renderer="svelte" language="mdx" tabTitle="Svelte CSF" +import { Meta } from '@storybook/blocks'; + +import * as ExampleComponentStories from './ExampleComponent.stories.svelte'; + +{/* 👇 Documentation-only page */} + +<Meta title="Documentation" /> + +{/* 👇 Component documentation page */} + +<Meta of={ExampleComponentStories} /> ``` +```mdx filename="ExampleDocumentation.mdx" renderer="svelte" language="mdx" tabTitle="CSF" +import { Meta } from '@storybook/blocks'; + +import * as ExampleComponentStories from './ExampleComponent.stories'; + +{/* 👇 Documentation-only page */} + +<Meta title="Documentation" /> + +{/* 👇 Component documentation page */} + +<Meta of={ExampleComponentStories} /> +``` diff --git a/docs/_snippets/storybook-auto-docs-mdx-docs-dos-donts.md b/docs/_snippets/storybook-auto-docs-mdx-docs-dos-donts.md index 640fc532e36e..31ace25a7efe 100644 --- a/docs/_snippets/storybook-auto-docs-mdx-docs-dos-donts.md +++ b/docs/_snippets/storybook-auto-docs-mdx-docs-dos-donts.md @@ -1,15 +1,12 @@ -```mdx renderer="common" language="mdx" -{/* Guideline.mdx */} - +```mdx filename="Guideline.mdx" renderer="common" language="mdx" <Guidelines> <Dos> - - Use buttons for the main actions on your page + - Use buttons for the main actions on your page - Identify the primary action and make it `primary` </Dos> <Donts> - - Use a button when a link will do (e.g., for navigation-only actions) + - Use a button when a link will do (e.g., for navigation-only actions) - Use multiple `primary` buttons in a single UI state </Donts> </Guidelines> ``` - diff --git a/docs/_snippets/storybook-auto-docs-mdx-docs-imports.md b/docs/_snippets/storybook-auto-docs-mdx-docs-imports.md index a17d8e36ac69..ad4e03830036 100644 --- a/docs/_snippets/storybook-auto-docs-mdx-docs-imports.md +++ b/docs/_snippets/storybook-auto-docs-mdx-docs-imports.md @@ -1,8 +1,17 @@ -```mdx renderer="common" language="mdx" -{/* Checkbox.mdx */} - +```mdx filename="Checkbox.mdx" renderer="common" language="mdx" import { Canvas, Meta } from '@storybook/blocks'; import * as CheckboxStories from './Checkbox.stories'; ``` +```mdx filename="Checkbox.mdx" renderer="svelte" language="mdx" tabTitle="Svelte CSF" +import { Canvas, Meta } from '@storybook/blocks'; + +import * as CheckboxStories from './Checkbox.stories.svelte'; +``` + +```mdx filename="Checkbox.mdx" renderer="svelte" language="mdx" tabTitle="CSF" +import { Canvas, Meta } from '@storybook/blocks'; + +import * as CheckboxStories from './Checkbox.stories'; +``` diff --git a/docs/_snippets/storybook-auto-docs-mdx-docs-meta-block.md b/docs/_snippets/storybook-auto-docs-mdx-docs-meta-block.md index 10fdbd6282ca..1cefe5dbd78c 100644 --- a/docs/_snippets/storybook-auto-docs-mdx-docs-meta-block.md +++ b/docs/_snippets/storybook-auto-docs-mdx-docs-meta-block.md @@ -1,6 +1,4 @@ -```mdx renderer="common" language="mdx" -{/* Checkbox.mdx */} - +```mdx filename="Checkbox.mdx" renderer="common" language="mdx" import { Meta } from '@storybook/blocks'; import * as CheckboxStories from './Checkbox.stories'; @@ -8,3 +6,18 @@ import * as CheckboxStories from './Checkbox.stories'; <Meta of={CheckboxStories} /> ``` +```mdx filename="Checkbox.mdx" renderer="svelte" language="mdx" tabTitle="Svelte CSF" +import { Meta } from '@storybook/blocks'; + +import * as CheckboxStories from './Checkbox.stories.svelte'; + +<Meta of={CheckboxStories} /> +``` + +```mdx filename="Checkbox.mdx" renderer="svelte" language="mdx" tabTitle="CSF" +import { Meta } from '@storybook/blocks'; + +import * as CheckboxStories from './Checkbox.stories'; + +<Meta of={CheckboxStories} /> +``` diff --git a/docs/_snippets/storybook-auto-docs-mdx-docs-story.md b/docs/_snippets/storybook-auto-docs-mdx-docs-story.md index 9a33596648de..b0d52e9e6506 100644 --- a/docs/_snippets/storybook-auto-docs-mdx-docs-story.md +++ b/docs/_snippets/storybook-auto-docs-mdx-docs-story.md @@ -1,6 +1,4 @@ -```mdx renderer="common" language="mdx" -{/* Checkbox.mdx */} - +```mdx filename="Checkbox.mdx" renderer="common" language="mdx" import { Canvas } from '@storybook/blocks'; import * as CheckboxStories from './Checkbox.stories'; @@ -8,3 +6,18 @@ import * as CheckboxStories from './Checkbox.stories'; <Canvas of={CheckboxStories.Unchecked} /> ``` +```mdx filename="Checkbox.mdx" renderer="svelte" language="mdx" tabTitle="Svelte CSF" +import { Canvas } from '@storybook/blocks'; + +import * as CheckboxStories from './Checkbox.stories.svelte'; + +<Canvas of={CheckboxStories.Unchecked} /> +``` + +```mdx filename="Checkbox.mdx" renderer="svelte" language="mdx" tabTitle="CSF" +import { Canvas } from '@storybook/blocks'; + +import * as CheckboxStories from './Checkbox.stories'; + +<Canvas of={CheckboxStories.Unchecked} /> +``` diff --git a/docs/_snippets/storybook-auto-docs-mdx-file.md b/docs/_snippets/storybook-auto-docs-mdx-file.md index 41e7a6e3f22f..f6d76fd9bf0a 100644 --- a/docs/_snippets/storybook-auto-docs-mdx-file.md +++ b/docs/_snippets/storybook-auto-docs-mdx-file.md @@ -1,6 +1,4 @@ -```mdx renderer="common" language="mdx" -{/* Page.mdx */} - +```mdx filename="Page.mdx" renderer="common" language="mdx" import { Canvas, Meta, Story } from '@storybook/blocks'; import * as ListStories from './List.stories'; @@ -13,7 +11,7 @@ import * as PageStories from './Page.stories'; # Page -Page is a layout container that is used to position children in predetermined areas. +Page is a layout container that is used to position children in predetermined areas. It's often used to apply consistent positioning for content across pages in an application @@ -38,3 +36,78 @@ List items are used to group related content in a list. They must be nested with <Story of={ListItemStories.Starter} meta={ListItemStories} /> ``` +```mdx filename="Page.mdx" renderer="svelte" language="mdx" tabTitle="Svelte CSF" +import { Canvas, Meta, Story } from '@storybook/blocks'; + +import * as ListStories from './List.stories.svelte'; + +import * as ListItemStories from './ListItem.stories.svelte'; + +import * as PageStories from './Page.stories.svelte'; + +<Meta of={PageStories} /> + +# Page + +Page is a layout container that is used to position children in predetermined areas. + +It's often used to apply consistent positioning for content across pages in an application + +## Usage + +<Canvas of={PageStories.Basic} /> + +# List + +List is a grouping of related items. List can be ordered with multiple levels of nesting. + +## Usage + +<Story of={ListStories.Filled} /> + +# List Item + +List items are used to group related content in a list. They must be nested within a List component. + +## Usage + +<Story of={ListItemStories.Starter} meta={ListItemStories} /> +``` + +```mdx filename="Page.mdx" renderer="svelte" language="mdx" tabTitle="CSF" +import { Canvas, Meta, Story } from '@storybook/blocks'; + +import * as ListStories from './List.stories'; + +import * as ListItemStories from './ListItem.stories'; + +import * as PageStories from './Page.stories'; + +<Meta of={PageStories} /> + +# Page + +Page is a layout container that is used to position children in predetermined areas. + +It's often used to apply consistent positioning for content across pages in an application + +## Usage + +<Canvas of={PageStories.Basic} /> + +# List + +List is a grouping of related items. List can be ordered with multiple levels of nesting. + +## Usage + +<Story of={ListStories.Filled} /> + +# List Item + +List items are used to group related content in a list. They must be nested within a List component. + +## Usage + +<Story of={ListItemStories.Starter} meta={ListItemStories} /> +``` diff --git a/docs/_snippets/storybook-auto-docs-standalone-page.md b/docs/_snippets/storybook-auto-docs-standalone-page.md index b1fb8f8bdcc3..353d95aa5092 100644 --- a/docs/_snippets/storybook-auto-docs-standalone-page.md +++ b/docs/_snippets/storybook-auto-docs-standalone-page.md @@ -1,6 +1,4 @@ -```mdx renderer="common" language="mdx" -{/* src/GettingStarted.mdx */} - +```mdx filename="src/GettingStarted.mdx" renderer="common" language="mdx" # Getting Started Welcome! Whether you're a designer or a developer, this guide will help you get started and connect you to the essential resources you need. @@ -8,6 +6,7 @@ Welcome! Whether you're a designer or a developer, this guide will help you get ## Table of Contents - [Design Resources](#design-resources) + - [Figma](#figma) - [UI/UX Design Guidelines](#uiux-design-guidelines) - [Design Assets](#design-assets) @@ -61,4 +60,3 @@ Your development environment is critical. Here are some tools and resources to h --- ``` - diff --git a/docs/_snippets/storybook-auto-docs-starter-example.md b/docs/_snippets/storybook-auto-docs-starter-example.md index d8d8bddf22b0..c24c71600cf7 100644 --- a/docs/_snippets/storybook-auto-docs-starter-example.md +++ b/docs/_snippets/storybook-auto-docs-starter-example.md @@ -1,6 +1,4 @@ -```mdx renderer="common" language="mdx" -{/* Button.mdx */} - +```mdx filename="Button.mdx" renderer="common" language="mdx" import { Meta, Story } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; @@ -20,3 +18,42 @@ Buttons are often used for form submissions and to toggle elements into view. <Story of={ButtonStories.Basic} /> ``` +```mdx filename="Button.mdx" renderer="svelte" language="mdx" tabTitle="Svelte CSF" +import { Meta, Story } from '@storybook/blocks'; + +import * as ButtonStories from './Button.stories.svelte'; + +<Meta of={ButtonStories} /> + +# Button + +Button is a clickable interactive element that triggers a response. + +You can place text and icons inside of a button. + +Buttons are often used for form submissions and to toggle elements into view. + +## Usage + +<Story of={ButtonStories.Basic} /> +``` + +```mdx filename="Button.mdx" renderer="svelte" language="mdx" tabTitle="CSF" +import { Meta, Story } from '@storybook/blocks'; + +import * as ButtonStories from './Button.stories'; + +<Meta of={ButtonStories} /> + +# Button + +Button is a clickable interactive element that triggers a response. + +You can place text and icons inside of a button. + +Buttons are often used for form submissions and to toggle elements into view. + +## Usage + +<Story of={ButtonStories.Basic} /> +``` diff --git a/docs/_snippets/storybook-automigrate.md b/docs/_snippets/storybook-automigrate.md index 1f666ddd55a8..1757c0b23406 100644 --- a/docs/_snippets/storybook-automigrate.md +++ b/docs/_snippets/storybook-automigrate.md @@ -9,4 +9,3 @@ pnpm dlx storybook@latest automigrate ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@latest automigrate ``` - diff --git a/docs/_snippets/storybook-babel-configuration-example.md b/docs/_snippets/storybook-babel-configuration-example.md index f2387da7de7d..411b2313e86d 100644 --- a/docs/_snippets/storybook-babel-configuration-example.md +++ b/docs/_snippets/storybook-babel-configuration-example.md @@ -7,4 +7,3 @@ export function babelDefault(config: TransformOptions) { }; } ``` - diff --git a/docs/_snippets/storybook-backgrounds-addon-default-params.md b/docs/_snippets/storybook-backgrounds-addon-default-params.md index 27e5e756d1c5..74d28417e073 100644 --- a/docs/_snippets/storybook-backgrounds-addon-default-params.md +++ b/docs/_snippets/storybook-backgrounds-addon-default-params.md @@ -10,4 +10,3 @@ export default { }, }; ``` - diff --git a/docs/_snippets/storybook-backgrounds-preset-config.md b/docs/_snippets/storybook-backgrounds-preset-config.md index 9dc431a89c0f..0f519253b03a 100644 --- a/docs/_snippets/storybook-backgrounds-preset-config.md +++ b/docs/_snippets/storybook-backgrounds-preset-config.md @@ -3,4 +3,3 @@ export function config(entry = []) { return [...entry, require.resolve('./defaultParameters')]; } ``` - diff --git a/docs/_snippets/storybook-build-test-flag.md b/docs/_snippets/storybook-build-test-flag.md index 52eaf29d1762..98c9d4ddba15 100644 --- a/docs/_snippets/storybook-build-test-flag.md +++ b/docs/_snippets/storybook-build-test-flag.md @@ -9,4 +9,3 @@ pnpm run build-storybook --test ```shell renderer="common" language="js" packageManager="yarn" yarn build-storybook --test ``` - diff --git a/docs/_snippets/storybook-builder-api-build-server.md b/docs/_snippets/storybook-builder-api-build-server.md index a8afc23b050f..2cf99eb3ddbf 100644 --- a/docs/_snippets/storybook-builder-api-build-server.md +++ b/docs/_snippets/storybook-builder-api-build-server.md @@ -32,4 +32,3 @@ export async function build(options: ExtendedOptions) { await viteBuild(finalConfig); } ``` - diff --git a/docs/_snippets/storybook-builder-api-configuration-options.md b/docs/_snippets/storybook-builder-api-configuration-options.md index 3b9ff0cf4cb0..83f9692e9278 100644 --- a/docs/_snippets/storybook-builder-api-configuration-options.md +++ b/docs/_snippets/storybook-builder-api-configuration-options.md @@ -32,4 +32,3 @@ export async function createViteServer(options: ExtendedOptions, devServer: Serv // Remainder implementation } ``` - diff --git a/docs/_snippets/storybook-builder-api-dev-server.md b/docs/_snippets/storybook-builder-api-dev-server.md index 0c7799f1a1dc..41dd09d2ef27 100644 --- a/docs/_snippets/storybook-builder-api-dev-server.md +++ b/docs/_snippets/storybook-builder-api-dev-server.md @@ -18,4 +18,3 @@ export async function createViteServer(options: ExtendedOptions, devServer: Serv }); } ``` - diff --git a/docs/_snippets/storybook-builder-api-interface.md b/docs/_snippets/storybook-builder-api-interface.md index 42bcabc41f1b..69988858c26f 100644 --- a/docs/_snippets/storybook-builder-api-interface.md +++ b/docs/_snippets/storybook-builder-api-interface.md @@ -20,4 +20,3 @@ export interface Builder<Config, Stats> { overridePresets?: string[]; } ``` - diff --git a/docs/_snippets/storybook-builder-api-mdx.md b/docs/_snippets/storybook-builder-api-mdx.md index 020ea42166ae..8475d18f736f 100644 --- a/docs/_snippets/storybook-builder-api-mdx.md +++ b/docs/_snippets/storybook-builder-api-mdx.md @@ -16,4 +16,3 @@ export function mdxPlugin() { }); } ``` - diff --git a/docs/_snippets/storybook-builder-api-preview-exports.md b/docs/_snippets/storybook-builder-api-preview-exports.md index e6091e618d7b..3eefea3c09f3 100644 --- a/docs/_snippets/storybook-builder-api-preview-exports.md +++ b/docs/_snippets/storybook-builder-api-preview-exports.md @@ -78,4 +78,3 @@ export async function generateIframeScriptCode(options: ExtendedOptions) { return code; } ``` - diff --git a/docs/_snippets/storybook-builder-api-shutdown-server.md b/docs/_snippets/storybook-builder-api-shutdown-server.md index 310e41eb7ccc..c642a9c6fc01 100644 --- a/docs/_snippets/storybook-builder-api-shutdown-server.md +++ b/docs/_snippets/storybook-builder-api-shutdown-server.md @@ -16,4 +16,3 @@ export const start: ViteBuilder['start'] = async ({ options, server: devServer } }; }; ``` - diff --git a/docs/_snippets/storybook-canvas-doc-block-story.md b/docs/_snippets/storybook-canvas-doc-block-story.md index 07619d9f0fb7..ada5f64f9fa9 100644 --- a/docs/_snippets/storybook-canvas-doc-block-story.md +++ b/docs/_snippets/storybook-canvas-doc-block-story.md @@ -162,4 +162,3 @@ export const Colors: Story = { ), }; ``` - diff --git a/docs/_snippets/storybook-client-globals-example-file.md b/docs/_snippets/storybook-client-globals-example-file.md index fb76daa7d184..49ffd3c3bd50 100644 --- a/docs/_snippets/storybook-client-globals-example-file.md +++ b/docs/_snippets/storybook-client-globals-example-file.md @@ -5,4 +5,3 @@ const { window: globalWindow } = global; globalWindow.STORYBOOK_ENV = 'vue'; ``` - diff --git a/docs/_snippets/storybook-client-preview.md b/docs/_snippets/storybook-client-preview.md index 9602d622aa01..98f2d64ebb47 100644 --- a/docs/_snippets/storybook-client-preview.md +++ b/docs/_snippets/storybook-client-preview.md @@ -9,4 +9,3 @@ const api = start(render); // the boilerplate code ``` - diff --git a/docs/_snippets/storybook-component-layout-param.md b/docs/_snippets/storybook-component-layout-param.md index 56afcb84e22e..c24d0d683281 100644 --- a/docs/_snippets/storybook-component-layout-param.md +++ b/docs/_snippets/storybook-component-layout-param.md @@ -81,4 +81,3 @@ const meta: Meta = { export default meta; ``` - diff --git a/docs/_snippets/storybook-config-layout.md b/docs/_snippets/storybook-config-layout.md index 413a57d07576..59b5ac968c87 100644 --- a/docs/_snippets/storybook-config-layout.md +++ b/docs/_snippets/storybook-config-layout.md @@ -24,4 +24,3 @@ addons.setConfig({ }, }); ``` - diff --git a/docs/_snippets/storybook-coverage-addon-config-options.md b/docs/_snippets/storybook-coverage-addon-config-options.md index 92890cfb44a0..6bbb3b9b551c 100644 --- a/docs/_snippets/storybook-coverage-addon-config-options.md +++ b/docs/_snippets/storybook-coverage-addon-config-options.md @@ -45,4 +45,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-coverage-addon-install.md b/docs/_snippets/storybook-coverage-addon-install.md index 04b1a4b263c7..38d085bdcdc6 100644 --- a/docs/_snippets/storybook-coverage-addon-install.md +++ b/docs/_snippets/storybook-coverage-addon-install.md @@ -1,12 +1,11 @@ ```shell renderer="common" language="js" packageManager="npm" -npm install @storybook/addon-coverage --save-dev +npx storybook@latest add @storybook/addon-coverage ``` ```shell renderer="common" language="js" packageManager="pnpm" -pnpm add --save-dev @storybook/addon-coverage +pnpm dlx storybook@latest add @storybook/addon-coverage ``` ```shell renderer="common" language="js" packageManager="yarn" -yarn add --dev @storybook/addon-coverage +yarn dlx storybook@latest add @storybook/addon-coverage ``` - diff --git a/docs/_snippets/storybook-coverage-addon-registration.md b/docs/_snippets/storybook-coverage-addon-registration.md deleted file mode 100644 index d775e1a7b229..000000000000 --- a/docs/_snippets/storybook-coverage-addon-registration.md +++ /dev/null @@ -1,25 +0,0 @@ -```js filename=".storybook/main.js" renderer="common" language="js" -export default { - stories: [], - addons: [ - // Other Storybook addons - '@storybook/addon-coverage', //👈 Registers the addon - ], -}; -``` - -```ts filename=".storybook/main.ts" renderer="common" language="ts" -// Replace your-framework with the framework and builder you are using (e.g., react-webpack5, vue3-webpack5) -import type { StorybookConfig } from '@storybook/your-framework'; - -const config: StorybookConfig = { - stories: [], - addons: [ - // Other Storybook addons - '@storybook/addon-coverage', //👈 Registers the addon - ], -}; - -export default config; -``` - diff --git a/docs/_snippets/storybook-coverage-report-lcov.md b/docs/_snippets/storybook-coverage-report-lcov.md index 338131fa9c66..72f9699d5316 100644 --- a/docs/_snippets/storybook-coverage-report-lcov.md +++ b/docs/_snippets/storybook-coverage-report-lcov.md @@ -1,4 +1,3 @@ ```shell renderer="common" language="js" npx nyc report --reporter=lcov -t coverage/storybook --report-dir coverage/storybook ``` - diff --git a/docs/_snippets/storybook-coverage-report-vue.md b/docs/_snippets/storybook-coverage-report-vue.md index 037434637162..276690bac0eb 100644 --- a/docs/_snippets/storybook-coverage-report-vue.md +++ b/docs/_snippets/storybook-coverage-report-vue.md @@ -1,13 +1,12 @@ -```js filename=".nyc.config.js" renderer="common" language="js" +```js filename=".nyc.config.js" renderer="common" language="js" tabTitle="JavaScript configuration" export default { // Other configuration options extension: ['.js', '.cjs', '.mjs', '.ts', '.tsx', '.jsx', '.vue'], }; ``` -```json renderer="common" language="json" +```json filename=".nycrc.json" renderer="common" language="json" tabTitle="JSON configuration" { "extension": [".js", ".cjs", ".mjs", ".ts", ".tsx", ".jsx", ".vue"] } ``` - diff --git a/docs/_snippets/storybook-csf-3-auto-title-redundant.md b/docs/_snippets/storybook-csf-3-auto-title-redundant.md index ee593ca87dc0..557977ef1af6 100644 --- a/docs/_snippets/storybook-csf-3-auto-title-redundant.md +++ b/docs/_snippets/storybook-csf-3-auto-title-redundant.md @@ -117,4 +117,3 @@ export const Default: Story = { }, }; ``` - diff --git a/docs/_snippets/storybook-custom-docs-markdown.md b/docs/_snippets/storybook-custom-docs-markdown.md index fc666e9b2b65..933ffd344d2e 100644 --- a/docs/_snippets/storybook-custom-docs-markdown.md +++ b/docs/_snippets/storybook-custom-docs-markdown.md @@ -1,9 +1,7 @@ -```mdx renderer="common" language="mdx" -{/* Changelog.mdx */} +```mdx filename="Changelog.mdx" renderer="common" language="mdx" +import { Meta, Markdown } from '@storybook/blocks'; -import { Meta, Markdown } from "@storybook/blocks"; - -import Readme from "../../Changelog.md?raw"; +import Readme from '../../Changelog.md?raw'; <Meta title="Changelog" /> @@ -11,4 +9,3 @@ import Readme from "../../Changelog.md?raw"; <Markdown>{Readme}</Markdown> ``` - diff --git a/docs/_snippets/storybook-custom-manager-head.md b/docs/_snippets/storybook-custom-manager-head.md index 81364cd10cb3..46c400359df9 100644 --- a/docs/_snippets/storybook-custom-manager-head.md +++ b/docs/_snippets/storybook-custom-manager-head.md @@ -20,4 +20,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-debug-webpack-dev.md b/docs/_snippets/storybook-debug-webpack-dev.md index 1f7c0ace4f93..21009cff84c0 100644 --- a/docs/_snippets/storybook-debug-webpack-dev.md +++ b/docs/_snippets/storybook-debug-webpack-dev.md @@ -5,4 +5,3 @@ npm run storybook -- --debug-webpack ```shell renderer="common" language="js" packageManager="yarn" yarn storybook --debug-webpack ``` - diff --git a/docs/_snippets/storybook-debug-webpack-prod.md b/docs/_snippets/storybook-debug-webpack-prod.md index 4c181925d55c..151420844f2d 100644 --- a/docs/_snippets/storybook-debug-webpack-prod.md +++ b/docs/_snippets/storybook-debug-webpack-prod.md @@ -5,4 +5,3 @@ npm run build-storybook -- --debug-webpack ```shell renderer="common" language="js" packageManager="yarn" yarn build-storybook --debug-webpack ``` - diff --git a/docs/_snippets/storybook-disable-telemetry-env.md b/docs/_snippets/storybook-disable-telemetry-env.md index c9cceef0212c..a6b2a0a94a45 100644 --- a/docs/_snippets/storybook-disable-telemetry-env.md +++ b/docs/_snippets/storybook-disable-telemetry-env.md @@ -1,4 +1,3 @@ -```shell renderer="common" language="js" tabTitle="env-var" +```shell renderer="common" language="js" STORYBOOK_DISABLE_TELEMETRY=1 yarn storybook ``` - diff --git a/docs/_snippets/storybook-disable-telemetry-flag.md b/docs/_snippets/storybook-disable-telemetry-flag.md index 53b5af66bc8d..00626b39e6ad 100644 --- a/docs/_snippets/storybook-disable-telemetry-flag.md +++ b/docs/_snippets/storybook-disable-telemetry-flag.md @@ -9,4 +9,3 @@ pnpm run storybook --disable-telemetry ```shell renderer="common" language="js" packageManager="yarn" yarn storybook --disable-telemetry ``` - diff --git a/docs/_snippets/storybook-doctor.md b/docs/_snippets/storybook-doctor.md index 55550037ce75..a17f1d873466 100644 --- a/docs/_snippets/storybook-doctor.md +++ b/docs/_snippets/storybook-doctor.md @@ -9,4 +9,3 @@ pnpm dlx storybook@latest doctor ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@latest doctor ``` - diff --git a/docs/_snippets/storybook-ember-cli-build.md b/docs/_snippets/storybook-ember-cli-build.md index 4e46b197d13c..468daf86cb91 100644 --- a/docs/_snippets/storybook-ember-cli-build.md +++ b/docs/_snippets/storybook-ember-cli-build.md @@ -13,4 +13,3 @@ module.exports = function (defaults) { return app.toTree(); }; ``` - diff --git a/docs/_snippets/storybook-extract-specific-version.md b/docs/_snippets/storybook-extract-specific-version.md index ba8fd3fa0323..82bdb0189c5b 100644 --- a/docs/_snippets/storybook-extract-specific-version.md +++ b/docs/_snippets/storybook-extract-specific-version.md @@ -1,4 +1,4 @@ -```shell renderer="common" language="js" packageManager="npx" +```shell renderer="common" language="js" packageManager="npm" npx storybook@7.5.3 extract ``` @@ -9,4 +9,3 @@ pnpm dlx storybook@7.5.3 extract ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@7.5.3 extract ``` - diff --git a/docs/_snippets/storybook-figma-addon-install.md b/docs/_snippets/storybook-figma-addon-install.md index 1d547af33fd1..aa21ff5491a6 100644 --- a/docs/_snippets/storybook-figma-addon-install.md +++ b/docs/_snippets/storybook-figma-addon-install.md @@ -1,12 +1,11 @@ ```shell renderer="common" language="js" packageManager="npm" -npm install --save-dev @storybook/addon-designs +npx storybook@latest add @storybook/addon-designs ``` ```shell renderer="common" language="js" packageManager="pnpm" -pnpm add --save-dev @storybook/addon-designs +pnpm dlx storybook@latest add @storybook/addon-designs ``` ```shell renderer="common" language="js" packageManager="yarn" -yarn add --dev @storybook/addon-designs +yarn dlx storybook@latest add @storybook/addon-designs ``` - diff --git a/docs/_snippets/storybook-fix-imports-autodocs-monorepo.md b/docs/_snippets/storybook-fix-imports-autodocs-monorepo.md index e64d33a957c5..8a1cef5486ed 100644 --- a/docs/_snippets/storybook-fix-imports-autodocs-monorepo.md +++ b/docs/_snippets/storybook-fix-imports-autodocs-monorepo.md @@ -58,4 +58,3 @@ const meta: Meta<typeof MyComponent> = { export default meta; ``` - diff --git a/docs/_snippets/storybook-framework-render-function.md b/docs/_snippets/storybook-framework-render-function.md index 79dd68a4cae7..814368a6e2fa 100644 --- a/docs/_snippets/storybook-framework-render-function.md +++ b/docs/_snippets/storybook-framework-render-function.md @@ -7,4 +7,3 @@ export default function renderMain({ storyFn }: RenderMainArgs) { rootElement.innerHTML = html; } ``` - diff --git a/docs/_snippets/storybook-generated-argtypes.md b/docs/_snippets/storybook-generated-argtypes.md index 1f28e69a13e1..3250ac217846 100644 --- a/docs/_snippets/storybook-generated-argtypes.md +++ b/docs/_snippets/storybook-generated-argtypes.md @@ -15,4 +15,3 @@ const argTypes = { }, }; ``` - diff --git a/docs/_snippets/storybook-init-v7.md b/docs/_snippets/storybook-init-v7.md index e74bfce11ce4..3966bc1efaf5 100644 --- a/docs/_snippets/storybook-init-v7.md +++ b/docs/_snippets/storybook-init-v7.md @@ -1,4 +1,4 @@ -```shell renderer="common" language="js" packageManager="npx" +```shell renderer="common" language="js" packageManager="npm" npx storybook@^7 init ``` @@ -9,4 +9,3 @@ pnpm dlx storybook@^7 init ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@^7 init ``` - diff --git a/docs/_snippets/storybook-interactions-addon-registration.md b/docs/_snippets/storybook-interactions-addon-registration.md index c56c6e8a7154..dae3fa856fe8 100644 --- a/docs/_snippets/storybook-interactions-addon-registration.md +++ b/docs/_snippets/storybook-interactions-addon-registration.md @@ -25,4 +25,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-interactions-play-function.md b/docs/_snippets/storybook-interactions-play-function.md index fcc0c3bb20cb..adb5900352b1 100644 --- a/docs/_snippets/storybook-interactions-play-function.md +++ b/docs/_snippets/storybook-interactions-play-function.md @@ -232,4 +232,3 @@ export const Submitted: Story = { }, }; ``` - diff --git a/docs/_snippets/storybook-interactions-step-function.md b/docs/_snippets/storybook-interactions-step-function.md index 96d5c8847162..1283c93bdcf5 100644 --- a/docs/_snippets/storybook-interactions-step-function.md +++ b/docs/_snippets/storybook-interactions-step-function.md @@ -190,4 +190,3 @@ export const Submitted: Story = { }, }; ``` - diff --git a/docs/_snippets/storybook-main-advanced-config-example.md b/docs/_snippets/storybook-main-advanced-config-example.md index 65752e8ff26c..b09dfe148cf3 100644 --- a/docs/_snippets/storybook-main-advanced-config-example.md +++ b/docs/_snippets/storybook-main-advanced-config-example.md @@ -34,4 +34,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-auto-title-custom.md b/docs/_snippets/storybook-main-auto-title-custom.md index 9abaa4459c30..ee1abb62d8b2 100644 --- a/docs/_snippets/storybook-main-auto-title-custom.md +++ b/docs/_snippets/storybook-main-auto-title-custom.md @@ -27,4 +27,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-config-remark-options.md b/docs/_snippets/storybook-main-config-remark-options.md index e8fc5c45d007..2126d1c26c2c 100644 --- a/docs/_snippets/storybook-main-config-remark-options.md +++ b/docs/_snippets/storybook-main-config-remark-options.md @@ -47,4 +47,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-configuration-src-dir.md b/docs/_snippets/storybook-main-configuration-src-dir.md index 591ac0188c2f..ecc36c851e55 100644 --- a/docs/_snippets/storybook-main-configuration-src-dir.md +++ b/docs/_snippets/storybook-main-configuration-src-dir.md @@ -1,4 +1,4 @@ -```js filename="./storybook/main.js" renderer="common" language="js" tabTitle="main-js" +```js filename="./storybook/main.js" renderer="common" language="js" export default { // Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) framework: '@storybook/your-framework', @@ -6,7 +6,7 @@ export default { }; ``` -```ts filename=".storybook/main.ts" renderer="common" language="ts" tabTitle="main-ts" +```ts filename=".storybook/main.ts" renderer="common" language="ts" // Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) import type { StorybookConfig } from '@storybook/your-framework'; @@ -17,4 +17,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-disable-addon.md b/docs/_snippets/storybook-main-disable-addon.md index 725234295c06..ddf6350af496 100644 --- a/docs/_snippets/storybook-main-disable-addon.md +++ b/docs/_snippets/storybook-main-disable-addon.md @@ -33,4 +33,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-disable-telemetry.md b/docs/_snippets/storybook-main-disable-telemetry.md index da402967d828..fd28e548ce3c 100644 --- a/docs/_snippets/storybook-main-disable-telemetry.md +++ b/docs/_snippets/storybook-main-disable-telemetry.md @@ -1,4 +1,4 @@ -```js filename=".storybook/main.js" renderer="common" language="js" tabTitle="main-js" +```js filename=".storybook/main.js" renderer="common" language="js" export default { // Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) framework: '@storybook/your-framework', @@ -9,7 +9,7 @@ export default { }; ``` -```ts filename=".storybook/main.ts" renderer="common" language="ts" tabTitle="main-ts" +```ts filename=".storybook/main.ts" renderer="common" language="ts" // Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) import type { StorybookConfig } from '@storybook/your-framework'; @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-extend-ts-config.md b/docs/_snippets/storybook-main-extend-ts-config.md index efb9579b81b0..e8548fe59bfe 100644 --- a/docs/_snippets/storybook-main-extend-ts-config.md +++ b/docs/_snippets/storybook-main-extend-ts-config.md @@ -33,4 +33,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-figma-addon-register.md b/docs/_snippets/storybook-main-figma-addon-register.md deleted file mode 100644 index bd02a21c1cb5..000000000000 --- a/docs/_snippets/storybook-main-figma-addon-register.md +++ /dev/null @@ -1,26 +0,0 @@ -```js filename=".storybook/main.js" renderer="common" language="js" -export default { - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], - addons: [ - // Other Storybook addons - '@storybook/addon-designs', // 👈 Addon is registered here - ], -}; -``` - -```ts filename=".storybook/main.ts" renderer="common" language="ts" -// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) -import type { StorybookConfig } from '@storybook/your-framework'; - -const config: StorybookConfig = { - framework: '@storybook/your-framework', - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], - addons: [ - // Other Storybook addons - '@storybook/addon-designs', // 👈 Addon is registered here - ], -}; - -export default config; -``` - diff --git a/docs/_snippets/storybook-main-fix-imports-autodocs-monorepo.md b/docs/_snippets/storybook-main-fix-imports-autodocs-monorepo.md index 25e273b4af49..fe3e0f978416 100644 --- a/docs/_snippets/storybook-main-fix-imports-autodocs-monorepo.md +++ b/docs/_snippets/storybook-main-fix-imports-autodocs-monorepo.md @@ -27,4 +27,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-full-individual-essentials-config.md b/docs/_snippets/storybook-main-full-individual-essentials-config.md index 93e1c35cd744..85e0e4612767 100644 --- a/docs/_snippets/storybook-main-full-individual-essentials-config.md +++ b/docs/_snippets/storybook-main-full-individual-essentials-config.md @@ -59,4 +59,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-js-md-files.md b/docs/_snippets/storybook-main-js-md-files.md index 161d7f303ff3..96ec0d8622ac 100644 --- a/docs/_snippets/storybook-main-js-md-files.md +++ b/docs/_snippets/storybook-main-js-md-files.md @@ -17,4 +17,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-pnpm-with-module-resolution.md b/docs/_snippets/storybook-main-pnpm-with-module-resolution.md index 4be87978a4f7..f022bd2f611b 100644 --- a/docs/_snippets/storybook-main-pnpm-with-module-resolution.md +++ b/docs/_snippets/storybook-main-pnpm-with-module-resolution.md @@ -42,4 +42,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-preview-head.md b/docs/_snippets/storybook-main-preview-head.md index a7a8ee7bd1dd..30beffbf60b7 100644 --- a/docs/_snippets/storybook-main-preview-head.md +++ b/docs/_snippets/storybook-main-preview-head.md @@ -10,4 +10,3 @@ export default { `); }; ``` - diff --git a/docs/_snippets/storybook-main-prop-filter.md b/docs/_snippets/storybook-main-prop-filter.md index 359b951ce491..bdb28d02e8bd 100644 --- a/docs/_snippets/storybook-main-prop-filter.md +++ b/docs/_snippets/storybook-main-prop-filter.md @@ -21,4 +21,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-react-docgen-typescript.md b/docs/_snippets/storybook-main-react-docgen-typescript.md index 727b5c8a7cdb..71f562f3fe1a 100644 --- a/docs/_snippets/storybook-main-react-docgen-typescript.md +++ b/docs/_snippets/storybook-main-react-docgen-typescript.md @@ -15,4 +15,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-ref-local.md b/docs/_snippets/storybook-main-ref-local.md index cf7f06c1529c..7cdea926c5ed 100644 --- a/docs/_snippets/storybook-main-ref-local.md +++ b/docs/_snippets/storybook-main-ref-local.md @@ -37,4 +37,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-register-addon.md b/docs/_snippets/storybook-main-register-addon.md index ab10b1976599..166793a4632b 100644 --- a/docs/_snippets/storybook-main-register-addon.md +++ b/docs/_snippets/storybook-main-register-addon.md @@ -3,4 +3,3 @@ export default { addons: ['path/to/manager.js'], }; ``` - diff --git a/docs/_snippets/storybook-main-register-essentials-addon.md b/docs/_snippets/storybook-main-register-essentials-addon.md index 59f397a9dd5d..a12e9e58c48f 100644 --- a/docs/_snippets/storybook-main-register-essentials-addon.md +++ b/docs/_snippets/storybook-main-register-essentials-addon.md @@ -18,4 +18,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-register-example-addon.md b/docs/_snippets/storybook-main-register-example-addon.md index 024dd6b7e5fa..ac59dd73e354 100644 --- a/docs/_snippets/storybook-main-register-example-addon.md +++ b/docs/_snippets/storybook-main-register-example-addon.md @@ -20,4 +20,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-register-individual-actions-addon.md b/docs/_snippets/storybook-main-register-individual-actions-addon.md index 45cb5261b754..248a85c4afb9 100644 --- a/docs/_snippets/storybook-main-register-individual-actions-addon.md +++ b/docs/_snippets/storybook-main-register-individual-actions-addon.md @@ -19,4 +19,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-register-presets-managerentry.md b/docs/_snippets/storybook-main-register-presets-managerentry.md index fca4f44e6419..4aa96883322d 100644 --- a/docs/_snippets/storybook-main-register-presets-managerentry.md +++ b/docs/_snippets/storybook-main-register-presets-managerentry.md @@ -5,4 +5,3 @@ export default { ], }; ``` - diff --git a/docs/_snippets/storybook-main-simplified-config.md b/docs/_snippets/storybook-main-simplified-config.md index b1f9a6a5872e..c324634836c8 100644 --- a/docs/_snippets/storybook-main-simplified-config.md +++ b/docs/_snippets/storybook-main-simplified-config.md @@ -25,4 +25,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-ts-module-resolution-atsign-import.md b/docs/_snippets/storybook-main-ts-module-resolution-atsign-import.md index ac281eb91a65..6149c57438be 100644 --- a/docs/_snippets/storybook-main-ts-module-resolution-atsign-import.md +++ b/docs/_snippets/storybook-main-ts-module-resolution-atsign-import.md @@ -38,4 +38,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-ts-module-resolution.md b/docs/_snippets/storybook-main-ts-module-resolution.md index 3473115ae6e2..c6932f0cc9be 100644 --- a/docs/_snippets/storybook-main-ts-module-resolution.md +++ b/docs/_snippets/storybook-main-ts-module-resolution.md @@ -43,4 +43,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-use-manager-entries.md b/docs/_snippets/storybook-main-use-manager-entries.md index f3686ea18d51..9f70558000bd 100644 --- a/docs/_snippets/storybook-main-use-manager-entries.md +++ b/docs/_snippets/storybook-main-use-manager-entries.md @@ -3,4 +3,3 @@ export default { managerEntries: ['some-storybook-addon/entry-point.js'], }; ``` - diff --git a/docs/_snippets/storybook-main-using-existing-config.md b/docs/_snippets/storybook-main-using-existing-config.md index 5c36cbf42766..e7c60a8f8b20 100644 --- a/docs/_snippets/storybook-main-using-existing-config.md +++ b/docs/_snippets/storybook-main-using-existing-config.md @@ -33,4 +33,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-versioned-webpack.md b/docs/_snippets/storybook-main-versioned-webpack.md index eab56d99cf4a..f4b00f27abf8 100644 --- a/docs/_snippets/storybook-main-versioned-webpack.md +++ b/docs/_snippets/storybook-main-versioned-webpack.md @@ -7,4 +7,3 @@ export function webpackFinal(config, { presets }) { return config; } ``` - diff --git a/docs/_snippets/storybook-main-webpack-options.md b/docs/_snippets/storybook-main-webpack-options.md index 07adfc8fa696..bbb9728f62ff 100644 --- a/docs/_snippets/storybook-main-webpack-options.md +++ b/docs/_snippets/storybook-main-webpack-options.md @@ -35,4 +35,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-main-webpack-preset-config.md b/docs/_snippets/storybook-main-webpack-preset-config.md index bf5e1656c94e..1967202f9119 100644 --- a/docs/_snippets/storybook-main-webpack-preset-config.md +++ b/docs/_snippets/storybook-main-webpack-preset-config.md @@ -19,4 +19,3 @@ export async function webpack(baseConfig, options) { }; } ``` - diff --git a/docs/_snippets/storybook-main-webpack5-fsCache.md b/docs/_snippets/storybook-main-webpack5-fsCache.md index ccb14a9cdddc..9ca18b587cf7 100644 --- a/docs/_snippets/storybook-main-webpack5-fsCache.md +++ b/docs/_snippets/storybook-main-webpack5-fsCache.md @@ -10,4 +10,3 @@ export default { }, }; ``` - diff --git a/docs/_snippets/storybook-main-webpack5-lazyCompilation.md b/docs/_snippets/storybook-main-webpack5-lazyCompilation.md index 7e95269a8e27..182c2187fd9c 100644 --- a/docs/_snippets/storybook-main-webpack5-lazyCompilation.md +++ b/docs/_snippets/storybook-main-webpack5-lazyCompilation.md @@ -10,4 +10,3 @@ export default { }, }; ``` - diff --git a/docs/_snippets/storybook-main-webpack5.md b/docs/_snippets/storybook-main-webpack5.md index 8103e08a0ca5..f5e399b77ef4 100644 --- a/docs/_snippets/storybook-main-webpack5.md +++ b/docs/_snippets/storybook-main-webpack5.md @@ -5,4 +5,3 @@ export default { }, }; ``` - diff --git a/docs/_snippets/storybook-main-webpackfinal-example.md b/docs/_snippets/storybook-main-webpackfinal-example.md index a1c504de8932..5ec6c4b7646e 100644 --- a/docs/_snippets/storybook-main-webpackfinal-example.md +++ b/docs/_snippets/storybook-main-webpackfinal-example.md @@ -9,4 +9,3 @@ export function webpackFinal(config, { configDir }) { return applyCRAWebpackConfig(config, configDir); } ``` - diff --git a/docs/_snippets/storybook-manager-custom-theme.md b/docs/_snippets/storybook-manager-custom-theme.md index 6a592e294fe2..c8f06b738d16 100644 --- a/docs/_snippets/storybook-manager-custom-theme.md +++ b/docs/_snippets/storybook-manager-custom-theme.md @@ -6,4 +6,3 @@ addons.setConfig({ theme: yourTheme, }); ``` - diff --git a/docs/_snippets/storybook-manager-dark-theme.md b/docs/_snippets/storybook-manager-dark-theme.md index 04ffcbf1f6d9..399c33fd37b7 100644 --- a/docs/_snippets/storybook-manager-dark-theme.md +++ b/docs/_snippets/storybook-manager-dark-theme.md @@ -6,4 +6,3 @@ addons.setConfig({ theme: themes.dark, }); ``` - diff --git a/docs/_snippets/storybook-manager-disable-roots.md b/docs/_snippets/storybook-manager-disable-roots.md index f2bcba560e30..a6bf68ed0ff3 100644 --- a/docs/_snippets/storybook-manager-disable-roots.md +++ b/docs/_snippets/storybook-manager-disable-roots.md @@ -7,4 +7,3 @@ addons.setConfig({ }, }); ``` - diff --git a/docs/_snippets/storybook-manager-render-label-stories.md b/docs/_snippets/storybook-manager-render-label-stories.md index 621b2c863d5d..98a988631941 100644 --- a/docs/_snippets/storybook-manager-render-label-stories.md +++ b/docs/_snippets/storybook-manager-render-label-stories.md @@ -9,4 +9,3 @@ addons.setConfig({ }, }); ``` - diff --git a/docs/_snippets/storybook-mdx-template-with-prop.md b/docs/_snippets/storybook-mdx-template-with-prop.md index 340277699165..83533422aa56 100644 --- a/docs/_snippets/storybook-mdx-template-with-prop.md +++ b/docs/_snippets/storybook-mdx-template-with-prop.md @@ -1,9 +1,7 @@ -```mdx renderer="common" language="mdx" -{/* DocumentationTemplate.mdx */} - +```mdx filename="DocumentationTemplate.mdx" renderer="common" language="mdx" import { Meta, Title, Primary, Controls, Stories } from '@storybook/blocks'; -{/* +{/* * 👇 The isTemplate property is required to tell Storybook that this is a template * See https://storybook.js.org/docs/api/doc-blocks/doc-block-meta * to learn how to use @@ -32,4 +30,3 @@ Listed below are additional variations of the component. <Stories /> ``` - diff --git a/docs/_snippets/storybook-merged-argtypes.md b/docs/_snippets/storybook-merged-argtypes.md index bc6a0660d079..e3a13a0a5392 100644 --- a/docs/_snippets/storybook-merged-argtypes.md +++ b/docs/_snippets/storybook-merged-argtypes.md @@ -18,4 +18,3 @@ const argTypes = { }, }; ``` - diff --git a/docs/_snippets/storybook-migrate-csf-2-to-3.md b/docs/_snippets/storybook-migrate-csf-2-to-3.md index cf4e292d874a..502aa31d6b2d 100644 --- a/docs/_snippets/storybook-migrate-csf-2-to-3.md +++ b/docs/_snippets/storybook-migrate-csf-2-to-3.md @@ -12,4 +12,3 @@ pnpm dlx storybook@latest migrate csf-2-to-3 --glob="**/*.stories.tsx" --parser= # Convert CSF 2 to CSF 3 yarn dlx storybook@latest migrate csf-2-to-3 --glob="**/*.stories.tsx" --parser=tsx ``` - diff --git a/docs/_snippets/storybook-migrate-mdx-to-csf.md b/docs/_snippets/storybook-migrate-mdx-to-csf.md index 48ed3b60de91..daa7baf83b0d 100644 --- a/docs/_snippets/storybook-migrate-mdx-to-csf.md +++ b/docs/_snippets/storybook-migrate-mdx-to-csf.md @@ -12,4 +12,3 @@ pnpm dlx storybook@latest migrate mdx-to-csf --glob "src/**/*.stories.mdx" # Convert stories in MDX to CSF yarn dlx storybook@latest migrate mdx-to-csf --glob "src/**/*.stories.mdx" ``` - diff --git a/docs/_snippets/storybook-migrate-stories-of-to-csf.md b/docs/_snippets/storybook-migrate-stories-of-to-csf.md index 0f73203fd378..392ca32e5e6b 100644 --- a/docs/_snippets/storybook-migrate-stories-of-to-csf.md +++ b/docs/_snippets/storybook-migrate-stories-of-to-csf.md @@ -12,4 +12,3 @@ pnpm dlx storybook@latest migrate storiesof-to-csf --glob="**/*.stories.tsx" --p # Convert storiesOf to CSF 1 yarn dlx storybook@latest migrate storiesof-to-csf --glob="**/*.stories.tsx" --parser=tsx ``` - diff --git a/docs/_snippets/storybook-preset-full-config-object.md b/docs/_snippets/storybook-preset-full-config-object.md index 06cf12f99b02..d744586ea9f0 100644 --- a/docs/_snippets/storybook-preset-full-config-object.md +++ b/docs/_snippets/storybook-preset-full-config-object.md @@ -12,4 +12,3 @@ export default { }, }; ``` - diff --git a/docs/_snippets/storybook-preview-auto-docs-custom-docs-container.md b/docs/_snippets/storybook-preview-auto-docs-custom-docs-container.md index 9e0828acd150..52d25e847a61 100644 --- a/docs/_snippets/storybook-preview-auto-docs-custom-docs-container.md +++ b/docs/_snippets/storybook-preview-auto-docs-custom-docs-container.md @@ -50,4 +50,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-auto-docs-custom-mdx-template.md b/docs/_snippets/storybook-preview-auto-docs-custom-mdx-template.md index 1b11d0d702fb..0e97c75f2b19 100644 --- a/docs/_snippets/storybook-preview-auto-docs-custom-mdx-template.md +++ b/docs/_snippets/storybook-preview-auto-docs-custom-mdx-template.md @@ -9,4 +9,3 @@ export default { }, }; ``` - diff --git a/docs/_snippets/storybook-preview-auto-docs-custom-template-function.md b/docs/_snippets/storybook-preview-auto-docs-custom-template-function.md index 0d6d10c90fa7..b7a8a420f8eb 100644 --- a/docs/_snippets/storybook-preview-auto-docs-custom-template-function.md +++ b/docs/_snippets/storybook-preview-auto-docs-custom-template-function.md @@ -56,4 +56,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-auto-docs-override-mdx-container.md b/docs/_snippets/storybook-preview-auto-docs-override-mdx-container.md index 03d642e2cd77..315429659e90 100644 --- a/docs/_snippets/storybook-preview-auto-docs-override-mdx-container.md +++ b/docs/_snippets/storybook-preview-auto-docs-override-mdx-container.md @@ -68,4 +68,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-auto-docs-override-theme.md b/docs/_snippets/storybook-preview-auto-docs-override-theme.md index 7b1b355b42fd..8639496e6d8d 100644 --- a/docs/_snippets/storybook-preview-auto-docs-override-theme.md +++ b/docs/_snippets/storybook-preview-auto-docs-override-theme.md @@ -38,4 +38,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-body-example.md b/docs/_snippets/storybook-preview-body-example.md index 07ec6f9144ed..21886170b09d 100644 --- a/docs/_snippets/storybook-preview-body-example.md +++ b/docs/_snippets/storybook-preview-body-example.md @@ -1,6 +1,3 @@ -```html renderer="common" language="ts" tabTitle="html" -{/* .storybook/preview-body.html */} - +```html filename=".storybook/preview-body.html" renderer="common" language="js" <div id="custom-root"></div> ``` - diff --git a/docs/_snippets/storybook-preview-body-font-size.md b/docs/_snippets/storybook-preview-body-font-size.md index 1aaa3031d097..99c62f5d7726 100644 --- a/docs/_snippets/storybook-preview-body-font-size.md +++ b/docs/_snippets/storybook-preview-body-font-size.md @@ -1,10 +1,7 @@ -```html renderer="common" language="ts" tabTitle="html" -{/* .storybook/preview-body.html */} - +```html filename=".storybook/preview-body.html" renderer="common" language="js" <style> html { font-size: 15px; } </style> ``` - diff --git a/docs/_snippets/storybook-preview-compodoc-config.md b/docs/_snippets/storybook-preview-compodoc-config.md index 776249642ba2..17d7af9cf4e8 100644 --- a/docs/_snippets/storybook-preview-compodoc-config.md +++ b/docs/_snippets/storybook-preview-compodoc-config.md @@ -20,4 +20,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-configure-globaltypes.md b/docs/_snippets/storybook-preview-configure-globaltypes.md index a5504e518507..bbf1c6dd7af8 100644 --- a/docs/_snippets/storybook-preview-configure-globaltypes.md +++ b/docs/_snippets/storybook-preview-configure-globaltypes.md @@ -75,4 +75,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-custom-canvas.md b/docs/_snippets/storybook-preview-custom-canvas.md index 4f5f90024f3b..05fccc7d5366 100644 --- a/docs/_snippets/storybook-preview-custom-canvas.md +++ b/docs/_snippets/storybook-preview-custom-canvas.md @@ -30,4 +30,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-custom-code-renderer.md b/docs/_snippets/storybook-preview-custom-code-renderer.md index d32357ab45a6..a70653aee1cb 100644 --- a/docs/_snippets/storybook-preview-custom-code-renderer.md +++ b/docs/_snippets/storybook-preview-custom-code-renderer.md @@ -30,4 +30,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-custom-elements-config.md b/docs/_snippets/storybook-preview-custom-elements-config.md index 7d0db859cb9c..8ba526e80655 100644 --- a/docs/_snippets/storybook-preview-custom-elements-config.md +++ b/docs/_snippets/storybook-preview-custom-elements-config.md @@ -38,4 +38,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-custom-metadata.md b/docs/_snippets/storybook-preview-custom-metadata.md index 50e6530eb191..17334b597d4b 100644 --- a/docs/_snippets/storybook-preview-custom-metadata.md +++ b/docs/_snippets/storybook-preview-custom-metadata.md @@ -15,4 +15,3 @@ export default { }, }; ``` - diff --git a/docs/_snippets/storybook-preview-custom-params.md b/docs/_snippets/storybook-preview-custom-params.md index b9c1908beb62..862749b58ccc 100644 --- a/docs/_snippets/storybook-preview-custom-params.md +++ b/docs/_snippets/storybook-preview-custom-params.md @@ -28,4 +28,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-custom-toc.md b/docs/_snippets/storybook-preview-custom-toc.md index c3846775abf1..25ea41c85db4 100644 --- a/docs/_snippets/storybook-preview-custom-toc.md +++ b/docs/_snippets/storybook-preview-custom-toc.md @@ -40,4 +40,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-doc-blocks-controls-exclude-prop.md b/docs/_snippets/storybook-preview-doc-blocks-controls-exclude-prop.md index 08ac32cb8132..5a7a9535a138 100644 --- a/docs/_snippets/storybook-preview-doc-blocks-controls-exclude-prop.md +++ b/docs/_snippets/storybook-preview-doc-blocks-controls-exclude-prop.md @@ -22,4 +22,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-docs-dark-theme.md b/docs/_snippets/storybook-preview-docs-dark-theme.md index 423d1c9cb4d1..a356b6176019 100644 --- a/docs/_snippets/storybook-preview-docs-dark-theme.md +++ b/docs/_snippets/storybook-preview-docs-dark-theme.md @@ -26,4 +26,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-empty-sort-object.md b/docs/_snippets/storybook-preview-empty-sort-object.md index dc73686f2f7a..669f71ed8cef 100644 --- a/docs/_snippets/storybook-preview-empty-sort-object.md +++ b/docs/_snippets/storybook-preview-empty-sort-object.md @@ -30,4 +30,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-enable-toc.md b/docs/_snippets/storybook-preview-enable-toc.md index 0f131ecbab23..a4d0c95e3203 100644 --- a/docs/_snippets/storybook-preview-enable-toc.md +++ b/docs/_snippets/storybook-preview-enable-toc.md @@ -22,4 +22,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-expanded-controls.md b/docs/_snippets/storybook-preview-expanded-controls.md index 522860eda7ed..e168a359868a 100644 --- a/docs/_snippets/storybook-preview-expanded-controls.md +++ b/docs/_snippets/storybook-preview-expanded-controls.md @@ -18,4 +18,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-extended-theme-variables.md b/docs/_snippets/storybook-preview-extended-theme-variables.md index d1ca5e3db5cf..e6df84d48ec4 100644 --- a/docs/_snippets/storybook-preview-extended-theme-variables.md +++ b/docs/_snippets/storybook-preview-extended-theme-variables.md @@ -5,4 +5,3 @@ addonActionsTheme: { BASE_BACKGROUND_COLOR: 'transparent', } ``` - diff --git a/docs/_snippets/storybook-preview-global-decorator.md b/docs/_snippets/storybook-preview-global-decorator.md index 492cb13867d6..041dd4dfd4d7 100644 --- a/docs/_snippets/storybook-preview-global-decorator.md +++ b/docs/_snippets/storybook-preview-global-decorator.md @@ -121,4 +121,3 @@ export default { decorators: [(story) => html`<div style="margin: 3em">${story()}</div>`], }; ``` - diff --git a/docs/_snippets/storybook-preview-global-loader.md b/docs/_snippets/storybook-preview-global-loader.md index 3c84596ad58d..d63d87dc76e7 100644 --- a/docs/_snippets/storybook-preview-global-loader.md +++ b/docs/_snippets/storybook-preview-global-loader.md @@ -22,4 +22,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-global-parameters.md b/docs/_snippets/storybook-preview-global-parameters.md index b9c1908beb62..862749b58ccc 100644 --- a/docs/_snippets/storybook-preview-global-parameters.md +++ b/docs/_snippets/storybook-preview-global-parameters.md @@ -28,4 +28,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-head-example.md b/docs/_snippets/storybook-preview-head-example.md index 3afab4ac7d2d..8b744dd19bdc 100644 --- a/docs/_snippets/storybook-preview-head-example.md +++ b/docs/_snippets/storybook-preview-head-example.md @@ -1,12 +1,13 @@ -```html renderer="common" language="ts" tabTitle="html" -{/* .storybook/preview-head.html */} - -{/* Pull in static files served from your Static directory or the internet */} -{/* Example: `main.js|ts` is configured with staticDirs: ['../public'] and your font is located in the `fonts` directory inside your `public` directory */} +```html filename=".storybook/preview-head.html" renderer="common" language="js" +<!-- +Pull in static files served from your Static directory or the internet +Example: +`main.js|ts` is configured with staticDirs: ['../public'] and your font is located in the `fonts` +directory inside your `public` directory +--> <link rel="preload" href="/fonts/my-font.woff2" /> -{/* Or you can load custom head-tag JavaScript: */} - +<!-- Or you can load custom head-tag JavaScript: --> <script src="https://use.typekit.net/xxxyyy.js"></script> <script> try { @@ -14,4 +15,3 @@ } catch (e) {} </script> ``` - diff --git a/docs/_snippets/storybook-preview-head-import-global-styles.md b/docs/_snippets/storybook-preview-head-import-global-styles.md index aab04dfd4795..7f1c18be7155 100644 --- a/docs/_snippets/storybook-preview-head-import-global-styles.md +++ b/docs/_snippets/storybook-preview-head-import-global-styles.md @@ -1,14 +1,11 @@ -```html renderer="common" language="ts" tabTitle="html" -{/* .storybook/preview-head.html */} - -{/* Loads a font from a CDN */} +```html filename=".storybook/preview-head.html" renderer="common" language="ts" +<!-- Loads a font from a CDN --> <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet" /> -{/* Load your CSS file */} +<!-- Load your CSS file --> <link rel="stylesheet" href="path/to/your/styles.css" /> ``` - diff --git a/docs/_snippets/storybook-preview-import-global-styles.md b/docs/_snippets/storybook-preview-import-global-styles.md index d73c34e4776b..17219d409cda 100644 --- a/docs/_snippets/storybook-preview-import-global-styles.md +++ b/docs/_snippets/storybook-preview-import-global-styles.md @@ -18,4 +18,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-layout-param.md b/docs/_snippets/storybook-preview-layout-param.md index 3e2d7fd520d0..4b6c649d9a83 100644 --- a/docs/_snippets/storybook-preview-layout-param.md +++ b/docs/_snippets/storybook-preview-layout-param.md @@ -18,4 +18,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-locales-globaltype.md b/docs/_snippets/storybook-preview-locales-globaltype.md index d96bf310cc3a..c0928d584a98 100644 --- a/docs/_snippets/storybook-preview-locales-globaltype.md +++ b/docs/_snippets/storybook-preview-locales-globaltype.md @@ -78,4 +78,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-matching-argtypes.md b/docs/_snippets/storybook-preview-matching-argtypes.md index 6d2f2212593e..61e2beae5c28 100644 --- a/docs/_snippets/storybook-preview-matching-argtypes.md +++ b/docs/_snippets/storybook-preview-matching-argtypes.md @@ -18,4 +18,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-optout-inline.md b/docs/_snippets/storybook-preview-optout-inline.md index 81e32f4b4399..60991af50570 100644 --- a/docs/_snippets/storybook-preview-optout-inline.md +++ b/docs/_snippets/storybook-preview-optout-inline.md @@ -24,4 +24,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-parameters-color-swatches.md b/docs/_snippets/storybook-preview-parameters-color-swatches.md index 5029cb279168..a018de4b7a09 100644 --- a/docs/_snippets/storybook-preview-parameters-color-swatches.md +++ b/docs/_snippets/storybook-preview-parameters-color-swatches.md @@ -22,4 +22,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-prepareforinline.md b/docs/_snippets/storybook-preview-prepareforinline.md index e0940ccf9819..443f62a6b1de 100644 --- a/docs/_snippets/storybook-preview-prepareforinline.md +++ b/docs/_snippets/storybook-preview-prepareforinline.md @@ -11,4 +11,3 @@ export default { }, }; ``` - diff --git a/docs/_snippets/storybook-preview-register-language-globally.md b/docs/_snippets/storybook-preview-register-language-globally.md index 4d798c0e46d0..6fb0772bb4a3 100644 --- a/docs/_snippets/storybook-preview-register-language-globally.md +++ b/docs/_snippets/storybook-preview-register-language-globally.md @@ -40,4 +40,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-sort-function.md b/docs/_snippets/storybook-preview-sort-function.md index 6c0d87e7a88a..d55ba7643036 100644 --- a/docs/_snippets/storybook-preview-sort-function.md +++ b/docs/_snippets/storybook-preview-sort-function.md @@ -25,4 +25,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-use-global-type.md b/docs/_snippets/storybook-preview-use-global-type.md index 0f9a8737f699..994fb264a6e4 100644 --- a/docs/_snippets/storybook-preview-use-global-type.md +++ b/docs/_snippets/storybook-preview-use-global-type.md @@ -8,7 +8,7 @@ const preview: Preview = { (story) => `<div [class]="myTheme">${story}</div>`, ({ globals }) => { return { myTheme: globals['theme'] }; - }, + } ), ], }; @@ -143,7 +143,7 @@ const preview: Preview = { export default preview; ``` -```js filename=".storybook/preview.js" renderer="vue" language="js" tabTitle="3" +```js filename=".storybook/preview.js" renderer="vue" language="js" import { setup } from '@storybook/vue3'; import { VApp } from 'vuetify/components'; @@ -176,7 +176,7 @@ const preview = { export default preview; ``` -```ts filename=".storybook/preview.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename=".storybook/preview.ts" renderer="vue" language="ts" import type { Preview } from '@storybook/vue3'; import { setup } from '@storybook/vue3'; @@ -243,4 +243,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-with-angular-polyfills.md b/docs/_snippets/storybook-preview-with-angular-polyfills.md deleted file mode 100644 index 26dc3eb44ddb..000000000000 --- a/docs/_snippets/storybook-preview-with-angular-polyfills.md +++ /dev/null @@ -1,21 +0,0 @@ -```js filename=".storybook/preview.js" renderer="angular" language="js" -import { setCompodocJson } from '@storybook/addon-docs/angular'; -import docJson from '../documentation.json'; - -import '../src/polyfills'; - -setCompodocJson(docJson); - -export default { - parameters: { - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/, - }, - }, - docs: { story: { inline: true } }, - }, -}; -``` - diff --git a/docs/_snippets/storybook-preview-with-hoc-component-decorator.md b/docs/_snippets/storybook-preview-with-hoc-component-decorator.md deleted file mode 100644 index 2b8a1d70b738..000000000000 --- a/docs/_snippets/storybook-preview-with-hoc-component-decorator.md +++ /dev/null @@ -1,50 +0,0 @@ -```js filename=".storybook/preview.js" renderer="vue" language="js" tabTitle="component-3" -import { setup } from '@storybook/vue3'; - -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faPlusSquare as fasPlusSquare } from '@fortawesome/free-solid-svg-icons'; - -import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; - -setup((app) => { - //👇 Adds the icon to the library so you can use it in your story. - library.add(fasPlusSquare); - app.component('font-awesome-icon', FontAwesomeIcon); -}); - -export default { - decorators: [ - (story) => ({ - components: { story }, - template: '<div style="margin: 3em;"><story /></div>', - }), - ], -}; -``` - -```ts filename=".storybook/preview.ts" renderer="vue" language="ts" tabTitle="component-3" -import { setup, Preview } from '@storybook/vue3'; - -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faPlusSquare as fasPlusSquare } from '@fortawesome/free-solid-svg-icons'; - -import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; - -setup((app) => { - //👇 Adds the icon to the library so you can use it in your story. - library.add(fasPlusSquare); - app.component('font-awesome-icon', FontAwesomeIcon); -}); - -const preview: Preview = { - decorators: [ - (story) => ({ - components: { story }, - template: '<div style="margin: 3em;"><story /></div>', - }), - ], -}; - -export default preview; -``` - diff --git a/docs/_snippets/storybook-preview-with-library-decorator.md b/docs/_snippets/storybook-preview-with-library-decorator.md index 8e90b2747784..6c9b9219bf3e 100644 --- a/docs/_snippets/storybook-preview-with-library-decorator.md +++ b/docs/_snippets/storybook-preview-with-library-decorator.md @@ -1,4 +1,33 @@ -```js filename=".storybook/preview.js" renderer="vue" language="js" tabTitle="library-3" +```js filename=".storybook/preview.ts" renderer="angular" language="ts" tabTitle="preview" +import type { Preview } from '@storybook/angular'; + +import { setCompodocJson } from '@storybook/addon-docs/angular'; + +import docJson from '../documentation.json'; + +import '../src/polyfills'; + +setCompodocJson(docJson); + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + }, +}; + +export default preview; +``` + +```ts filename="src/polyfills.ts" renderer="angular" language="ts" tabTitle="polyfills" +import '@angular/localize/init'; +``` + +```js filename=".storybook/preview.js" renderer="vue" language="js" tabTitle="library" import { setup } from '@storybook/vue3'; import { createPinia } from 'pinia'; @@ -18,7 +47,31 @@ export default { }; ``` -```ts filename=".storybook/preview.ts" renderer="vue" language="ts" tabTitle="library-3" +```js filename=".storybook/preview.js" renderer="vue" language="js" tabTitle="component" +import { setup } from '@storybook/vue3'; + +import { library } from '@fortawesome/fontawesome-svg-core'; +import { faPlusSquare as fasPlusSquare } from '@fortawesome/free-solid-svg-icons'; + +import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; + +setup((app) => { + //👇 Adds the icon to the library so you can use it in your story. + library.add(fasPlusSquare); + app.component('font-awesome-icon', FontAwesomeIcon); +}); + +export default { + decorators: [ + (story) => ({ + components: { story }, + template: '<div style="margin: 3em;"><story /></div>', + }), + ], +}; +``` + +```ts filename=".storybook/preview.ts" renderer="vue" language="ts" tabTitle="library" import { setup, Preview } from '@storybook/vue3'; import { createPinia } from 'pinia'; @@ -40,3 +93,28 @@ const preview: Preview = { export default preview; ``` +```ts filename=".storybook/preview.ts" renderer="vue" language="ts" tabTitle="component" +import { setup, Preview } from '@storybook/vue3'; + +import { library } from '@fortawesome/fontawesome-svg-core'; +import { faPlusSquare as fasPlusSquare } from '@fortawesome/free-solid-svg-icons'; + +import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; + +setup((app) => { + //👇 Adds the icon to the library so you can use it in your story. + library.add(fasPlusSquare); + app.component('font-awesome-icon', FontAwesomeIcon); +}); + +const preview: Preview = { + decorators: [ + (story) => ({ + components: { story }, + template: '<div style="margin: 3em;"><story /></div>', + }), + ], +}; + +export default preview; +``` diff --git a/docs/_snippets/storybook-preview-with-ordered-pages-and-wildcard.md b/docs/_snippets/storybook-preview-with-ordered-pages-and-wildcard.md index b1b61605b116..04bf16d2d20e 100644 --- a/docs/_snippets/storybook-preview-with-ordered-pages-and-wildcard.md +++ b/docs/_snippets/storybook-preview-with-ordered-pages-and-wildcard.md @@ -26,4 +26,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-preview-with-ordered-pages.md b/docs/_snippets/storybook-preview-with-ordered-pages.md index 1bf1a7ec0a4c..72b79e145c55 100644 --- a/docs/_snippets/storybook-preview-with-ordered-pages.md +++ b/docs/_snippets/storybook-preview-with-ordered-pages.md @@ -26,4 +26,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/storybook-read-environment-variables.md b/docs/_snippets/storybook-read-environment-variables.md index 7c8f1c8a6c4c..608b90bbc845 100644 --- a/docs/_snippets/storybook-read-environment-variables.md +++ b/docs/_snippets/storybook-read-environment-variables.md @@ -7,4 +7,3 @@ console.log(process.env.STORYBOOK_DATA_KEY); console.log(import.meta.env.STORYBOOK_THEME); console.log(import.meta.env.STORYBOOK_DATA_KEY); ``` - diff --git a/docs/_snippets/storybook-remove-command.md b/docs/_snippets/storybook-remove-command.md index ba8c815f8f48..43f8d804617a 100644 --- a/docs/_snippets/storybook-remove-command.md +++ b/docs/_snippets/storybook-remove-command.md @@ -9,4 +9,3 @@ pnpm dlx storybook@latest remove @storybook/addon-a11y ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@latest remove @storybook/addon-a11y ``` - diff --git a/docs/_snippets/storybook-run-dev.md b/docs/_snippets/storybook-run-dev.md index d1b093f92486..4c562b86bf86 100644 --- a/docs/_snippets/storybook-run-dev.md +++ b/docs/_snippets/storybook-run-dev.md @@ -13,4 +13,3 @@ pnpm run storybook ```shell renderer="common" language="js" packageManager="yarn" yarn storybook ``` - diff --git a/docs/_snippets/storybook-server-framework-options.md b/docs/_snippets/storybook-server-framework-options.md index b16de7b63cc8..56916a549d33 100644 --- a/docs/_snippets/storybook-server-framework-options.md +++ b/docs/_snippets/storybook-server-framework-options.md @@ -8,4 +8,3 @@ export default { frameworkPresets: [require.resolve('./framework-preset-my-framework.js')], }; ``` - diff --git a/docs/_snippets/storybook-server-options.md b/docs/_snippets/storybook-server-options.md index 5af66e203bb7..ce8b458fc199 100644 --- a/docs/_snippets/storybook-server-options.md +++ b/docs/_snippets/storybook-server-options.md @@ -7,4 +7,3 @@ export default { frameworkPresets: [require.resolve('./framework-preset-vue.js')], }; ``` - diff --git a/docs/_snippets/storybook-start-dev-server.md b/docs/_snippets/storybook-start-dev-server.md index b8cb5ef811b0..62b5e0df161b 100644 --- a/docs/_snippets/storybook-start-dev-server.md +++ b/docs/_snippets/storybook-start-dev-server.md @@ -5,4 +5,3 @@ import options from './options'; buildDev(options); ``` - diff --git a/docs/_snippets/storybook-story-layout-param.md b/docs/_snippets/storybook-story-layout-param.md index 8594ccdda3a5..f0403f7993e4 100644 --- a/docs/_snippets/storybook-story-layout-param.md +++ b/docs/_snippets/storybook-story-layout-param.md @@ -99,4 +99,3 @@ export const WithLayout: Story = { }, }; ``` - diff --git a/docs/_snippets/storybook-storyloading-with-directory.md b/docs/_snippets/storybook-storyloading-with-directory.md index efd3ad885d4f..1f9f22e37611 100644 --- a/docs/_snippets/storybook-storyloading-with-directory.md +++ b/docs/_snippets/storybook-storyloading-with-directory.md @@ -19,4 +19,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-storysource-manager-entries.md b/docs/_snippets/storybook-storysource-manager-entries.md index 1eac3840ec4b..7f2a65c8cf15 100644 --- a/docs/_snippets/storybook-storysource-manager-entries.md +++ b/docs/_snippets/storybook-storysource-manager-entries.md @@ -1,4 +1,3 @@ ```js filename="storysource/preset.js" renderer="common" language="js" /* nothing needed */ ``` - diff --git a/docs/_snippets/storybook-telemetry-crash-report-event.md b/docs/_snippets/storybook-telemetry-crash-report-event.md index 5b307df850b6..118bd8b6c179 100644 --- a/docs/_snippets/storybook-telemetry-crash-report-event.md +++ b/docs/_snippets/storybook-telemetry-crash-report-event.md @@ -11,4 +11,3 @@ message: 'Your button is not working' } ``` - diff --git a/docs/_snippets/storybook-telemetry-main-enable-crash-reports.md b/docs/_snippets/storybook-telemetry-main-enable-crash-reports.md index aa80c4375fe0..32f436b273ae 100644 --- a/docs/_snippets/storybook-telemetry-main-enable-crash-reports.md +++ b/docs/_snippets/storybook-telemetry-main-enable-crash-reports.md @@ -1,4 +1,4 @@ -```js filename=".storybook/main.js" renderer="common" language="js" tabTitle="main-js" +```js filename=".storybook/main.js" renderer="common" language="js" export default { // Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) framework: '@storybook/your-framework', @@ -9,7 +9,7 @@ export default { }; ``` -```ts filename=".storybook/main.ts" renderer="common" language="ts" tabTitle="main-ts" +```ts filename=".storybook/main.ts" renderer="common" language="ts" // Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite) import type { StorybookConfig } from '@storybook/your-framework'; @@ -23,4 +23,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/storybook-telemetry-preview-event.md b/docs/_snippets/storybook-telemetry-preview-event.md index 8cc060bbafd6..275db577eef9 100644 --- a/docs/_snippets/storybook-telemetry-preview-event.md +++ b/docs/_snippets/storybook-telemetry-preview-event.md @@ -5,4 +5,3 @@ STORYBOOK_TELEMETRY_DEBUG=1 npm run storybook ```shell renderer="common" language="js" packageManager="yarn" STORYBOOK_TELEMETRY_DEBUG=1 yarn storybook ``` - diff --git a/docs/_snippets/storybook-telemetry-storybook-enable-crash-reports-env.md b/docs/_snippets/storybook-telemetry-storybook-enable-crash-reports-env.md new file mode 100644 index 000000000000..cc5eb3bd9da9 --- /dev/null +++ b/docs/_snippets/storybook-telemetry-storybook-enable-crash-reports-env.md @@ -0,0 +1,3 @@ +```shell renderer="common" language="js" +STORYBOOK_ENABLE_CRASH_REPORTS=1 yarn storybook +``` diff --git a/docs/_snippets/storybook-telemetry-storybook-enable-crash-reports.md b/docs/_snippets/storybook-telemetry-storybook-enable-crash-reports-flag.md similarity index 74% rename from docs/_snippets/storybook-telemetry-storybook-enable-crash-reports.md rename to docs/_snippets/storybook-telemetry-storybook-enable-crash-reports-flag.md index 4eebe6003d03..5724a59ee45e 100644 --- a/docs/_snippets/storybook-telemetry-storybook-enable-crash-reports.md +++ b/docs/_snippets/storybook-telemetry-storybook-enable-crash-reports-flag.md @@ -1,7 +1,3 @@ -```shell renderer="common" language="js" tabTitle="env-var" -STORYBOOK_ENABLE_CRASH_REPORTS=1 yarn storybook -``` - ```shell renderer="common" language="js" packageManager="npm" npm run storybook -- --enable-crash-reports ``` @@ -13,4 +9,3 @@ pnpm run storybook --enable-crash-reports ```shell renderer="common" language="js" packageManager="yarn" yarn storybook --enable-crash-reports ``` - diff --git a/docs/_snippets/storybook-test-fn-mock-spy.md b/docs/_snippets/storybook-test-fn-mock-spy.md index 62760213efbb..d371d0abb66f 100644 --- a/docs/_snippets/storybook-test-fn-mock-spy.md +++ b/docs/_snippets/storybook-test-fn-mock-spy.md @@ -5,6 +5,7 @@ import { expect, userEvent, within } from '@storybook/test'; // 👇 Must include the `.mock` portion of filename to have mocks typed correctly import { saveNote } from '#app/actions.mock'; import { createNotes } from '#mocks/notes'; + import NoteUI from './note-ui'; const meta: Meta<NoteUI> = { @@ -39,6 +40,7 @@ import { expect, userEvent, within } from '@storybook/test'; import { saveNote } from '#app/actions.mock'; import { createNotes } from '#mocks/notes'; + import NoteUI from './note-ui'; export default { @@ -73,6 +75,7 @@ import { expect, userEvent, within } from '@storybook/test'; // 👇 Must include the `.mock` portion of filename to have mocks typed correctly import { saveNote } from '#app/actions.mock'; import { createNotes } from '#mocks/notes'; + import NoteUI from './note-ui'; const meta = { @@ -203,4 +206,3 @@ export const SaveFlow: Story = { }, }; ``` - diff --git a/docs/_snippets/storybook-test-mock-file-example.md b/docs/_snippets/storybook-test-mock-file-example.md index 594f84887875..6313dcf2147c 100644 --- a/docs/_snippets/storybook-test-mock-file-example.md +++ b/docs/_snippets/storybook-test-mock-file-example.md @@ -5,4 +5,3 @@ import * as actual from './session'; export * from './session'; export const getUserFromSession = fn(actual.getUserFromSession).mockName('getUserFromSession'); ``` - diff --git a/docs/_snippets/storybook-test-mock-return-value.md b/docs/_snippets/storybook-test-mock-return-value.md index e552bc061e06..4017f205a00b 100644 --- a/docs/_snippets/storybook-test-mock-return-value.md +++ b/docs/_snippets/storybook-test-mock-return-value.md @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from '@storybook/angular'; // 👇 Must include the `.mock` portion of filename to have mocks typed correctly import { getUserFromSession } from '#api/session.mock'; + import { Page } from './Page'; const meta: Meta<Page> = { @@ -22,6 +23,7 @@ export const Default: Story = { ```js filename="Page.stories.js" renderer="common" language="js" import { getUserFromSession } from '#api/session.mock'; + import { Page } from './Page'; export default { @@ -42,6 +44,7 @@ import type { Meta, StoryObj } from '@storybook/your-renderer'; // 👇 Must include the `.mock` portion of filename to have mocks typed correctly import { getUserFromSession } from '#api/session.mock'; + import { Page } from './Page'; const meta = { @@ -66,6 +69,7 @@ import type { Meta, StoryObj } from '@storybook/your-renderer'; // 👇 Must include the `.mock` portion of filename to have mocks typed correctly import { getUserFromSession } from '#api/session.mock'; + import { Page } from './Page'; const meta: Meta<typeof Page> = { @@ -118,4 +122,3 @@ export const Default: Story = { }, }; ``` - diff --git a/docs/_snippets/storybook-test-with-storyname.md b/docs/_snippets/storybook-test-with-storyname.md index e09ae2cec29b..8cabc5577c1b 100644 --- a/docs/_snippets/storybook-test-with-storyname.md +++ b/docs/_snippets/storybook-test-with-storyname.md @@ -13,4 +13,3 @@ it('should format CSF exports with sensible defaults', () => { }); }); ``` - diff --git a/docs/_snippets/storybook-theme-example-variables.md b/docs/_snippets/storybook-theme-example-variables.md index 0f045dc6c52e..aca575cad984 100644 --- a/docs/_snippets/storybook-theme-example-variables.md +++ b/docs/_snippets/storybook-theme-example-variables.md @@ -9,4 +9,3 @@ export default create({ brandTarget: '_self', }); ``` - diff --git a/docs/_snippets/storybook-theming-packages-install.md b/docs/_snippets/storybook-theming-packages-install.md index a4e031c514d8..36a076f0b8f3 100644 --- a/docs/_snippets/storybook-theming-packages-install.md +++ b/docs/_snippets/storybook-theming-packages-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/manager-api @storybook/theming ```shell renderer="common" language="js" packageManager="yarn" yarn add --dev @storybook/manager-api @storybook/theming ``` - diff --git a/docs/_snippets/storybook-theming-styled-import.md b/docs/_snippets/storybook-theming-styled-import.md index 112d6d7497d2..5c1f84ea8b6c 100644 --- a/docs/_snippets/storybook-theming-styled-import.md +++ b/docs/_snippets/storybook-theming-styled-import.md @@ -1,4 +1,3 @@ ```js filename="YourTheme.js" renderer="common" language="js" import { styled } from '@storybook/theming'; ``` - diff --git a/docs/_snippets/storybook-upgrade-prerelease.md b/docs/_snippets/storybook-upgrade-prerelease.md index 882153c1a175..3b71ef4c4d98 100644 --- a/docs/_snippets/storybook-upgrade-prerelease.md +++ b/docs/_snippets/storybook-upgrade-prerelease.md @@ -9,4 +9,3 @@ pnpm dlx storybook@next upgrade ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@next upgrade ``` - diff --git a/docs/_snippets/storybook-upgrade-to-prior-major.md b/docs/_snippets/storybook-upgrade-to-prior-major.md index 58295bb021e3..a8a0de4ad9ba 100644 --- a/docs/_snippets/storybook-upgrade-to-prior-major.md +++ b/docs/_snippets/storybook-upgrade-to-prior-major.md @@ -9,4 +9,3 @@ pnpm dlx storybook@^7 upgrade ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@^7 upgrade ``` - diff --git a/docs/_snippets/storybook-upgrade.md b/docs/_snippets/storybook-upgrade.md index ddc92f704cb2..3b71ef4c4d98 100644 --- a/docs/_snippets/storybook-upgrade.md +++ b/docs/_snippets/storybook-upgrade.md @@ -1,12 +1,11 @@ ```shell renderer="common" language="js" packageManager="npm" -npx storybook@latest upgrade +npx storybook@next upgrade ``` ```shell renderer="common" language="js" packageManager="pnpm" -pnpm dlx storybook@latest upgrade +pnpm dlx storybook@next upgrade ``` ```shell renderer="common" language="js" packageManager="yarn" -yarn dlx storybook@latest upgrade +yarn dlx storybook@next upgrade ``` - diff --git a/docs/_snippets/storybook-vite-builder-install.md b/docs/_snippets/storybook-vite-builder-install.md index 0de50e2116b3..9bc49e64fbf8 100644 --- a/docs/_snippets/storybook-vite-builder-install.md +++ b/docs/_snippets/storybook-vite-builder-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/builder-vite ```shell renderer="common" language="js" packageManager="yarn" yarn add --dev @storybook/builder-vite ``` - diff --git a/docs/_snippets/storybook-vite-builder-jest-mock.md b/docs/_snippets/storybook-vite-builder-jest-mock.md index 1a864be1d6e2..51a05104a0dc 100644 --- a/docs/_snippets/storybook-vite-builder-jest-mock.md +++ b/docs/_snippets/storybook-vite-builder-jest-mock.md @@ -1,8 +1,5 @@ -```html renderer="common" language="ts" tabTitle="html" -{/* .storybook/preview-head.html */} - +```html filename=".storybook/preview-head.html" renderer="common" language="js" <script> window.global = window; </script> ``` - diff --git a/docs/_snippets/storybook-vite-builder-ts-configure.md b/docs/_snippets/storybook-vite-builder-ts-configure.md index f9fb98a7e6a6..61ec1ecce1ea 100644 --- a/docs/_snippets/storybook-vite-builder-ts-configure.md +++ b/docs/_snippets/storybook-vite-builder-ts-configure.md @@ -29,4 +29,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/subpath-imports-config.md b/docs/_snippets/subpath-imports-config.md index 676b3e461631..9d61b031d0f9 100644 --- a/docs/_snippets/subpath-imports-config.md +++ b/docs/_snippets/subpath-imports-config.md @@ -23,4 +23,3 @@ } } ``` - diff --git a/docs/_snippets/svelte-csf-addon-install.md b/docs/_snippets/svelte-csf-addon-install.md index 3b036e9fecf0..45120afac465 100644 --- a/docs/_snippets/svelte-csf-addon-install.md +++ b/docs/_snippets/svelte-csf-addon-install.md @@ -9,4 +9,3 @@ pnpm dlx storybook@latest add @storybook/addon-svelte-csf ```shell renderer="svelte" language="js" packageManager="yarn" yarn storybook@latest add @storybook/addon-svelte-csf ``` - diff --git a/docs/_snippets/svelte-csf-addon-options.md b/docs/_snippets/svelte-csf-addon-options.md new file mode 100644 index 000000000000..12b4dc2f730f --- /dev/null +++ b/docs/_snippets/svelte-csf-addon-options.md @@ -0,0 +1,31 @@ +```js filename=".storybook/main.js" renderer="svelte" language="js" +export default { + // Other configuration + addons: [ + { + name: '@storybook/addon-svelte-csf', + options: { + legacyTemplate: true, // Enables the legacy template syntax + }, + }, + ], +}; +``` + +```js filename=".storybook/main.ts" renderer="svelte" language="ts" +// Replace your-framework with the name of your Svelte framework +import type { StorybookConfig } from '@storybook/your-framework'; + +const config: StorybookConfig = { + // Other configuration + addons: [ + { + name: '@storybook/addon-svelte-csf', + options: { + legacyTemplate: true, // Enables the legacy template syntax + }, + }, + ], +}; +export default config; +``` diff --git a/docs/_snippets/svelte-csf-addon-tags.md b/docs/_snippets/svelte-csf-addon-tags.md new file mode 100644 index 000000000000..8cf9b43b99c8 --- /dev/null +++ b/docs/_snippets/svelte-csf-addon-tags.md @@ -0,0 +1,31 @@ +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Before" +<script> + import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; +</script> + +<Meta title="MyComponent" component={MyComponent} /> + +<Template let:args> + <MyComponent {...args} /> +</Template> + +<Story name="Default" autodocs /> +``` + +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="After" + +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); + +</script> + +<Story name="Default" tags={['autodocs']} /> +``` diff --git a/docs/_snippets/svelte-csf-story-custom-children.md b/docs/_snippets/svelte-csf-story-custom-children.md new file mode 100644 index 000000000000..cc1263e909c2 --- /dev/null +++ b/docs/_snippets/svelte-csf-story-custom-children.md @@ -0,0 +1,39 @@ +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Before" +<script> + import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; + + import OuterComponent from './OuterComponent.svelte'; + import MyComponent from './MyComponent.svelte'; +</script> + +<Meta title="MyComponent" component={MyComponent} /> + +<Template let:args> + <OuterComponent> + <MyComponent /> + </OuterComponent> +</Template> + +<Story name="Default" /> +``` + +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="After" + +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import OuterComponent from './OuterComponent.svelte'; + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + component: MyComponent, + }); + +</script> + +<Story name="Default"> + <OuterComponent> + <MyComponent /> + </OuterComponent> +</Story> +``` diff --git a/docs/_snippets/svelte-csf-story-migration.md b/docs/_snippets/svelte-csf-story-migration.md new file mode 100644 index 000000000000..e12e0a748671 --- /dev/null +++ b/docs/_snippets/svelte-csf-story-migration.md @@ -0,0 +1,27 @@ +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Before" +<script> + import { Meta, Story } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; +</script> + + +<Meta title="MyComponent" component={MyComponent} /> + +<Story name="Default" /> +``` + +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="After" +<script context> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import MyComponent from './MyComponent.svelte'; + + const { Story } = defineMeta({ + title: 'MyComponent', + component: MyComponent, + }); +</script> + +<Story name="Default" /> +``` diff --git a/docs/_snippets/svelte-vite-add-framework.md b/docs/_snippets/svelte-vite-add-framework.md index 13b0ad47f572..200d3fefe6cc 100644 --- a/docs/_snippets/svelte-vite-add-framework.md +++ b/docs/_snippets/svelte-vite-add-framework.md @@ -15,4 +15,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/svelte-vite-framework-options.md b/docs/_snippets/svelte-vite-framework-options.md new file mode 100644 index 000000000000..d023f1226d8c --- /dev/null +++ b/docs/_snippets/svelte-vite-framework-options.md @@ -0,0 +1,27 @@ +```js filename=".storybook/main.js" renderer="svelte" language="js" +export default { + // ... + framework: { + name: '@storybook/svelte-vite', + options: { + // ... + }, + }, +}; +``` + +```ts filename=".storybook/main.ts" renderer="svelte" language="ts" +import { StorybookConfig } from '@storybook/svelte-vite'; + +const config: StorybookConfig = { + // ... + framework: { + name: '@storybook/svelte-vite', + options: { + // ... + }, + }, +}; + +export default config; +``` diff --git a/docs/_snippets/svelte-vite-install.md b/docs/_snippets/svelte-vite-install.md index 3285ba245fd1..aae2ef5541bb 100644 --- a/docs/_snippets/svelte-vite-install.md +++ b/docs/_snippets/svelte-vite-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/svelte-vite ```shell renderer="svelte" language="js" packageManager="yarn" yarn add --dev @storybook/svelte-vite ``` - diff --git a/docs/_snippets/svelte-webpack-framework-options.md b/docs/_snippets/svelte-webpack-framework-options.md new file mode 100644 index 000000000000..22852dd3ab2f --- /dev/null +++ b/docs/_snippets/svelte-webpack-framework-options.md @@ -0,0 +1,27 @@ +```js filename=".storybook/main.js" renderer="svelte" language="js" +export default { + // ... + framework: { + name: '@storybook/svelte-webpack5', + options: { + // ... + }, + }, +}; +``` + +```ts filename=".storybook/main.ts" renderer="svelte" language="ts" +import { StorybookConfig } from '@storybook/svelte-webpack5'; + +const config: StorybookConfig = { + // ... + framework: { + name: '@storybook/svelte-webpack5', + options: { + // ... + }, + }, +}; + +export default config; +``` diff --git a/docs/_snippets/svelte-webpack5-add-framework.md b/docs/_snippets/svelte-webpack5-add-framework.md index e93100f0043e..2ababfd97736 100644 --- a/docs/_snippets/svelte-webpack5-add-framework.md +++ b/docs/_snippets/svelte-webpack5-add-framework.md @@ -15,4 +15,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/svelte-webpack5-install.md b/docs/_snippets/svelte-webpack5-install.md index a8d7089adfa1..85d5fd91e779 100644 --- a/docs/_snippets/svelte-webpack5-install.md +++ b/docs/_snippets/svelte-webpack5-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/svelte-webpack5 ```shell renderer="svelte" language="js" packageManager="yarn" yarn add --dev @storybook/svelte-webpack5 ``` - diff --git a/docs/_snippets/sveltekit-add-framework.md b/docs/_snippets/sveltekit-add-framework.md index b712a957b5f5..986845f37c15 100644 --- a/docs/_snippets/sveltekit-add-framework.md +++ b/docs/_snippets/sveltekit-add-framework.md @@ -7,7 +7,7 @@ export default { ``` ```ts filename=".storybook/main.ts" renderer="svelte" language="ts" -import { StorybookConfig } from '@storybook/nextjs'; +import { StorybookConfig } from '@storybook/sveltekit'; const config: StorybookConfig = { // ... @@ -17,4 +17,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/sveltekit-framework-options.md b/docs/_snippets/sveltekit-framework-options.md new file mode 100644 index 000000000000..55de473d707b --- /dev/null +++ b/docs/_snippets/sveltekit-framework-options.md @@ -0,0 +1,27 @@ +```js filename=".storybook/main.js" renderer="svelte" language="js" +export default { + // ... + framework: { + name: '@storybook/sveltekit', + options: { + // ... + }, + }, +}; +``` + +```ts filename=".storybook/main.ts" renderer="svelte" language="ts" +import { StorybookConfig } from '@storybook/sveltekit'; + +const config: StorybookConfig = { + // ... + framework: { + name: '@storybook/sveltekit', + options: { + // ... + }, + }, +}; + +export default config; +``` diff --git a/docs/_snippets/sveltekit-install.md b/docs/_snippets/sveltekit-install.md index e7010dd695a8..0ffa2c676836 100644 --- a/docs/_snippets/sveltekit-install.md +++ b/docs/_snippets/sveltekit-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/sveltekit ```shell renderer="svelte" language="js" packageManager="yarn" yarn add --dev @storybook/sveltekit ``` - diff --git a/docs/_snippets/table-story-fully-customize-controls.md b/docs/_snippets/table-story-fully-customize-controls.md deleted file mode 100644 index 091214d5621a..000000000000 --- a/docs/_snippets/table-story-fully-customize-controls.md +++ /dev/null @@ -1,30 +0,0 @@ -```html renderer="svelte" language="ts" tabTitle="native-format" -{/*Table.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; - - import Table from './Table.svelte'; -</script> - -<Meta title="Custom Table" component={Table} argTypes={{ size: { options: ['small', 'medium', -'large'], }, }} /> - -<template let:args> - <table {...args}> - <tbody> - {#each args.data as row} - <tr> - {#each row as col} - <td>{col}</td> - {/each} - </tr> - {/each} - </tbody> - </table> -</template> - -{/* 👇 The data arg is for the story component and the remaining args get passed to the Table component */} -<Story name="Numeric" args={{ data: [ [1, 2, 3], [4, 5, 6], ], size: 'large', }} /> -``` - diff --git a/docs/_snippets/tags-autodocs-in-meta.md b/docs/_snippets/tags-autodocs-in-meta.md index 062907b3fe1f..38c05474cf94 100644 --- a/docs/_snippets/tags-autodocs-in-meta.md +++ b/docs/_snippets/tags-autodocs-in-meta.md @@ -11,6 +11,30 @@ const meta: Meta<Button> = { export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], + }); +</script> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], +}; +``` + ```js filename="Button.stories.js" renderer="common" language="js" import { Button } from './Button'; @@ -21,6 +45,33 @@ export default { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], +} satisfies Meta<typeof Button>; +export default meta; +``` + ```ts filename="Button.stories.ts" renderer="common" language="ts-4-9" // Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite) import type { Meta } from '@storybook/your-framework'; @@ -35,6 +86,33 @@ const meta = { export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], +}; +export default meta; +``` + ```ts filename="Button.stories.ts" renderer="common" language="ts" // Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite) import type { Meta } from '@storybook/your-framework'; @@ -69,4 +147,3 @@ const meta: Meta = { }; export default meta; ``` - diff --git a/docs/_snippets/tags-autodocs-in-preview.md b/docs/_snippets/tags-autodocs-in-preview.md index 9f3f8c030498..7d96acbe053d 100644 --- a/docs/_snippets/tags-autodocs-in-preview.md +++ b/docs/_snippets/tags-autodocs-in-preview.md @@ -18,4 +18,3 @@ const preview: Preview = { export default preview; ``` - diff --git a/docs/_snippets/tags-autodocs-remove-component.md b/docs/_snippets/tags-autodocs-remove-component.md index c1000d58ae8b..60014c991265 100644 --- a/docs/_snippets/tags-autodocs-remove-component.md +++ b/docs/_snippets/tags-autodocs-remove-component.md @@ -1,5 +1,5 @@ ```ts filename="Page.stories.ts" renderer="angular" language="ts" -import type { Meta, StoryObj } from '@storybook/angular'; +import type { Meta } from '@storybook/angular'; import { Page } from './Page'; @@ -11,6 +11,30 @@ const meta: Meta<Page> = { export default meta; ``` +```svelte filename="Page.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Page from './Page.svelte'; + + const { Story } = defineMeta({ + component: Page, + // 👇 Disable auto-generated documentation for this component + tags: ['!autodocs'], + }); +</script> +``` + +```js filename="Page.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Page from './Page.svelte'; + +export default { + component: Page, + // 👇 Disable auto-generated documentation for this component + tags: ['!autodocs'], +}; +``` + ```js filename="Page.stories.js" renderer="common" language="js" import { Page } from './Page'; @@ -21,9 +45,36 @@ export default { }; ``` +```svelte filename="Page.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Page from './Page.svelte'; + + const { Story } = defineMeta({ + component: Page, + // 👇 Disable auto-generated documentation for this component + tags: ['!autodocs'], + }); +</script> +``` + +```ts filename="Page.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Page from './Page.svelte'; + +const meta = { + component: Page, + // 👇 Disable auto-generated documentation for this component + tags: ['!autodocs'], +} satisfies Meta<typeof Page>; +export default meta; +``` + ```ts filename="Page.stories.ts" renderer="common" language="ts-4-9" // Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite) -import type { Meta, StoryObj } from '@storybook/your-framework'; +import type { Meta } from '@storybook/your-framework'; import { Page } from './Page'; @@ -35,9 +86,36 @@ const meta = { export default meta; ``` +```svelte filename="Page.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Page from './Page.svelte'; + + const { Story } = defineMeta({ + component: Page, + // 👇 Disable auto-generated documentation for this component + tags: ['!autodocs'], + }); +</script> +``` + +```ts filename="Page.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Page from './Page.svelte'; + +const meta: Meta<typeof Page> = { + component: Page, + // 👇 Disable auto-generated documentation for this component + tags: ['!autodocs'], +}; +export default meta; +``` + ```ts filename="Page.stories.ts" renderer="common" language="ts" // Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite) -import type { Meta, StoryObj } from '@storybook/your-framework'; +import type { Meta } from '@storybook/your-framework'; import { Page } from './Page'; @@ -59,7 +137,7 @@ export default { ``` ```ts filename="Page.stories.ts" renderer="web-components" language="ts" -import type { Meta, StoryObj } from '@storybook/web-components'; +import type { Meta } from '@storybook/web-components'; const meta: Meta = { title: 'Page', @@ -69,4 +147,3 @@ const meta: Meta = { }; export default meta; ``` - diff --git a/docs/_snippets/tags-autodocs-remove-story.md b/docs/_snippets/tags-autodocs-remove-story.md index 70f036a52755..d50ed675de30 100644 --- a/docs/_snippets/tags-autodocs-remove-story.md +++ b/docs/_snippets/tags-autodocs-remove-story.md @@ -18,6 +18,38 @@ export const UndocumentedStory: Story = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], + }); +</script> + +<!--👇 Removes this story from auto-generated documentation --> +<Story name="UndocumentedStory" tags={['!autodocs']} /> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], +}; + +export const UndocumentedStory = { + // 👇 Removes this story from auto-generated documentation + tags: ['!autodocs'], +}; +``` + ```js filename="Button.stories.js" renderer="common" language="js" import { Button } from './Button'; @@ -33,6 +65,43 @@ export const UndocumentedStory = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], + }); +</script> + +<!--👇 Removes this story from auto-generated documentation --> +<Story name="UndocumentedStory" tags={['!autodocs']} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], +} satisfies Meta<typeof Button>; +export default meta; + +type Story = StoryObj<typeof meta>; + +export const UndocumentedStory: Story = { + // 👇 Removes this story from auto-generated documentation + tags: ['!autodocs'], +}; +``` + ```ts filename="Button.stories.ts" renderer="common" language="ts-4-9" // Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite) import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -54,6 +123,43 @@ export const UndocumentedStory: Story = { }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], + }); +</script> + +<!--👇 Removes this story from auto-generated documentation --> +<Story name="UndocumentedStory" tags={['!autodocs']} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, + //👇 Enables auto-generated documentation for this component and includes all stories in this file + tags: ['autodocs'], +}; +export default meta; + +type Story = StoryObj<typeof Button>; + +export const UndocumentedStory: Story = { + // 👇 Removes this story from auto-generated documentation + tags: ['!autodocs'], +}; +``` + ```ts filename="Button.stories.ts" renderer="common" language="ts" // Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite) import type { Meta, StoryObj } from '@storybook/your-framework'; @@ -107,4 +213,3 @@ export const UndocumentedStory: Story = { tags: ['!autodocs'], }; ``` - diff --git a/docs/_snippets/tags-combo-example.md b/docs/_snippets/tags-combo-example.md index 2a5d3041103d..26c529261071 100644 --- a/docs/_snippets/tags-combo-example.md +++ b/docs/_snippets/tags-combo-example.md @@ -22,17 +22,14 @@ export const Variant2: Story = { args: { variant: 2 }, }; -// Etc... - export const Combo: Story = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], render: () => ({ template: ` <div> - <demo-button variant={1}> - <demo-button variant={2}> - {/* Etc... */} + <demo-button [variant]="1"></demo-button> + <demo-button [variant]="2"></demo-button> </div> `, }), @@ -58,16 +55,13 @@ export const Variant2 = { args: { variant: 2 }, }; -// Etc... - export const Combo = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], render: () => ( <> - <Button variant={1}> - <Button variant={2}> - {/* Etc... */} + <Button variant={1} /> + <Button variant={2} /> </> ), }; @@ -97,16 +91,13 @@ export const Variant2: Story = { args: { variant: 2 }, }; -// Etc... - export const Combo: Story = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], render: () => ( <> - <Button variant={1}> - <Button variant={2}> - {/* Etc... */} + <Button variant={1} /> + <Button variant={2} /> </> ), }; @@ -136,16 +127,13 @@ export const Variant2: Story = { args: { variant: 2 }, }; -// Etc... - export const Combo: Story = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], render: () => ( <> - <Button variant={1}> - <Button variant={2}> - {/* Etc... */} + <Button variant={1} /> + <Button variant={2} /> </> ), }; @@ -170,16 +158,13 @@ export const Variant2 = { args: { variant: 2 }, }; -// Etc... - export const Combo = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], render: () => ( <> - <Button variant={1}> - <Button variant={2}> - {/* Etc... */} + <Button variant={1} /> + <Button variant={2} /> </> ), }; @@ -209,16 +194,13 @@ export const Variant2: Story = { args: { variant: 2 }, }; -// Etc... - export const Combo: Story = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], render: () => ( <> - <Button variant={1}> - <Button variant={2}> - {/* Etc... */} + <Button variant={1} /> + <Button variant={2} /> </> ), }; @@ -248,21 +230,111 @@ export const Variant2: Story = { args: { variant: 2 }, }; -// Etc... - export const Combo: Story = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], render: () => ( <> - <Button variant={1}> - <Button variant={2}> - {/* Etc... */} + <Button variant={1} /> + <Button variant={2} /> </> ), }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + import { Button } from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<!-- 👇 This story will not appear in Storybook's sidebar or docs page --> +<Story + name="Variant1" + tags={['!dev', '!autodocs']} + args={{ variant: 1 }} +/> + +<!-- 👇 This story will not appear in Storybook's sidebar or docs page --> +<Story + name="Variant2" + tags={['!dev', '!autodocs']} + args={{ variant: 2 }} +/> + +<!-- 👇 This story should not be tested, but will appear in the sidebar and docs page --> +<Story name="Combo" tags={['!test']}> + <Button variant={1}> + <Button variant={2}> +</Story> +``` + +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + import { Button } from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<!-- 👇 This story will not appear in Storybook's sidebar or docs page --> +<Story + name="Variant1" + tags={['!dev', '!autodocs']} + args={{ variant: 1 }} +/> + +<!-- 👇 This story will not appear in Storybook's sidebar or docs page --> +<Story + name="Variant2" + tags={['!dev', '!autodocs']} + args={{ variant: 2 }} +/> + +<!-- 👇 This story should not be tested, but will appear in the sidebar and docs page --> +<Story name="Combo" tags={['!test']}> + <Button variant={1} /> + <Button variant={2} /> +</Story> +``` + +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + import { Button } from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + }); +</script> + +<!-- 👇 This story will not appear in Storybook's sidebar or docs page --> +<Story + name="Variant1" + tags={['!dev', '!autodocs']} + args={{ variant: 1 }} +/> + +<!-- 👇 This story will not appear in Storybook's sidebar or docs page --> +<Story + name="Variant2" + tags={['!dev', '!autodocs']} + args={{ variant: 2 }} +/> + +<!-- 👇 This story should not be tested, but will appear in the sidebar and docs page --> +<Story name="Combo" tags={['!test']}> + <Button variant={1} /> + <Button variant={2} /> +</Story> +``` + ```js filename="Button.stories.js" renderer="vue" language="js" import { Button } from './Button'; @@ -282,8 +354,6 @@ export const Variant2 = { args: { variant: 2 }, }; -// Etc... - export const Combo = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], @@ -291,9 +361,8 @@ export const Combo = { components: { Button }, template: ` <div> - <Button variant={1}> - <Button variant={2}> - {/* Etc... */} + <Button :variant="1" /> + <Button :variant="2" /> </div> `, }), @@ -324,8 +393,6 @@ export const Variant2: Story = { args: { variant: 2 }, }; -// Etc... - export const Combo: Story = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], @@ -333,9 +400,8 @@ export const Combo: Story = { components: { Button }, template: ` <div> - <Button variant={1}> - <Button variant={2}> - {/* Etc... */} + <Button :variant="1" /> + <Button :variant="2" /> </div> `, }), @@ -366,8 +432,6 @@ export const Variant2: Story = { args: { variant: 2 }, }; -// Etc... - export const Combo: Story = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], @@ -375,16 +439,15 @@ export const Combo: Story = { components: { Button }, template: ` <div> - <Button variant={1}> - <Button variant={2}> - {/* Etc... */} + <Button :variant="1" /> + <Button :variant="2" /> </div> `, }), }; ``` -```ts filename="Button.stories.ts" renderer="web-components" language="js" +```ts filename="Button.stories.js" renderer="web-components" language="js" import { html } from 'lit'; export default { @@ -404,16 +467,13 @@ export const Variant2 = { args: { variant: 2 }, }; -// Etc... - export const Combo = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], render: () => html` <div> - <demo-button variant="1"> - <demo-button variant="2"> - {/* Etc... */} + <demo-button variant="1" /> + <demo-button variant="2" /> </div> `, }; @@ -443,18 +503,14 @@ export const Variant2: Story = { args: { variant: 2 }, }; -// Etc... - export const Combo: Story = { // 👇 This story should not be tested, but will appear in the sidebar and docs page tags: ['!test'], render: () => html` <div> - <demo-button variant="1"> - <demo-button variant="2"> - {/* Etc... */} + <demo-button variant="1" /> + <demo-button variant="2" /> </div> `, }; ``` - diff --git a/docs/_snippets/tags-docs-only-in-meta.md b/docs/_snippets/tags-docs-only-in-meta.md index f602b0e1b9bc..dfadf65125c5 100644 --- a/docs/_snippets/tags-docs-only-in-meta.md +++ b/docs/_snippets/tags-docs-only-in-meta.md @@ -5,60 +5,162 @@ import { Button } from './Button'; const meta: Meta<Button> = { component: Button, - /** - * 👇 All stories in this file will: - * - Be included in the docs page - * - Not appear in Storybook's sidebar + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar */ tags: ['autodocs', '!dev'], }; export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar + */ + tags: ['autodocs', '!dev'], + }); +</script> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar + */ + tags: ['autodocs', '!dev'], +}; +``` + ```js filename="Button.stories.js" renderer="common" language="js" import { Button } from './Button'; export default { component: Button, - /** - * 👇 All stories in this file will: - * - Be included in the docs page - * - Not appear in Storybook's sidebar + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar */ tags: ['autodocs', '!dev'], }; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar + */ + tags: ['autodocs', '!dev'], + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar + */ + tags: ['autodocs', '!dev'], +} satisfies Meta<typeof Button>; +export default meta; +``` + ```ts filename="Button.stories.ts" renderer="common" language="ts-4-9" // Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite) -import type { Meta, StoryObj } from '@storybook/your-framework'; +import type { Meta } from '@storybook/your-framework'; import { Button } from './Button'; const meta = { component: Button, - /** - * 👇 All stories in this file will: - * - Be included in the docs page - * - Not appear in Storybook's sidebar + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar */ tags: ['autodocs', '!dev'], } satisfies Meta<typeof Button>; export default meta; ``` +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar + */ + tags: ['autodocs', '!dev'], + }); +</script> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar + */ + tags: ['autodocs', '!dev'], +}; +export default meta; +``` + ```ts filename="Button.stories.ts" renderer="common" language="ts" // Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite) -import type { Meta, StoryObj } from '@storybook/your-framework'; +import type { Meta } from '@storybook/your-framework'; import { Button } from './Button'; const meta: Meta<typeof Button> = { component: Button, - /** - * 👇 All stories in this file will: - * - Be included in the docs page - * - Not appear in Storybook's sidebar + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar */ tags: ['autodocs', '!dev'], }; @@ -69,10 +171,10 @@ export default meta; export default { title: 'Button', component: 'demo-button', - /** - * 👇 All stories in this file will: - * - Be included in the docs page - * - Not appear in Storybook's sidebar + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar */ tags: ['autodocs', '!dev'], }; @@ -84,13 +186,12 @@ import type { Meta, StoryObj } from '@storybook/web-components'; const meta: Meta = { title: 'Button', component: 'demo-button', - /** - * 👇 All stories in this file will: - * - Be included in the docs page - * - Not appear in Storybook's sidebar + /* + * All stories in this file will: + * - Be included in the docs page + * - Not appear in Storybook's sidebar */ tags: ['autodocs', '!dev'], }; export default meta; ``` - diff --git a/docs/_snippets/tags-in-meta-and-story.md b/docs/_snippets/tags-in-meta-and-story.md index fb7cdcd14f97..d0f262f2d6f7 100644 --- a/docs/_snippets/tags-in-meta-and-story.md +++ b/docs/_snippets/tags-in-meta-and-story.md @@ -5,25 +5,79 @@ import { Button } from './Button'; const meta: Meta<Button> = { component: Button, - /** - * 👇 All stories in this file will have these tags applied: - * - autodocs - * - dev (implicit default, inherited from preview) - * - test (implicit default, inherited from preview) + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) */ tags: ['autodocs'], }; -export default meta; +export default meta; type Story = StoryObj<Button>; export const ExperimentalFeatureStory: Story = { - /** - * 👇 This particular story will have these tags applied: - * - experimental - * - autodocs (inherited from meta) - * - dev (inherited from meta) - * - test (inherited from meta) + /* + * This particular story will have these tags applied: + * - experimental + * - autodocs (inherited from meta) + * - dev (inherited from meta) + * - test (inherited from meta) + */ + tags: ['experimental'], +}; +``` + +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) + */ + tags: ['autodocs'], + }); +</script> + +<!-- + This particular story will have these tags applied: + - experimental + - autodocs (inherited from meta) + - dev (inherited from meta) + - test (inherited from meta) +--> +<Story name="ExperimentalFeatureStory" tags={['experimental']} /> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) + */ + tags: ['autodocs'], +}; + +export const ExperimentalFeatureStory = { + /* + * This particular story will have these tags applied: + * - experimental + * - autodocs (inherited from meta) + * - dev (inherited from meta) + * - test (inherited from meta) */ tags: ['experimental'], }; @@ -34,22 +88,81 @@ import { Button } from './Button'; export default { component: Button, - /** - * 👇 All stories in this file will have these tags applied: - * - autodocs - * - dev (implicit default, inherited from preview) - * - test (implicit default, inherited from preview) + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) */ tags: ['autodocs'], }; export const ExperimentalFeatureStory = { - /** - * 👇 This particular story will have these tags applied: - * - experimental - * - autodocs (inherited from meta) - * - dev (inherited from meta) - * - test (inherited from meta) + /* + * This particular story will have these tags applied: + * - experimental + * - autodocs (inherited from meta) + * - dev (inherited from meta) + * - test (inherited from meta) + */ + tags: ['experimental'], +}; +``` + +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) + */ + tags: ['autodocs'], + }); +</script> + +<!-- + This particular story will have these tags applied: + - experimental + - autodocs (inherited from meta) + - dev (inherited from meta) + - test (inherited from meta) +--> +<Story name="ExperimentalFeatureStory" tags={['experimental']} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) + */ + tags: ['autodocs'], +} satisfies Meta<typeof Button>; + +export default meta; +type Story = StoryObj<typeof meta>; + +export const ExperimentalFeatureStory: Story = { + /* + * This particular story will have these tags applied: + * - experimental + * - autodocs (inherited from meta) + * - dev (inherited from meta) + * - test (inherited from meta) */ tags: ['experimental'], }; @@ -63,25 +176,84 @@ import { Button } from './Button'; const meta = { component: Button, - /** - * 👇 All stories in this file will have these tags applied: - * - autodocs - * - dev (implicit default, inherited from preview) - * - test (implicit default, inherited from preview) + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) */ tags: ['autodocs'], } satisfies Meta<typeof Button>; -export default meta; +export default meta; type Story = StoryObj<typeof meta>; export const ExperimentalFeatureStory: Story = { - /** - * 👇 This particular story will have these tags applied: - * - experimental - * - autodocs (inherited from meta) - * - dev (inherited from meta) - * - test (inherited from meta) + /* + * This particular story will have these tags applied: + * - experimental + * - autodocs (inherited from meta) + * - dev (inherited from meta) + * - test (inherited from meta) + */ + tags: ['experimental'], +}; +``` + +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) + */ + tags: ['autodocs'], + }); +</script> + +<!-- + This particular story will have these tags applied: + - experimental + - autodocs (inherited from meta) + - dev (inherited from meta) + - test (inherited from meta) +--> +<Story name="ExperimentalFeatureStory" tags={['experimental']} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) + */ + tags: ['autodocs'], +}; + +export default meta; +type Story = StoryObj<typeof Button>; + +export const ExperimentalFeatureStory: Story = { + /* + * This particular story will have these tags applied: + * - experimental + * - autodocs (inherited from meta) + * - dev (inherited from meta) + * - test (inherited from meta) */ tags: ['experimental'], }; @@ -95,25 +267,25 @@ import { Button } from './Button'; const meta: Meta<typeof Button> = { component: Button, - /** - * 👇 All stories in this file will have these tags applied: - * - autodocs - * - dev (implicit default, inherited from preview) - * - test (implicit default, inherited from preview) + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) */ tags: ['autodocs'], }; -export default meta; +export default meta; type Story = StoryObj<typeof Button>; export const ExperimentalFeatureStory: Story = { - /** - * 👇 This particular story will have these tags applied: - * - experimental - * - autodocs (inherited from meta) - * - dev (inherited from meta) - * - test (inherited from meta) + /* + * This particular story will have these tags applied: + * - experimental + * - autodocs (inherited from meta) + * - dev (inherited from meta) + * - test (inherited from meta) */ tags: ['experimental'], }; @@ -123,22 +295,22 @@ export const ExperimentalFeatureStory: Story = { export default { title: 'Button', component: 'demo-button', - /** - * 👇 All stories in this file will have these tags applied: - * - autodocs - * - dev (implicit default, inherited from preview) - * - test (implicit default, inherited from preview) + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) */ tags: ['autodocs'], }; export const ExperimentalFeatureStory = { - /** - * 👇 This particular story will have these tags applied: - * - experimental - * - autodocs (inherited from meta) - * - dev (inherited from meta) - * - test (inherited from meta) + /* + * This particular story will have these tags applied: + * - experimental + * - autodocs (inherited from meta) + * - dev (inherited from meta) + * - test (inherited from meta) */ tags: ['experimental'], }; @@ -150,27 +322,26 @@ import type { Meta, StoryObj } from '@storybook/web-components'; const meta: Meta = { title: 'Button', component: 'demo-button', - /** - * 👇 All stories in this file will have these tags applied: - * - autodocs - * - dev (implicit default, inherited from preview) - * - test (implicit default, inherited from preview) + /* + * All stories in this file will have these tags applied: + * - autodocs + * - dev (implicit default, inherited from preview) + * - test (implicit default, inherited from preview) */ tags: ['autodocs'], }; -export default meta; +export default meta; type Story = StoryObj; export const ExperimentalFeatureStory: Story = { - /** - * 👇 This particular story will have these tags applied: - * - experimental - * - autodocs (inherited from meta) - * - dev (inherited from meta) - * - test (inherited from meta) + /* + * This particular story will have these tags applied: + * - experimental + * - autodocs (inherited from meta) + * - dev (inherited from meta) + * - test (inherited from meta) */ tags: ['experimental'], }; ``` - diff --git a/docs/_snippets/tags-in-preview.md b/docs/_snippets/tags-in-preview.md index 7d9aeff2964d..de110347bbe0 100644 --- a/docs/_snippets/tags-in-preview.md +++ b/docs/_snippets/tags-in-preview.md @@ -1,11 +1,11 @@ ```js filename=".storybook/preview.js" renderer="common" language="js" export default { // ...rest of preview - /** - * 👇 All stories in your project will have these tags applied: - * - autodocs - * - dev (implicit default) - * - test (implicit default) + /* + * All stories in your project will have these tags applied: + * - autodocs + * - dev (implicit default) + * - test (implicit default) */ tags: ['autodocs'], }; @@ -17,15 +17,14 @@ import type { Preview } from '@storybook/your-renderer'; const preview: Preview = { // ...rest of preview - /** - * 👇 All stories in your project will have these tags applied: - * - autodocs - * - dev (implicit default) - * - test (implicit default) + /* + * All stories in your project will have these tags applied: + * - autodocs + * - dev (implicit default) + * - test (implicit default) */ tags: ['autodocs'], }; export default preview; ``` - diff --git a/docs/_snippets/tags-remove-in-story.md b/docs/_snippets/tags-remove-in-story.md index 8e94be4250c3..b48beba734f8 100644 --- a/docs/_snippets/tags-remove-in-story.md +++ b/docs/_snippets/tags-remove-in-story.md @@ -1,22 +1,51 @@ ```ts filename="Button.stories.ts" renderer="angular" language="ts" import type { Meta, StoryObj } from '@storybook/angular'; -import { Button } from './Button'; +import { Button } from './Button.component'; const meta: Meta<Button> = { component: Button, // 👇 Applies to all stories in this file tags: ['stable'], }; -export default meta; +export default meta; type Story = StoryObj<Button>; export const ExperimentalFeatureStory: Story = { - /** - * 👇 For this particular story, remove the inherited - * `stable` tag and apply the `experimental` tag - */ + //👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag + tags: ['!stable', 'experimental'], +}; +``` + +```svelte filename="Button.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + // 👇 Applies to all stories in this file + tags: ['stable'], + }); +</script> + +<!-- 👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag --> +<Story name="ExperimentalFeatureStory" tags={['!stable', 'experimental']} /> +``` + +```js filename="Button.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import Button from './Button.svelte'; + +export default { + component: Button, + // 👇 Applies to all stories in this file + tags: ['stable'], +}; + +export const ExperimentalFeatureStory = { + //👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag tags: ['!stable', 'experimental'], }; ``` @@ -31,10 +60,44 @@ export default { }; export const ExperimentalFeatureStory = { - /** - * 👇 For this particular story, remove the inherited - * `stable` tag and apply the `experimental` tag - */ + //👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag + tags: ['!stable', 'experimental'], +}; +``` + +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + // 👇 Applies to all stories in this file + tags: ['stable'], + }); +</script> + +<!-- 👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag --> +<Story name="ExperimentalFeatureStory" tags={['!stable', 'experimental']} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta = { + component: Button, + // 👇 Applies to all stories in this file + tags: ['stable'], +} satisfies Meta<typeof Button>; + +export default meta; +type Story = StoryObj<typeof meta>; + +export const ExperimentalFeatureStory: Story = { + //👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag tags: ['!stable', 'experimental'], }; ``` @@ -55,10 +118,44 @@ export default meta; type Story = StoryObj<typeof meta>; export const ExperimentalFeatureStory: Story = { - /** - * 👇 For this particular story, remove the inherited - * `stable` tag and apply the `experimental` tag - */ + //👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag + tags: ['!stable', 'experimental'], +}; +``` + +```svelte filename="Button.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import Button from './Button.svelte'; + + const { Story } = defineMeta({ + component: Button, + // 👇 Applies to all stories in this file + tags: ['stable'], + }); +</script> + +<!-- 👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag --> +<Story name="ExperimentalFeatureStory" tags={['!stable', 'experimental']} /> +``` + +```ts filename="Button.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/svelte'; + +import Button from './Button.svelte'; + +const meta: Meta<typeof Button> = { + component: Button, + // 👇 Applies to all stories in this file + tags: ['stable'], +}; + +export default meta; +type Story = StoryObj<typeof Button>; + +export const ExperimentalFeatureStory: Story = { + //👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag tags: ['!stable', 'experimental'], }; ``` @@ -74,15 +171,12 @@ const meta: Meta<typeof Button> = { // 👇 Applies to all stories in this file tags: ['stable'], }; -export default meta; +export default meta; type Story = StoryObj<typeof Button>; export const ExperimentalFeatureStory: Story = { - /** - * 👇 For this particular story, remove the inherited - * `stable` tag and apply the `experimental` tag - */ + //👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag tags: ['!stable', 'experimental'], }; ``` @@ -96,10 +190,7 @@ export default { }; export const ExperimentalFeatureStory = { - /** - * 👇 For this particular story, remove the inherited - * `stable` tag and apply the `experimental` tag - */ + //👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag tags: ['!stable', 'experimental'], }; ``` @@ -113,16 +204,12 @@ const meta: Meta = { // 👇 Applies to all stories in this file tags: ['stable'], }; -export default meta; +export default meta; type Story = StoryObj; export const ExperimentalFeatureStory: Story = { - /** - * 👇 For this particular story, remove the inherited - * `stable` tag and apply the `experimental` tag - */ + //👇 For this particular story, remove the inherited `stable` tag and apply the `experimental` tag tags: ['!stable', 'experimental'], }; ``` - diff --git a/docs/_snippets/test-runner-a11y-config.md b/docs/_snippets/test-runner-a11y-config.md index de01dce91393..14824205701b 100644 --- a/docs/_snippets/test-runner-a11y-config.md +++ b/docs/_snippets/test-runner-a11y-config.md @@ -44,4 +44,3 @@ const config: TestRunnerConfig = { export default config; ``` - diff --git a/docs/_snippets/test-runner-a11y-disable.md b/docs/_snippets/test-runner-a11y-disable.md index 4acc306f653c..e1b176bc4a0f 100644 --- a/docs/_snippets/test-runner-a11y-disable.md +++ b/docs/_snippets/test-runner-a11y-disable.md @@ -61,4 +61,3 @@ const config: TestRunnerConfig = { export default config; ``` - diff --git a/docs/_snippets/test-runner-auth.md b/docs/_snippets/test-runner-auth.md index 7712fc4b47bf..3733b0a8ca52 100644 --- a/docs/_snippets/test-runner-auth.md +++ b/docs/_snippets/test-runner-auth.md @@ -23,4 +23,3 @@ const config: TestRunnerConfig = { export default config; ``` - diff --git a/docs/_snippets/test-runner-axe-playwright.md b/docs/_snippets/test-runner-axe-playwright.md index b9eb9e8f7162..2f09c11027a1 100644 --- a/docs/_snippets/test-runner-axe-playwright.md +++ b/docs/_snippets/test-runner-axe-playwright.md @@ -9,4 +9,3 @@ pnpm add --save-dev axe-playwright ```shell renderer="common" language="js" packageManager="yarn" yarn add --dev axe-playwright ``` - diff --git a/docs/_snippets/test-runner-config-serializer.md b/docs/_snippets/test-runner-config-serializer.md index 460b1da8c524..ea1110eecef0 100644 --- a/docs/_snippets/test-runner-config-serializer.md +++ b/docs/_snippets/test-runner-config-serializer.md @@ -14,4 +14,3 @@ const config = { export default config; ``` - diff --git a/docs/_snippets/test-runner-config-snapshot-resolver.md b/docs/_snippets/test-runner-config-snapshot-resolver.md index e4bf8639d2d8..634d9303c607 100644 --- a/docs/_snippets/test-runner-config-snapshot-resolver.md +++ b/docs/_snippets/test-runner-config-snapshot-resolver.md @@ -11,4 +11,3 @@ const config = { export default config; ``` - diff --git a/docs/_snippets/test-runner-coverage.md b/docs/_snippets/test-runner-coverage.md index 06200c3930fe..42c44817f6f9 100644 --- a/docs/_snippets/test-runner-coverage.md +++ b/docs/_snippets/test-runner-coverage.md @@ -9,4 +9,3 @@ pnpm run test-storybook --coverage ```shell renderer="common" language="js" packageManager="yarn" yarn test-storybook --coverage ``` - diff --git a/docs/_snippets/test-runner-custom-page-viewport.md b/docs/_snippets/test-runner-custom-page-viewport.md index d15eaa4d0da3..bc6342e0d86c 100644 --- a/docs/_snippets/test-runner-custom-page-viewport.md +++ b/docs/_snippets/test-runner-custom-page-viewport.md @@ -18,7 +18,7 @@ module.exports = { // Converts the viewport size from percentages to numbers [screen]: parseInt(size), }), - {}, + {} ); // Configures the Playwright page to use the viewport size page.setViewportSize(viewportSize); @@ -51,7 +51,7 @@ const config: TestRunnerConfig = { // Converts the viewport size from percentages to numbers [screen]: parseInt(size), }), - {}, + {} ); // Configures the Playwright page to use the viewport size page.setViewportSize(viewportSize); @@ -63,4 +63,3 @@ const config: TestRunnerConfig = { export default config; ``` - diff --git a/docs/_snippets/test-runner-custom-snapshot-resolver.md b/docs/_snippets/test-runner-custom-snapshot-resolver.md index 0fd336b41b18..dba1c8c745fd 100644 --- a/docs/_snippets/test-runner-custom-snapshot-resolver.md +++ b/docs/_snippets/test-runner-custom-snapshot-resolver.md @@ -15,4 +15,3 @@ export default { testPathForConsistencyCheck: 'example.storyshot', }; ``` - diff --git a/docs/_snippets/test-runner-custom-snapshot-serializer.md b/docs/_snippets/test-runner-custom-snapshot-serializer.md index dc544953701f..ced9e33f3731 100644 --- a/docs/_snippets/test-runner-custom-snapshot-serializer.md +++ b/docs/_snippets/test-runner-custom-snapshot-serializer.md @@ -19,4 +19,3 @@ module.exports = { }, }; ``` - diff --git a/docs/_snippets/test-runner-dom-snapshot-testing.md b/docs/_snippets/test-runner-dom-snapshot-testing.md index 6fb40633207b..f17021eeedb3 100644 --- a/docs/_snippets/test-runner-dom-snapshot-testing.md +++ b/docs/_snippets/test-runner-dom-snapshot-testing.md @@ -23,4 +23,3 @@ const config: TestRunnerConfig = { export default config; ``` - diff --git a/docs/_snippets/test-runner-eject-config.md b/docs/_snippets/test-runner-eject-config.md index cd5e7cf708a6..133a87c294df 100644 --- a/docs/_snippets/test-runner-eject-config.md +++ b/docs/_snippets/test-runner-eject-config.md @@ -9,4 +9,3 @@ pnpm run test-storybook --eject ```sh renderer="common" language="js" packageManager="yarn" yarn test-storybook --eject ``` - diff --git a/docs/_snippets/test-runner-execute-with-flags.md b/docs/_snippets/test-runner-execute-with-flags.md index 922856044f9c..a4f710f89612 100644 --- a/docs/_snippets/test-runner-execute-with-flags.md +++ b/docs/_snippets/test-runner-execute-with-flags.md @@ -9,4 +9,3 @@ pnpm run test-storybook --watch ```shell renderer="common" language="js" packageManager="yarn" yarn test-storybook --watch ``` - diff --git a/docs/_snippets/test-runner-execute.md b/docs/_snippets/test-runner-execute.md index a99bf77236b6..af9470fd2999 100644 --- a/docs/_snippets/test-runner-execute.md +++ b/docs/_snippets/test-runner-execute.md @@ -9,4 +9,3 @@ pnpm run test-storybook ```shell renderer="common" language="js" packageManager="yarn" yarn test-storybook ``` - diff --git a/docs/_snippets/test-runner-helper-function.md b/docs/_snippets/test-runner-helper-function.md index c88743d7b1f4..8d600e464560 100644 --- a/docs/_snippets/test-runner-helper-function.md +++ b/docs/_snippets/test-runner-helper-function.md @@ -62,4 +62,3 @@ const config: TestRunnerConfig = { export default config; ``` - diff --git a/docs/_snippets/test-runner-hooks-example.md b/docs/_snippets/test-runner-hooks-example.md index 77caddb91dd6..a055ab35f9b5 100644 --- a/docs/_snippets/test-runner-hooks-example.md +++ b/docs/_snippets/test-runner-hooks-example.md @@ -47,4 +47,3 @@ const config: TestRunnerConfig = { export default config; ``` - diff --git a/docs/_snippets/test-runner-image-snapshot-testing.md b/docs/_snippets/test-runner-image-snapshot-testing.md index 1f19377922a4..03d1a0c1faa8 100644 --- a/docs/_snippets/test-runner-image-snapshot-testing.md +++ b/docs/_snippets/test-runner-image-snapshot-testing.md @@ -49,4 +49,3 @@ const config: TestRunnerConfig = { }; export default config; ``` - diff --git a/docs/_snippets/test-runner-install.md b/docs/_snippets/test-runner-install.md index 3fe38c3dd3f8..aa64481319fb 100644 --- a/docs/_snippets/test-runner-install.md +++ b/docs/_snippets/test-runner-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/test-runner ```shell renderer="common" language="js" packageManager="yarn" yarn add --dev @storybook/test-runner ``` - diff --git a/docs/_snippets/test-runner-local-build-workflow.md b/docs/_snippets/test-runner-local-build-workflow.md index b429c34cfaeb..c5e72c546b82 100644 --- a/docs/_snippets/test-runner-local-build-workflow.md +++ b/docs/_snippets/test-runner-local-build-workflow.md @@ -1,8 +1,8 @@ -```yml renderer="common" language="ts" tabTitle="yml" -# .github/workflows/storybook-tests.yml - +```yml filename=".github/workflows/storybook-tests.yml" renderer="common" language="ts" tabTitle="yml" name: 'Storybook Tests' + on: push + jobs: test: timeout-minutes: 60 @@ -24,4 +24,3 @@ jobs: "npx http-server storybook-static --port 6006 --silent" \ "npx wait-on tcp:127.0.0.1:6006 && yarn test-storybook" ``` - diff --git a/docs/_snippets/test-runner-no-index-json.md b/docs/_snippets/test-runner-no-index-json.md index c84436d8ee80..6f576c6494c8 100644 --- a/docs/_snippets/test-runner-no-index-json.md +++ b/docs/_snippets/test-runner-no-index-json.md @@ -9,4 +9,3 @@ pnpm run test-storybook --no-index-json ```shell renderer="common" language="js" packageManager="yarn" yarn test-storybook --no-index-json ``` - diff --git a/docs/_snippets/test-runner-snapshot-resolver-custom-directory.md b/docs/_snippets/test-runner-snapshot-resolver-custom-directory.md index b76fb087f375..023ec13fb63d 100644 --- a/docs/_snippets/test-runner-snapshot-resolver-custom-directory.md +++ b/docs/_snippets/test-runner-snapshot-resolver-custom-directory.md @@ -16,4 +16,3 @@ export default { testPathForConsistencyCheck: 'example', }; ``` - diff --git a/docs/_snippets/test-runner-tags-include.md b/docs/_snippets/test-runner-tags-include.md index 60be0f9361c7..4000cde41e51 100644 --- a/docs/_snippets/test-runner-tags-include.md +++ b/docs/_snippets/test-runner-tags-include.md @@ -17,4 +17,3 @@ const config: TestRunnerConfig = { export default config; ``` - diff --git a/docs/_snippets/test-runner-waitpageready.md b/docs/_snippets/test-runner-waitpageready.md index 0601ff1aed77..b608c4180388 100644 --- a/docs/_snippets/test-runner-waitpageready.md +++ b/docs/_snippets/test-runner-waitpageready.md @@ -51,4 +51,3 @@ const config: TestRunnerConfig = { export default config; ``` - diff --git a/docs/_snippets/test-runner-with-deploy-event-workflow.md b/docs/_snippets/test-runner-with-deploy-event-workflow.md index 61ece061f2a6..201aa115692b 100644 --- a/docs/_snippets/test-runner-with-deploy-event-workflow.md +++ b/docs/_snippets/test-runner-with-deploy-event-workflow.md @@ -1,8 +1,8 @@ -```yml renderer="common" language="ts" tabTitle="yml" -# .github/workflows/storybook-tests.yml - +```yml filename=".github/workflows/storybook-tests.yml" renderer="common" language="ts" tabTitle="yml" name: Storybook Tests + on: deployment_status + jobs: test: timeout-minutes: 60 @@ -22,4 +22,3 @@ jobs: env: TARGET_URL: '${{ github.event.deployment_status.target_url }}' ``` - diff --git a/docs/_snippets/test-runner-with-index-json.md b/docs/_snippets/test-runner-with-index-json.md index 578e05423cf9..c364b50f6c25 100644 --- a/docs/_snippets/test-runner-with-index-json.md +++ b/docs/_snippets/test-runner-with-index-json.md @@ -9,4 +9,3 @@ pnpm run test-storybook --index-json ```shell renderer="common" language="js" packageManager="yarn" yarn test-storybook --index-json ``` - diff --git a/docs/_snippets/typed-csf-file.md b/docs/_snippets/typed-csf-file.md index 41bac1d67f61..02e76c156f89 100644 --- a/docs/_snippets/typed-csf-file.md +++ b/docs/_snippets/typed-csf-file.md @@ -81,4 +81,3 @@ export const Primary: StoryObj = { }, }; ``` - diff --git a/docs/_snippets/upgrade-command-specific-version.md b/docs/_snippets/upgrade-command-specific-version.md index edd9ce329bc4..606cd1d64610 100644 --- a/docs/_snippets/upgrade-command-specific-version.md +++ b/docs/_snippets/upgrade-command-specific-version.md @@ -1,4 +1,4 @@ -```shell renderer="common" language="js" packageManager="npx" +```shell renderer="common" language="js" packageManager="npm" npx storybook@7.6.6 upgrade ``` @@ -9,4 +9,3 @@ pnpm dlx storybook@7.6.6 upgrade ```shell renderer="common" language="js" packageManager="yarn" yarn dlx storybook@7.6.6 upgrade ``` - diff --git a/docs/_snippets/vue-jest-optional-config-scripts.md b/docs/_snippets/vue-jest-optional-config-scripts.md deleted file mode 100644 index 16e373f80638..000000000000 --- a/docs/_snippets/vue-jest-optional-config-scripts.md +++ /dev/null @@ -1,16 +0,0 @@ -```json renderer="vue" language="js" tabTitle="jest" -{ - "scripts": { - "test": "jest --setupFiles ./setupFile.js" - } -} -``` - -```json renderer="vue" language="ts" tabTitle="jest" -{ - "scripts": { - "test": "jest --setupFiles ./setupFile.js" - } -} -``` - diff --git a/docs/_snippets/vue-vite-framework-options.md b/docs/_snippets/vue-vite-framework-options.md new file mode 100644 index 000000000000..ce87365d5614 --- /dev/null +++ b/docs/_snippets/vue-vite-framework-options.md @@ -0,0 +1,25 @@ +```js filename=".storybook/main.js" renderer="vue" language="js" +export default { + framework: { + name: '@storybook/vue3-vite', + options: { + docgen: 'vue-component-meta', + }, + }, +}; +``` + +```ts filename=".storybook/main.ts" renderer="vue" language="ts" +import type { StorybookConfig } from '@storybook/vue3-vite'; + +const config: StorybookConfig = { + framework: { + name: '@storybook/vue3-vite', + options: { + docgen: 'vue-component-meta', + }, + }, +}; + +export default config; +``` diff --git a/docs/_snippets/vue-webpack5-framework-options.md b/docs/_snippets/vue-webpack5-framework-options.md new file mode 100644 index 000000000000..7661567b00e9 --- /dev/null +++ b/docs/_snippets/vue-webpack5-framework-options.md @@ -0,0 +1,25 @@ +```js filename=".storybook/main.js" renderer="vue" language="js" +export default { + framework: { + name: '@storybook/vue3-webpack5', + options: { + // ... + }, + }, +}; +``` + +```ts filename=".storybook/main.ts" renderer="vue" language="ts" +import type { StorybookConfig } from '@storybook/vue-webpack5'; + +const config: StorybookConfig = { + framework: { + name: '@storybook/vue3-webpack5', + options: { + // ... + }, + }, +}; + +export default config; +``` diff --git a/docs/_snippets/vue3-vite-add-framework.md b/docs/_snippets/vue3-vite-add-framework.md index 2d4e13180f0a..5c617faae463 100644 --- a/docs/_snippets/vue3-vite-add-framework.md +++ b/docs/_snippets/vue3-vite-add-framework.md @@ -15,4 +15,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/vue3-vite-install.md b/docs/_snippets/vue3-vite-install.md index f2ea6a46843c..45a4b77c3dcd 100644 --- a/docs/_snippets/vue3-vite-install.md +++ b/docs/_snippets/vue3-vite-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/vue3-vite ```shell renderer="vue" language="js" packageManager="yarn" yarn add --dev @storybook/vue3-vite ``` - diff --git a/docs/_snippets/vue3-webpack5-add-framework.md b/docs/_snippets/vue3-webpack5-add-framework.md index 02c792ac8262..7c83b82bd090 100644 --- a/docs/_snippets/vue3-webpack5-add-framework.md +++ b/docs/_snippets/vue3-webpack5-add-framework.md @@ -15,4 +15,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/vue3-webpack5-install.md b/docs/_snippets/vue3-webpack5-install.md index b77fa45d7b3e..55eb9006b2ca 100644 --- a/docs/_snippets/vue3-webpack5-install.md +++ b/docs/_snippets/vue3-webpack5-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/vue3-webpack5 ```shell renderer="vue" language="js" packageManager="yarn" yarn add --dev @storybook/vue3-webpack5 ``` - diff --git a/docs/_snippets/web-components-vite-add-framework.md b/docs/_snippets/web-components-vite-add-framework.md index f9a5c03598a0..140ad899ff0a 100644 --- a/docs/_snippets/web-components-vite-add-framework.md +++ b/docs/_snippets/web-components-vite-add-framework.md @@ -15,4 +15,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/web-components-vite-framework-options.md b/docs/_snippets/web-components-vite-framework-options.md new file mode 100644 index 000000000000..39946561e2d8 --- /dev/null +++ b/docs/_snippets/web-components-vite-framework-options.md @@ -0,0 +1,25 @@ +```js filename=".storybook/main.js" renderer="web-components" language="js" +export default { + framework: { + name: '@storybook/web-components-vite', + options: { + // ... + }, + }, +}; +``` + +```ts filename=".storybook/main.ts" renderer="web-components" language="ts" +import type { StorybookConfig } from '@storybook/web-components-vite'; + +const config: StorybookConfig = { + framework: { + name: '@storybook/web-components-vite', + options: { + // ... + }, + }, +}; + +export default config; +``` diff --git a/docs/_snippets/web-components-vite-install.md b/docs/_snippets/web-components-vite-install.md index 2bb35f1e280a..c1bb0f6f47d9 100644 --- a/docs/_snippets/web-components-vite-install.md +++ b/docs/_snippets/web-components-vite-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/web-components-vite ```shell renderer="web-components" language="js" packageManager="yarn" yarn add --dev @storybook/web-components-vite ``` - diff --git a/docs/_snippets/web-components-webpack5-add-framework.md b/docs/_snippets/web-components-webpack5-add-framework.md index 7df40eb92288..5fbc8b5f5abf 100644 --- a/docs/_snippets/web-components-webpack5-add-framework.md +++ b/docs/_snippets/web-components-webpack5-add-framework.md @@ -1,8 +1,7 @@ ```js filename=".storybook/main.js" renderer="web-components" language="js" export default { // ... - // framework: '@storybook/react-webpack5', 👈 Remove this - framework: '@storybook/nextjs', // 👈 Add this + framework: '@storybook/web-components-webpack5', // 👈 Add this }; ``` @@ -16,4 +15,3 @@ const config: StorybookConfig = { export default config; ``` - diff --git a/docs/_snippets/web-components-webpack5-framework-options.md b/docs/_snippets/web-components-webpack5-framework-options.md new file mode 100644 index 000000000000..e2271207d624 --- /dev/null +++ b/docs/_snippets/web-components-webpack5-framework-options.md @@ -0,0 +1,26 @@ +```js filename=".storybook/main.js" renderer="web-components" language="js" +export default { + // ... + framework: { + name: '@storybook/web-components-webpack5', + options: { + // ... + }, + }, +}; +``` + +```ts filename=".storybook/main.ts" renderer="web-components" language="ts" +import type { StorybookConfig } from '@storybook/web-components-webpack5'; + +const config: StorybookConfig = { + framework: { + name: '@storybook/web-components-webpack5', + options: { + // ... + }, + }, +}; + +export default config; +``` diff --git a/docs/_snippets/web-components-webpack5-install.md b/docs/_snippets/web-components-webpack5-install.md index 23529f1184c4..633c15e1777c 100644 --- a/docs/_snippets/web-components-webpack5-install.md +++ b/docs/_snippets/web-components-webpack5-install.md @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/web-components-webpack5 ```shell renderer="web-components" language="js" packageManager="yarn" yarn add --dev @storybook/web-components-webpack5 ``` - diff --git a/docs/_snippets/web-components-webpack5-transpilation.md b/docs/_snippets/web-components-webpack5-transpilation.md new file mode 100644 index 000000000000..5c7bf66bcecf --- /dev/null +++ b/docs/_snippets/web-components-webpack5-transpilation.md @@ -0,0 +1,33 @@ +```js filename=".storybook/main.js" renderer="web-components" language="js" +export default { + webpackFinal: async (config) => { + // Find web-components rule for extra transpilation + const webComponentsRule = config.module.rules.find( + (rule) => rule.use && rule.use.options && rule.use.options.babelrc === false + ); + // Add your own `my-library` + webComponentsRule.test.push(new RegExp(`node_modules(\\/|\\\\)my-library(.*)\\.js$`)); + + return config; + }, +}; +``` + +```ts filename=".storybook/main.ts" renderer="web-components" language="ts" +import type { StorybookConfig } from '@storybook/web-components-webpack5'; + +const config: StorybookConfig = { + webpackFinal: async (config) => { + // Find web-components rule for extra transpilation + const webComponentsRule = config.module.rules.find( + (rule) => rule.use && rule.use.options && rule.use.options.babelrc === false + ); + // Add your own `my-library` + webComponentsRule.test.push(new RegExp(`node_modules(\\/|\\\\)my-library(.*)\\.js$`)); + + return config; + }, +}; + +export default config; +``` diff --git a/docs/_snippets/your-component-with-decorator.md b/docs/_snippets/your-component-with-decorator.md index 820f72da82e5..c06d43496724 100644 --- a/docs/_snippets/your-component-with-decorator.md +++ b/docs/_snippets/your-component-with-decorator.md @@ -148,9 +148,22 @@ const meta: Meta<typeof YourComponent> = { export default meta; ``` -```js filename="YourComponent.stories.js" renderer="svelte" language="js" -import YourComponent from './YourComponent.svelte'; +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + import MarginDecorator from './MarginDecorator.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + decorators: [() => MarginDecorator], + }); +</script> +``` +```js filename="YourComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import YourComponent from './YourComponent.svelte'; import MarginDecorator from './MarginDecorator.svelte'; export default { @@ -159,41 +172,49 @@ export default { }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* YourComponent.stories.svelte */} - -<script> - import { Meta, Template } from '@storybook/addon-svelte-csf'; +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + import YourComponent from './YourComponent.svelte'; import MarginDecorator from './MarginDecorator.svelte'; - import YourComponent from './YourComponent.svelte'; + const { Story } = defineMeta({ + component: YourComponent, + decorators: [() => MarginDecorator], + }); </script> - -<meta title="YourComponent" component="{YourComponent}" /> - -<template let:args> - <MarginDecorator> - {/*👇 Your component here */} - </MarginDecorator> -</template> ``` -```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta } from '@storybook/svelte'; import YourComponent from './YourComponent.svelte'; import MarginDecorator from './MarginDecorator.svelte'; const meta = { - component: Button, + component: YourComponent, decorators: [() => MarginDecorator], -} satisfies Meta<typeof Button>; +} satisfies Meta<typeof YourComponent>; export default meta; ``` -```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts" +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + import MarginDecorator from './MarginDecorator.svelte'; + + const { Story } = defineMeta({ + component: YourComponent, + decorators: [() => MarginDecorator], + }); +</script> +``` + +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta } from '@storybook/svelte'; import YourComponent from './YourComponent.svelte'; @@ -262,4 +283,3 @@ const meta: Meta<YourComponentProps> = { }; export default meta; ``` - diff --git a/docs/_snippets/your-component.md b/docs/_snippets/your-component.md index 7ec83e1ce72a..689566b0323d 100644 --- a/docs/_snippets/your-component.md +++ b/docs/_snippets/your-component.md @@ -207,56 +207,67 @@ export const FirstStory: Story = { }; ``` -```js filename="YourComponent.stories.js" renderer="svelte" language="js" +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + //👇 This export determines where your story goes in the story list + const { Story } = defineMeta({ + component: YourComponent, + }); +</script> + +<Story + name="FirstStory" + args={{ + /*👇 The args you need here will depend on your component */ + }} +/> +``` + +```js filename="YourComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" import YourComponent from './YourComponent.svelte'; -//👇This default export determines where your story goes in the story list +//👇 This default export determines where your story goes in the story list export default { component: YourComponent, }; -/* - *👇 Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/api/csf - * to learn how to use render functions. - */ export const FirstStory = { - render: (args) => ({ - Component: YourComponent, - props: args, - }), args: { //👇 The args you need here will depend on your component }, }; ``` -```html renderer="svelte" language="ts" tabTitle="native-format" -{/* YourComponent.stories.svelte */} - -<script> - import { Meta, Template, Story } from '@storybook/addon-svelte-csf'; +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts-4-9" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; import YourComponent from './YourComponent.svelte'; -</script> - -{/*👇 The title determines where your story goes in the story list */} -<Meta title="YourComponent" component={YourComponent} argTypes={{ /* Customize your args here -depending on your component */ }} /> -<template let:args> - <button {...args} /> -</template> + //👇 This export determines where your story goes in the story list + const { Story } = defineMeta({ + component: YourComponent, + }); +</script> -<Story name="FirstStory" args={{ /* The args you need here will depend on your component */ }} /> +<Story + name="FirstStory" + args={{ + /*👇 The args you need here will depend on your component */ + }} +/> ``` -```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts-4-9" +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts-4-9" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import YourComponent from './YourComponent.svelte'; -//👇This default export determines where your story goes in the story list +//👇 This default export determines where your story goes in the story list const meta = { component: YourComponent, } satisfies Meta<typeof YourComponent>; @@ -271,12 +282,32 @@ export const FirstStory: Story = { }; ``` -```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts" +```svelte filename="YourComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" +<script module> + import { defineMeta } from '@storybook/addon-svelte-csf'; + + import YourComponent from './YourComponent.svelte'; + + //👇 This export determines where your story goes in the story list + const { Story } = defineMeta({ + component: YourComponent, + }); +</script> + +<Story + name="FirstStory" + args={{ + /*👇 The args you need here will depend on your component */ + }} +/> +``` + +```ts filename="YourComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" import type { Meta, StoryObj } from '@storybook/svelte'; import YourComponent from './YourComponent.svelte'; -//👇This default export determines where your story goes in the story list +//👇 This default export determines where your story goes in the story list const meta: Meta<typeof YourComponent> = { component: YourComponent, }; @@ -291,7 +322,7 @@ export const FirstStory: Story = { }; ``` -```js filename="YourComponent.stories.js" renderer="vue" language="js" tabTitle="3" +```js filename="YourComponent.stories.js" renderer="vue" language="js" import YourComponent from './YourComponent.vue'; //👇 This default export determines where your story goes in the story list @@ -318,9 +349,7 @@ export const FirstStory = { }; ``` -```ts filename="YourComponent.stories.js" renderer="vue" language="ts-4-9" tabTitle="3" -import type { Meta, StoryObj } from '@storybook/vue3'; - +```ts filename="YourComponent.stories.js" renderer="vue" language="ts-4-9" import YourComponent from './YourComponent.vue'; const meta = { @@ -350,7 +379,7 @@ export const Primary: Story = { }; ``` -```ts filename="YourComponent.stories.ts" renderer="vue" language="ts" tabTitle="3" +```ts filename="YourComponent.stories.ts" renderer="vue" language="ts" import type { Meta, StoryObj } from '@storybook/vue3'; import YourComponent from './YourComponent.vue'; @@ -412,4 +441,3 @@ export const FirstStory: Story = { }, }; ``` - diff --git a/docs/_snippets/your-theme.md b/docs/_snippets/your-theme.md index b491ad8b608f..85b8021fd87c 100644 --- a/docs/_snippets/your-theme.md +++ b/docs/_snippets/your-theme.md @@ -40,4 +40,3 @@ export default create({ inputBorderRadius: 2, }); ``` - diff --git a/docs/addons/addon-knowledge-base.mdx b/docs/addons/addon-knowledge-base.mdx index c2dbdb497d30..ab0ef1268d52 100644 --- a/docs/addons/addon-knowledge-base.mdx +++ b/docs/addons/addon-knowledge-base.mdx @@ -79,7 +79,7 @@ Complementing the components, also included is a set of UI primitives. Use the c When you're developing your addon as a package, you can’t use `npm link` to add it to your project. List your addon as a local dependency into your package.json: -```json +```json title="package.json" { "dependencies": { "@storybook/addon-controls": "file:///home/username/myrepo" @@ -99,7 +99,7 @@ While developing your addon, you can configure HMR (hot module replacement) to r If you're developing a standalone addon, add a new script to `package.json` with the following: -```json +```json title="package.json" { "scripts": { "start": "npm run build -- --watch" diff --git a/docs/addons/addon-migration-guide.mdx b/docs/addons/addon-migration-guide.mdx index bf1c26309f04..cc032f6f24c1 100644 --- a/docs/addons/addon-migration-guide.mdx +++ b/docs/addons/addon-migration-guide.mdx @@ -15,7 +15,7 @@ We sincerely appreciate the dedication and effort addon creators put into keepin Begin by updating your Storybook dependencies. Use the `next` tag for pre-release versions, `latest` for the most recent stable release, or specify the version directly. -```jsonc +```jsonc title="package.json" { "dependencies": { "@storybook/client-logger": "next" // or "latest", or "^8.0.0" diff --git a/docs/addons/addon-types.mdx b/docs/addons/addon-types.mdx index 8b2aef939ff8..5c540cd0bdb0 100644 --- a/docs/addons/addon-types.mdx +++ b/docs/addons/addon-types.mdx @@ -40,11 +40,7 @@ Use this boilerplate code to add a new `button` to Storybook's Toolbar: {/* prettier-ignore-end */} <Callout variant="info"> - The `match` property allows you to conditionally render your toolbar addon, [based on the current view](./writing-addons.mdx#conditionally-render-the-addon). - - <hr style={{ margin: '-0.75em 0 0.75em' }} /> - - The `icon` element used in the example loads the icons from the `@storybook/components` package. See [here](../faq.mdx#what-icons-are-available-for-my-toolbar-or-my-addon) for the list of available icons that you can use. + The `match` property allows you to conditionally render your toolbar addon, [based on the current view](./writing-addons.mdx#conditionally-render-the-addon). The `icon` element used in the example loads the icons from the `@storybook/components` package. See [here](../faq.mdx#what-icons-are-available-for-my-toolbar-or-my-addon) for the list of available icons that you can use. </Callout> ### Tabs diff --git a/docs/addons/addons-api.mdx b/docs/addons/addons-api.mdx index 42cbb56c3a90..e5b580597b4f 100644 --- a/docs/addons/addons-api.mdx +++ b/docs/addons/addons-api.mdx @@ -95,7 +95,7 @@ The `selectStory` API method allows you to select a single story. It accepts the {/* prettier-ignore-start */} -<CodeSnippets path="button-story-with-addon-example.md" usesCsf3 csf2Path="addons/addons-api#snippet-button-story-with-addon-example" /> +<CodeSnippets path="button-story-with-addon-example.md" /> {/* prettier-ignore-end */} diff --git a/docs/addons/integration-catalog.mdx b/docs/addons/integration-catalog.mdx index f1b6e63fe9da..8439c033f847 100644 --- a/docs/addons/integration-catalog.mdx +++ b/docs/addons/integration-catalog.mdx @@ -59,10 +59,8 @@ Use the list below as a reference when filling in the values for both the `suppo Make sure to copy each item **exactly** as listed so that we can properly index your addon in our catalog. </Callout> -```json +```json title="package.json" { - // package.json - "name": "storybook-addon-outline", "version": "1.0.0", "description": "Outline all elements with CSS to help with layout placement and alignment", diff --git a/docs/addons/writing-addons.mdx b/docs/addons/writing-addons.mdx index fe3cb45ffd1b..b31aec29f869 100644 --- a/docs/addons/writing-addons.mdx +++ b/docs/addons/writing-addons.mdx @@ -26,7 +26,7 @@ The addon built in this guide is a UI-based addon, specifically a [toolbar](./ad {/* prettier-ignore-start */} -<CodeSnippets path="storybook-addon-toolkit-toolbar-example.md" /> +<CodeSnippets path="storybook-addon-toolkit-types.md" /> {/* prettier-ignore-end */} @@ -68,9 +68,7 @@ By default, code for the UI-based addons is located in one of the following file Going through the code blocks in sequence: -```ts -// src/Tool.tsx - +```ts title="src/Tool.tsx" import { useGlobals, useStorybookApi } from '@storybook/manager-api'; import { IconButton } from '@storybook/components'; import { LightningIcon } from '@storybook/icons'; @@ -80,9 +78,7 @@ The [`useGlobals`](./addons-api.mdx#useglobals) and [`useStorybookApi`](./addons The `IconButton` or `Button` component from the [`@storybook/components`](https://www.npmjs.com/package/@storybook/components) package can be used to render the buttons in the toolbar. The [`@storybook/icons`](https://github.com/storybookjs/icons) package provides a large set of appropriately sized and styled icons to choose from. -```ts -// src/Tool.tsx - +```ts title="src/Tool.tsx" export const Tool = memo(function MyAddonSelector() { const [globals, updateGlobals] = useGlobals(); const api = useStorybookApi(); @@ -175,7 +171,7 @@ Storybook addons, similar to most packages in the JavaScript ecosystem, are dist The first category of metadata is related to the addon itself. This includes the entry for the module, which files to include when the addon is published. And the required configuration to integrate the addon with Storybook, allowing it to be used by its consumers. -```json +```json title="package.json" { "exports": { ".": { @@ -213,7 +209,7 @@ The first category of metadata is related to the addon itself. This includes the The second metadata category is related to the [integration catalog](https://storybook.js.org/integrations). Most of this information is already pre-configured by the Addon Kit. However, items like the display name, icon, and frameworks must be configured via the `storybook` property to be displayed in the catalog. -```json +```json title="package.json" { "name": "my-storybook-addon", "version": "1.0.0", diff --git a/docs/api/csf.mdx b/docs/api/csf.mdx index 68f2d2f37266..efe4c1394d6a 100644 --- a/docs/api/csf.mdx +++ b/docs/api/csf.mdx @@ -10,7 +10,7 @@ sidebar: Component Story Format (CSF) is the recommended way to [write stories](../writing-stories/index.mdx). It's an [open standard](https://github.com/ComponentDriven/csf) based on ES6 modules that is portable beyond Storybook. <Callout variant="info" icon="💡"> - 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/index.mdx#storiesof-to-csf) for more information. + 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/index.mdx#major-breaking-changes) for more information. </Callout> 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). @@ -35,7 +35,7 @@ With CSF, every named export in the file represents a story object by default. {/* prettier-ignore-start */} -<CodeSnippets path="my-component-story-basic-and-props.md" usesCsf3 csf2Path="api/csf#snippet-my-component-story-basic-and-props" /> +<CodeSnippets path="my-component-story-basic-and-props.md" /> {/* prettier-ignore-end */} @@ -57,7 +57,7 @@ Storybook's `name` configuration element is helpful in specific circumstances. C {/* prettier-ignore-start */} -<CodeSnippets path="my-component-story-with-storyname.md" usesCsf3 csf2Path="api/csf#snippet-my-component-story-with-storyname" /> +<CodeSnippets path="my-component-story-with-storyname.md" /> {/* prettier-ignore-end */} @@ -69,7 +69,7 @@ Consider Storybook’s ["Button" example](../writing-stories/index.mdx#defining- {/* prettier-ignore-start */} -<CodeSnippets path="button-story-click-handler.md" usesCsf3 csf2Path="api/csf#snippet-button-story-click-handler" /> +<CodeSnippets path="button-story-click-handler.md" /> {/* prettier-ignore-end */} @@ -77,7 +77,7 @@ Now consider the same example, re-written with args: {/* prettier-ignore-start */} -<CodeSnippets path="button-story-click-handler-args.md" usesCsf3 csf2Path="api/csf#snippet-button-story-click-handler-args" /> +<CodeSnippets path="button-story-click-handler-args.md" /> {/* prettier-ignore-end */} @@ -85,7 +85,7 @@ Or even more simply: {/* prettier-ignore-start */} -<CodeSnippets path="button-story-click-handler-simplificated.md" usesCsf3 csf2Path="api/csf#snippet-button-story-click-handler-simplificated" /> +<CodeSnippets path="button-story-click-handler-simplificated.md" /> {/* prettier-ignore-end */} @@ -101,7 +101,7 @@ A good use case for the `play` function is a form component. With previous Story {/* prettier-ignore-start */} -<CodeSnippets path="login-form-with-play-function.md" usesCsf3 csf2Path="api/csf#snippet-login-form-with-play-function" /> +<CodeSnippets path="login-form-with-play-function.md" /> {/* prettier-ignore-end */} @@ -114,7 +114,7 @@ When the story renders in the UI, Storybook executes each step defined in the `p {/* prettier-ignore-start */} - <CodeSnippets path="component-story-with-custom-render-function.md" usesCsf3 csf2Path="api/csf#snippet-component-story-with-custom-render-function" /> + <CodeSnippets path="component-story-with-custom-render-function.md" /> {/* prettier-ignore-end */} @@ -152,7 +152,7 @@ Consider the following story file: {/* prettier-ignore-start */} -<CodeSnippets path="my-component-story-with-nonstory.md" usesCsf3 csf2Path="api/csf#snippet-my-component-story-with-nonstory" /> +<CodeSnippets path="my-component-story-with-nonstory.md" /> {/* prettier-ignore-end */} diff --git a/docs/api/doc-blocks/doc-block-argtypes.mdx b/docs/api/doc-blocks/doc-block-argtypes.mdx index f7009dd1ee32..62223e753138 100644 --- a/docs/api/doc-blocks/doc-block-argtypes.mdx +++ b/docs/api/doc-blocks/doc-block-argtypes.mdx @@ -17,9 +17,7 @@ The `ArgTypes` block can be used to show a static table of [arg types](../arg-ty {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, ArgTypes } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; @@ -51,9 +49,7 @@ import { ArgTypes } from '@storybook/blocks'; {/* prettier-ignore-start */} - ```md - {/* ButtonDocs.mdx */} - + ```md title="ButtonDocs.mdx" <ArgTypes of={ButtonStories} exclude={['style']} /> ``` diff --git a/docs/api/doc-blocks/doc-block-canvas.mdx b/docs/api/doc-blocks/doc-block-canvas.mdx index bee523de54be..1202bdd25abd 100644 --- a/docs/api/doc-blocks/doc-block-canvas.mdx +++ b/docs/api/doc-blocks/doc-block-canvas.mdx @@ -15,9 +15,7 @@ When using the Canvas block in MDX, it references a story with the `of` prop: {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Canvas } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; @@ -53,9 +51,7 @@ import { Canvas } from '@storybook/blocks'; {/* prettier-ignore-start */} - ```md - {/* ButtonDocs.mdx */} - + ```md title="ButtonDocs.mdx" <Canvas of={ButtonStories.Basic} sourceState="shown" /> ``` @@ -87,15 +83,13 @@ Provides any additional custom actions to show in the bottom right corner. These {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Story, Canvas, SourceState } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; <Meta of={ButtonStories} /> -{/* with an additional action */} +{/* With an additional action */} <Canvas additionalActions={[ { @@ -146,9 +140,7 @@ You can render a story from a CSF file that you haven’t attached to the MDX fi {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Canvas } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; import * as HeaderStories from './Header.stories'; diff --git a/docs/api/doc-blocks/doc-block-colorpalette.mdx b/docs/api/doc-blocks/doc-block-colorpalette.mdx index a0f31720ea4f..0459af784b06 100644 --- a/docs/api/doc-blocks/doc-block-colorpalette.mdx +++ b/docs/api/doc-blocks/doc-block-colorpalette.mdx @@ -13,9 +13,7 @@ The `ColorPalette` block allows you to document all color-related items (e.g., s {/* prettier-ignore-start */} -```md -{/* Colors.mdx */} - +```md title="Colors.mdx" import { Meta, ColorPalette, ColorItem } from '@storybook/blocks'; <Meta title="Colors" /> diff --git a/docs/api/doc-blocks/doc-block-controls.mdx b/docs/api/doc-blocks/doc-block-controls.mdx index 5c11708a0019..32bce38ca5ec 100644 --- a/docs/api/doc-blocks/doc-block-controls.mdx +++ b/docs/api/doc-blocks/doc-block-controls.mdx @@ -17,9 +17,7 @@ The `Controls` block can be used to show a dynamic table of args for a given sto {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Canvas, Controls } from '@storybook/blocks'; import * as ButtonStories from './Button.stories' @@ -59,9 +57,7 @@ import { Controls } from '@storybook/blocks'; {/* prettier-ignore-start */} - ```md - {/* ButtonDocs.mdx */} - + ```md title="ButtonDocs.mdx" <Controls of={ButtonStories} exclude={['style']} /> ``` diff --git a/docs/api/doc-blocks/doc-block-description.mdx b/docs/api/doc-blocks/doc-block-description.mdx index 15cbf9843764..538306e76a75 100644 --- a/docs/api/doc-blocks/doc-block-description.mdx +++ b/docs/api/doc-blocks/doc-block-description.mdx @@ -13,9 +13,7 @@ The `Description` block displays the description for a component, story, or meta {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Description } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; @@ -63,12 +61,9 @@ When documenting a component, reference a meta export in the `of` prop (see belo This flow gives you powerful ways to override the description for each scenario. Take the following example: -```jsx -// Button.jsx - +```jsx title="Button.jsx" /** - * # The Button component - * Shows a button + * The Button component shows a button */ export const Button = () => <button>Click me</button>; ``` @@ -81,9 +76,7 @@ export const Button = () => <button>Click me</button>; {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Description } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; diff --git a/docs/api/doc-blocks/doc-block-icongallery.mdx b/docs/api/doc-blocks/doc-block-icongallery.mdx index 7da3d7960cc2..be79b79e9213 100644 --- a/docs/api/doc-blocks/doc-block-icongallery.mdx +++ b/docs/api/doc-blocks/doc-block-icongallery.mdx @@ -11,12 +11,14 @@ The `IconGallery` block enables you to easily document React icon components ass ![Screenshot of IconGallery and IconItem blocks](../../_assets/api/doc-block-icongallery.png) -{/* prettier-ignore-start */} +## Documenting icons + +To document a set of icons, use the `IconGallery` block to display them in a grid. Each icon is wrapped in an `IconItem` block, enabling you to specify its properties, such as the name and the icon itself. -```md -{/* Iconography.mdx */} +{/* prettier-ignore-start */} -import { Meta, Title, IconGallery, IconItem } from '@storybook/blocks'; +```md title="Iconography.mdx" +import { Meta, IconGallery, IconItem } from '@storybook/blocks'; import { Icon as IconExample } from './Icon'; @@ -60,6 +62,31 @@ import { Icon as IconExample } from './Icon'; {/* prettier-ignore-end */} +### Automate icon documentation + +If you're working on a project that contains a large number of icons that you want to document, you can extend the `IconGallery` block, wrap `IconItem` in a loop, and iterate over the icons you want to document, including their properties. For example: + +{/* prettier-ignore-start */} + +```md title="Iconography.mdx" +import { Meta, IconGallery, IconItem } from '@storybook/blocks'; + +import { Icon as IconExample } from './Icon'; +import * as icons from './icons'; + +# Iconography + +<IconGallery> + {Object.keys(icons).map((icon) => ( + <IconItem name={icon}> + <IconExample icon={icon} /> + </IconItem> + ))} +</IconGallery> +``` + +{/* prettier-ignore-end */} + ## IconGallery ```js diff --git a/docs/api/doc-blocks/doc-block-markdown.mdx b/docs/api/doc-blocks/doc-block-markdown.mdx index ea807584bbe2..2732cd9b2cb5 100644 --- a/docs/api/doc-blocks/doc-block-markdown.mdx +++ b/docs/api/doc-blocks/doc-block-markdown.mdx @@ -13,9 +13,7 @@ When importing markdown files, it’s important to use the `?raw` suffix on the {/* prettier-ignore-start */} -````md -{/* README.md */} - +````md title="README.md" # Button Primary UI component for user interaction @@ -29,9 +27,7 @@ import { Button } from "@storybook/design-system"; {/* prettier-ignore-start */} -```md -{/* Header.mdx */} - +```md title="Header.mdx" // DON'T do this, will error import ReadMe from './README.md'; // DO this, will work diff --git a/docs/api/doc-blocks/doc-block-meta.mdx b/docs/api/doc-blocks/doc-block-meta.mdx index f0121df062e1..7d7cc0f724fa 100644 --- a/docs/api/doc-blocks/doc-block-meta.mdx +++ b/docs/api/doc-blocks/doc-block-meta.mdx @@ -12,9 +12,7 @@ The `Meta` block is used to [attach](#attached-vs-unattached) a custom MDX docs {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; @@ -49,9 +47,7 @@ Sets the name of the [attached](#attached-vs-unattached) doc entry. You can atta {/* prettier-ignore-start */} -```md -{/* Component.mdx */} - +```md title="Component.mdx" import { Meta } from '@storybook/blocks'; import * as ComponentStories from './component.stories'; @@ -69,9 +65,7 @@ Specifies which CSF file is [attached](#attached-vs-unattached) to this MDX file {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Story } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; diff --git a/docs/api/doc-blocks/doc-block-primary.mdx b/docs/api/doc-blocks/doc-block-primary.mdx index 62882f3a1d88..28dd3d678fd2 100644 --- a/docs/api/doc-blocks/doc-block-primary.mdx +++ b/docs/api/doc-blocks/doc-block-primary.mdx @@ -13,9 +13,7 @@ The `Primary` block displays the primary (first defined in the stories file) sto {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Primary } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; diff --git a/docs/api/doc-blocks/doc-block-source.mdx b/docs/api/doc-blocks/doc-block-source.mdx index e2d5f94d5985..f3edb6d6df9d 100644 --- a/docs/api/doc-blocks/doc-block-source.mdx +++ b/docs/api/doc-blocks/doc-block-source.mdx @@ -13,9 +13,7 @@ The `Source` block is used to render a snippet of source code directly. {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Source } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; @@ -47,9 +45,7 @@ import { Source } from '@storybook/blocks'; {/* prettier-ignore-start */} - ```md - {/* ButtonDocs.mdx */} - + ```md title="ButtonDocs.mdx" <Source of={ButtonStories.Basic} language="tsx" /> ``` @@ -68,9 +64,7 @@ Provides the source code to be rendered. {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Source } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; diff --git a/docs/api/doc-blocks/doc-block-stories.mdx b/docs/api/doc-blocks/doc-block-stories.mdx index 42cd9fcc2c95..6dcd5e0bff59 100644 --- a/docs/api/doc-blocks/doc-block-stories.mdx +++ b/docs/api/doc-blocks/doc-block-stories.mdx @@ -13,9 +13,7 @@ The `Stories` block renders the full collection of stories in a stories file. {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Stories } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; diff --git a/docs/api/doc-blocks/doc-block-story.mdx b/docs/api/doc-blocks/doc-block-story.mdx index c5a8828f421f..df1446ecb550 100644 --- a/docs/api/doc-blocks/doc-block-story.mdx +++ b/docs/api/doc-blocks/doc-block-story.mdx @@ -21,9 +21,7 @@ In Storybook Docs, you can render any of your stories from your CSF files in the {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx"+ import { Meta, Story } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; @@ -55,9 +53,7 @@ import { Story } from '@storybook/blocks'; {/* prettier-ignore-start */} - ```md - {/* ButtonDocs.mdx */} - + ```md title="ButtonDocs.mdx" <Story of={ButtonStories.Basic} autoplay /> ``` @@ -114,9 +110,7 @@ You can render a story from a CSF file that you haven’t attached to the MDX fi {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta, Story } from '@storybook/blocks'; import * as ButtonStories from './Button.stories'; import * as HeaderStories from './Header.stories'; diff --git a/docs/api/doc-blocks/doc-block-subtitle.mdx b/docs/api/doc-blocks/doc-block-subtitle.mdx index a04da42c328d..dee2b243f534 100644 --- a/docs/api/doc-blocks/doc-block-subtitle.mdx +++ b/docs/api/doc-blocks/doc-block-subtitle.mdx @@ -13,9 +13,7 @@ The `Subtitle` block can serve as a secondary heading for your docs entry. {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Subtitle } from '@storybook/blocks'; <Subtitle>This is the subtitle</Subtitle> diff --git a/docs/api/doc-blocks/doc-block-title.mdx b/docs/api/doc-blocks/doc-block-title.mdx index 3d8c74c25949..54a474b738f7 100644 --- a/docs/api/doc-blocks/doc-block-title.mdx +++ b/docs/api/doc-blocks/doc-block-title.mdx @@ -13,9 +13,7 @@ The `Title` block serves as the primary heading for your docs entry. It is typic {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Title } from '@storybook/blocks'; <Title>This is the title diff --git a/docs/api/doc-blocks/doc-block-typeset.mdx b/docs/api/doc-blocks/doc-block-typeset.mdx index 8ceb2ab7b67d..5cedbf8ab772 100644 --- a/docs/api/doc-blocks/doc-block-typeset.mdx +++ b/docs/api/doc-blocks/doc-block-typeset.mdx @@ -13,9 +13,7 @@ The `Typeset` block helps document the fonts used throughout your project. {/* prettier-ignore-start */} -```md -{/* Typography.mdx */} - +```md title="Typography.mdx" import { Meta, Typeset } from '@storybook/blocks'; diff --git a/docs/api/doc-blocks/doc-block-unstyled.mdx b/docs/api/doc-blocks/doc-block-unstyled.mdx index 4e9e56a8ade3..dce273c69d0b 100644 --- a/docs/api/doc-blocks/doc-block-unstyled.mdx +++ b/docs/api/doc-blocks/doc-block-unstyled.mdx @@ -11,7 +11,7 @@ By default, most elements (like `h1`, `p`, etc.) in docs have a few default styl {/* prettier-ignore-start */} -```md +```md title="ButtonDocs.mdx" import { Meta, Unstyled } from "@storybook/blocks"; import { Header } from "./Header.tsx"; diff --git a/docs/api/doc-blocks/doc-block-useof.mdx b/docs/api/doc-blocks/doc-block-useof.mdx index 7e5944c07869..89a7fb7c7d05 100644 --- a/docs/api/doc-blocks/doc-block-useof.mdx +++ b/docs/api/doc-blocks/doc-block-useof.mdx @@ -11,9 +11,7 @@ If your own doc blocks need to interface with annotations from Storybook—that Here’s an example of how the`useOf` hook could be used to create a custom block that displays the name of the story: -```jsx -// .storybook/blocks/StoryName.jsx - +```jsx title=".storybook/blocks/StoryName.jsx" import { useOf } from '@storybook/blocks'; /** @@ -38,22 +36,20 @@ export const StoryName = ({ of }) => { {/* prettier-ignore-start */} -```md -{/* ButtonDocs.mdx */} - +```md title="ButtonDocs.mdx" import { Meta } from '@storybook/blocks'; import { StoryName } from '../.storybook/blocks/StoryName'; import * as ButtonStories from './Button.stories'; -{/* renders "Secondary" */} +{/* Renders "Secondary" */} -{/* renders "Primary" */} +{/* Renders "Primary" */} -{/* renders "Button" */} +{/* Renders "Button" */} ``` diff --git a/docs/api/new-frameworks.mdx b/docs/api/new-frameworks.mdx index edd780db1191..11d8b8407f13 100644 --- a/docs/api/new-frameworks.mdx +++ b/docs/api/new-frameworks.mdx @@ -33,7 +33,7 @@ Storybook has the concept of [presets](../addons/writing-presets.mdx), which are It's helpful to understand Storybook's package structure before adding a framework preset. Each framework typically exposes two executables in its `package.json`: -```json +```json title="package.json" { "bin": { "storybook": "./bin/index.js", @@ -94,7 +94,7 @@ Consider the following React story: {/* prettier-ignore-start */} - + {/* prettier-ignore-end */} @@ -106,7 +106,7 @@ Consider the following hypothetical example: {/* prettier-ignore-start */} - + {/* prettier-ignore-end */} diff --git a/docs/api/parameters.mdx b/docs/api/parameters.mdx index 8f1313203871..28362afe6a5a 100644 --- a/docs/api/parameters.mdx +++ b/docs/api/parameters.mdx @@ -9,10 +9,6 @@ Parameters are static metadata used to configure your [stories](../get-started/w ## Story parameters -
- ℹ️ Parameters specified at the story level will [override](#parameter-inheritance) those specified at the project level and meta (component) level. -
- Parameters specified at the story level apply to that story only. They are defined in the `parameters` property of the story (named export): {/* prettier-ignore-start */} @@ -21,11 +17,11 @@ Parameters specified at the story level apply to that story only. They are defin {/* prettier-ignore-end */} -## Meta parameters + + Parameters specified at the story level will [override](#parameter-inheritance) those specified at the project level and meta (component) level. + -
- ℹ️ Parameters specified at the meta (component) level will [override](#parameter-inheritance) those specified at the project level. -
+## Meta parameters Parameter's specified in a [CSF](../writing-stories/index.mdx#component-story-format-csf) file's meta configuration apply to all stories in that file. They are defined in the `parameters` property of the `meta` (default export): @@ -35,6 +31,10 @@ Parameter's specified in a [CSF](../writing-stories/index.mdx#component-story-fo {/* prettier-ignore-end */} + + Parameters specified at the meta (component) level will [override](#parameter-inheritance) those specified at the project level. + + ## Project parameters Parameters specified at the project (global) level apply to **all stories** in your Storybook. They are defined in the `parameters` property of the default export in your `.storybook/preview.js|ts` file: @@ -172,7 +172,6 @@ All other parameters are contributed by addons. The [essential addon's](../essen * [Backgrounds](../essentials/backgrounds.mdx#parameters) * [Controls](../essentials/controls.mdx#parameters) * [Highlight](../essentials/highlight.mdx#parameters) -* [Interactions](../essentials/interactions.mdx#parameters) * [Measure & Outline](../essentials/measure-and-outline.mdx#parameters) * [Viewport](../essentials/viewport.mdx#parameters) @@ -186,15 +185,13 @@ When specifying parameters, they are merged together in order of increasing spec 2. Meta (component) parameters 3. Story parameters -
- ℹ️ Parameters are **merged**, so objects are deep-merged, but arrays and other properties are overwritten. -
+ + Parameters are **merged**, so objects are deep-merged, but arrays and other properties are overwritten. + In other words, the following specifications of parameters: -```js -// .storybook/preview.js|ts - +```js title=".storybook/preview.js|ts" const preview = { // 👇 Project-level parameters parameters: { @@ -209,9 +206,7 @@ const preview = { export default preview; ``` -```js -// Dialog.stories.js|ts - +```js title="Dialog.stories.js|ts" const meta = { component: Dialog, // 👇 Meta-level parameters diff --git a/docs/configure/environment-variables.mdx b/docs/configure/environment-variables.mdx index 1403cc371c69..f1b14c9a4c5c 100644 --- a/docs/configure/environment-variables.mdx +++ b/docs/configure/environment-variables.mdx @@ -90,7 +90,7 @@ When Storybook loads, it will enable you to access them in your stories similar {/* prettier-ignore-start */} - + {/* prettier-ignore-end */} diff --git a/docs/configure/integration/frameworks-feature-support.mdx b/docs/configure/integration/frameworks-feature-support.mdx index aead9b265217..006673db19f1 100644 --- a/docs/configure/integration/frameworks-feature-support.mdx +++ b/docs/configure/integration/frameworks-feature-support.mdx @@ -1,5 +1,6 @@ --- title: 'Feature support for frameworks' +hideRendererSelector: true sidebar: order: 2 title: Feature support for frameworks @@ -117,4 +118,4 @@ To align the Storybook ecosystem with the current state of frontend development, | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [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.mdx) instead. | | [Storyshots](../../writing-tests/snapshot-testing/storyshots-migration-guide.mdx) | 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/snapshot-testing/storyshots-migration-guide.mdx) for the available alternatives. | -| StoriesOf | 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.mdx) instead for writing stories.
See the [migration guide](../../migration-guide/index.mdx#storiesof-to-csf) for more information. | +| StoriesOf | 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.mdx) instead for writing stories.
See the [migration guide](../../migration-guide/index.mdx#major-breaking-changes) for more information. | diff --git a/docs/configure/integration/images-and-assets.mdx b/docs/configure/integration/images-and-assets.mdx index c500de8d210c..5d125c16d41a 100644 --- a/docs/configure/integration/images-and-assets.mdx +++ b/docs/configure/integration/images-and-assets.mdx @@ -15,7 +15,7 @@ Afterward, you can use any asset in your stories: {/* prettier-ignore-start */} - + {/* prettier-ignore-end */} @@ -35,7 +35,7 @@ Here `../public` is your static directory. Now use it in a component or story li {/* prettier-ignore-start */} - + {/* prettier-ignore-end */} @@ -61,7 +61,7 @@ Upload your files to an online CDN and reference them. In this example, we’re {/* prettier-ignore-start */} - + {/* prettier-ignore-end */} diff --git a/docs/configure/story-layout.mdx b/docs/configure/story-layout.mdx index c17f520d3579..deac6de3b8e7 100644 --- a/docs/configure/story-layout.mdx +++ b/docs/configure/story-layout.mdx @@ -41,6 +41,6 @@ Or even apply it to specific stories like so: {/* prettier-ignore-start */} - + {/* prettier-ignore-end */} diff --git a/docs/configure/story-rendering.mdx b/docs/configure/story-rendering.mdx index dccc3e518d1e..3749a925e9c8 100644 --- a/docs/configure/story-rendering.mdx +++ b/docs/configure/story-rendering.mdx @@ -14,8 +14,7 @@ Code executed in the preview file (`.storybook/preview.js|ts`) runs for every st Here's an example of how you might use the preview file to initialize a library that must run before your components render: - ```ts - // .storybook/preview.ts + ```ts title=".storybook/preview.ts" // Replace your-renderer with the renderer you are using (e.g., react, vue3) import { Preview } from '@storybook/your-renderer'; diff --git a/docs/configure/styling-and-css.mdx b/docs/configure/styling-and-css.mdx index ceebd2bb6957..70c0b4303c3f 100644 --- a/docs/configure/styling-and-css.mdx +++ b/docs/configure/styling-and-css.mdx @@ -111,7 +111,7 @@ sidebar: Don't forget to also add your global styles to your `build-storybook` target in your `angular.json` file. This will ensure that your global styles are included in the static build of your Storybook as well. - ```json + ```json title="angular.json" { "storybook": { "builder": "@storybook/angular:start-storybook", @@ -162,8 +162,9 @@ sidebar: For earlier Nx versions (before 14.1.8), your configuration would look like this: - ```json - "build-storybook": { + ```json title="project.json" + { + "build-storybook": { "executor": "@nrwl/storybook:build", "outputs": ["{options.outputPath}"], "options": { @@ -175,34 +176,37 @@ sidebar: "projectBuildConfig": "example-lib:build-storybook", "styles": ["apps/example-app/src/styles.scss"] } - } + }, + } ``` Starting with version 14.1.8, Nx uses the Storybook builder directly, which means any configuration supplied to the builder also applies to the NX setup. If you're working with a library, you'll need to configure the styling options ( e.g., preprocessors) inside the `build-storybook` options configuration object. For example: - ```json - "storybook": { - "executor": "@storybook/angular:start-storybook", - "options": { - "configDir": "apps/example-lib/.storybook", - "browserTarget": "example-lib:build-storybook", - }, + ```json title="workspace.json" + { + "storybook": { + "executor": "@storybook/angular:start-storybook", + "options": { + "configDir": "apps/example-lib/.storybook", + "browserTarget": "example-lib:build-storybook", }, - "build-storybook": { - "executor": "@storybook/angular:build-storybook", - "outputs": ["{options.outputPath}"], - "options": { - "outputDir": "dist/storybook/example-lib", - "configDir": "apps/example-lib/.storybook", - "browserTarget": "example-lib:build-storybook", - "styles": [".storybook/custom-styles.scss"], - "stylePreprocessorOptions": { - "includePaths": [ - "libs/design-system/src/lib" - ] - } + }, + "build-storybook": { + "executor": "@storybook/angular:build-storybook", + "outputs": ["{options.outputPath}"], + "options": { + "outputDir": "dist/storybook/example-lib", + "configDir": "apps/example-lib/.storybook", + "browserTarget": "example-lib:build-storybook", + "styles": [".storybook/custom-styles.scss"], + "stylePreprocessorOptions": { + "includePaths": [ + "libs/design-system/src/lib" + ] } } + }, + } ``` When Nx runs, it will load Storybook's configuration and styling based on [`storybook.browserTarget`](https://nx.dev/storybook/extra-topics-for-angular-projects#setting-up-browsertarget). diff --git a/docs/configure/telemetry.mdx b/docs/configure/telemetry.mdx index d4c3af5804da..56a6ef8cc707 100644 --- a/docs/configure/telemetry.mdx +++ b/docs/configure/telemetry.mdx @@ -1,5 +1,6 @@ --- title: 'Telemetry' +hideRendererSelector: true sidebar: order: 3 title: Telemetry @@ -163,7 +164,7 @@ In the future, we plan to share relevant data with the community through public ## How to opt-out -You may opt-out of the telemetry by setting Storybook's configuration element `disableTelemetry` to `true`, using the `--disable-telemetry` flag, or setting the environment variable`STORYBOOK_DISABLE_TELEMETRY` to `1`. For example: +You may opt out of the telemetry within your Storybook configuration by setting the `disableTelemetry` configuration element to `true`. {/* prettier-ignore-start */} @@ -171,13 +172,29 @@ You may opt-out of the telemetry by setting Storybook's configuration element `d {/* prettier-ignore-end */} +If necessary, you can also turn off telemetry via the command line with the `--disable-telemetry` flag. + +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} + +Or via the `STORYBOOK_DISABLE_TELEMETRY` environment variable. + +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} + There is a `boot` event containing no metadata (used to ensure the telemetry is working). It is sent prior to evaluating your [Storybook configuration file](../api/main-config/main-config.mdx) (i.e., `main.js|ts`), so it is unaffected by the `disableTelemetry` option. If you want to ensure that the event is not sent, use the `STORYBOOK_DISABLE_TELEMETRY` environment variable. ## Crash reports (disabled by default) -In addition to general usage telemetry, you may also choose to share crash reports. Storybook will then sanitize the error object (removing all user paths) and append it to the telemetry event. To enable crash reporting, you can set the `enableCrashReports` configuration element to `true`, using the `--enable-crash-reports` flag, or set the `STORYBOOK_ENABLE_CRASH_REPORTS` environment variable to `1`. For example: +In addition to general usage telemetry, you may also choose to share crash reports. Storybook will then sanitize the error object (removing all user paths) and append it to the telemetry event. To enable crash reporting, you can set the `enableCrashReports` configuration element to `true`. {/* prettier-ignore-start */} @@ -185,7 +202,23 @@ In addition to general usage telemetry, you may also choose to share crash repor {/* prettier-ignore-end */} -Generates the following item in the telemetry event: +You can also enable crash reporting via the command line with the `--enable-crash-reports` flag. + +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} + +Or by setting the `STORYBOOK_ENABLE_CRASH_REPORTS` environment variable to `1`. + +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} + +Enabling any of the options will generate the following item in the telemetry event: {/* prettier-ignore-start */} diff --git a/docs/configure/user-interface/sidebar-and-urls.mdx b/docs/configure/user-interface/sidebar-and-urls.mdx index 55537246e214..8ee6ecd62f3d 100644 --- a/docs/configure/user-interface/sidebar-and-urls.mdx +++ b/docs/configure/user-interface/sidebar-and-urls.mdx @@ -35,7 +35,7 @@ Consider the following story: {/* prettier-ignore-start */} - + {/* prettier-ignore-end */} @@ -45,7 +45,7 @@ It is possible to manually set the story's id, which is helpful if you want to r {/* prettier-ignore-start */} - + {/* prettier-ignore-end */} diff --git a/docs/contribute/RFC.mdx b/docs/contribute/RFC.mdx index 32f1aae9b636..d67f71e9a179 100644 --- a/docs/contribute/RFC.mdx +++ b/docs/contribute/RFC.mdx @@ -1,5 +1,6 @@ --- title: 'RFC process' +hideRendererSelector: true sidebar: order: 1 title: RFC process @@ -55,4 +56,4 @@ This RFC process took heavy inspiration from the RFC processes from [Rust](https * [Code](./code.mdx) for features and bug fixes * [Frameworks](./framework.mdx) to get started with a new framework * [Documentation](./documentation/documentation-updates.mdx) for documentation improvements, typos, and clarifications -* [Examples](./documentation/new-snippets.mdx) for new snippets and examples +* [Examples](./documentation/new-snippets.mdx) for new snippets diff --git a/docs/contribute/code.mdx b/docs/contribute/code.mdx index d735283bd8af..51a74533afde 100644 --- a/docs/contribute/code.mdx +++ b/docs/contribute/code.mdx @@ -1,5 +1,6 @@ --- title: 'Code contributions' +hideRendererSelector: true sidebar: order: 2 title: Code @@ -10,7 +11,7 @@ Contribute a new feature or bug fix to [Storybook's monorepo](https://github.com ## Prerequisites * Ensure you have Node version 18 installed (suggestion: v18.16.0). -* Ensure if you are using Windows to use the Windows Subsystem for Linux (WSL). +* If you're working with Windows, all commands should be run in a terminal with administrator privileges. ## Initial setup @@ -264,4 +265,4 @@ Once the PR is merged, the template will be generated on a nightly cadence and y * Code for features and bug fixes * [Frameworks](./framework.mdx) to get started with a new framework * [Documentation](./documentation/documentation-updates.mdx) for documentation improvements, typos, and clarifications -* [Examples](./documentation/new-snippets.mdx) for new snippets and examples +* [Examples](./documentation/new-snippets.mdx) for new snippets diff --git a/docs/contribute/documentation/documentation-updates.mdx b/docs/contribute/documentation/documentation-updates.mdx index 3e62a5a4d225..51e38f8a523a 100644 --- a/docs/contribute/documentation/documentation-updates.mdx +++ b/docs/contribute/documentation/documentation-updates.mdx @@ -1,5 +1,6 @@ --- title: 'Documentation updates' +hideRendererSelector: true sidebar: order: 1 title: Content @@ -31,4 +32,4 @@ In the Storybook repository, create a pull request that describes changes and in * [Code](../code.mdx) for features and bug fixes * [Frameworks](../framework.mdx) to get started with a new framework * Documentation for documentation improvements, typos, and clarifications -* [Examples](./new-snippets.mdx) for new snippets and examples +* [Examples](./new-snippets.mdx) for new snippets diff --git a/docs/contribute/documentation/new-snippets.mdx b/docs/contribute/documentation/new-snippets.mdx index 1a7cf0c0b601..b2bf813c91a5 100644 --- a/docs/contribute/documentation/new-snippets.mdx +++ b/docs/contribute/documentation/new-snippets.mdx @@ -1,5 +1,6 @@ --- title: 'Code snippets contributions' +hideRendererSelector: true sidebar: order: 2 title: Code snippets @@ -9,129 +10,288 @@ Add or update the code snippets in the documentation. This page outlines how the ## Documented frameworks -Storybook maintains code snippets for a [variety of frameworks](../../configure/integration/frameworks-feature-support.mdx). We try to keep them up to date as framework APIs evolve. But it's tricky to keep track of every API change in every framework. +Storybook maintains code snippets for a [variety of frameworks](../../configure/integration/frameworks-feature-support.mdx). We try to keep them up to date as framework APIs evolve. But keeping track of every API change in every framework is tricky. -We welcome community contributions to the code snippets. Here's a matrix of the frameworks we have snippets for. Help us add snippets for your favorite framework. +We welcome community contributions to the code snippets. Here's a matrix of the frameworks for which we have snippets. Help us add snippets for your favorite framework. -| React | Vue 3 | Angular | Web Components | Svelte | Solid | Ember | HTML | Preact | -| ---------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ----- | ---- | ------ | -| [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/react) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/vue) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/angular) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/web-components) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/svelte) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/solid) | ❌ | ❌ | ❌ | -## Setup +| React | Vue 3 | Angular | Web Components | Svelte | Solid | Ember | HTML | Preact | Qwik | +| ------ | ----- | --------- | ---------------|--------|--------|-------|------| -------|------| +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | -Assuming you've already followed the [local environment guide](../code.mdx#initial-setup), the first thing you need to do is create a branch on your local Storybook monorepo by running the following command: -```shell -git checkout -b code-snippets-for-framework +## Snippet syntax + +The code snippets referenced throughout the Storybook documentation are located in the [`docs/_snippets`](https://github.com/storybookjs/storybook/tree/next/docs/_snippets) directory inside individual Markdown files, containing the [supported frameworks](../../configure/integration/frameworks-feature-support.mdx), features and languages (i.e., JavaScript, MDX, TypeScript). + +### Example + +The following code block demonstrates how to structure a code snippet in the Storybook documentation and the attributes you can use to provide additional context to the code snippet. + +{/* prettier-ignore-start */} + +````md title="docs/_snippets/button-group-story.md" +```ts filename="ButtonGroup.stories.ts" renderer="vue" language="ts" tabTitle="3" +import type { Meta, StoryObj } from '@storybook/vue3'; + +import ButtonGroup from './ButtonGroup.vue'; + +//👇 Imports the Button stories +import * as ButtonStories from './Button.stories'; + +const meta: Meta = { + component: ButtonGroup, +}; + +export default meta; +type Story = StoryObj; + +export const Pair: Story = { + render: (args) => ({ + components: { ButtonGroup }, + setup() { + return { args }; + }, + template: '', + }), + args: { + buttons: [{ ...ButtonStories.Primary.args }, { ...ButtonStories.Secondary.args }], + orientation: 'horizontal', + }, +}; +``` +```` + +{/* prettier-ignore-end */} + + +## Common attributes for code snippets + +Following are the attributes you'll use most often in the Storybook documentation code snippets, as well as a brief explanation of each to help you understand the context in which they are used. + +### File name as title + +Most code examples should include a file name so readers can understand which file they relate to and where to paste it into their project. For code examples, include the `filename` attribute wrapped with quotation marks to indicate the file name. This is not required if the example relates to a terminal command. + +{/* prettier-ignore-start */} + +````md title="docs/_snippets/button-stories.md" +```ts filename="Button.stories.ts" ``` +```` -Before adding your snippets, open the `docs` folder with your editor of choice. Get familiarized with the documentation, including how the snippets are organized and their contents. +{/* prettier-ignore-end */} -Then inside the root folder of the Storybook monorepo, run the following command: +### Language configuration -```shell -yarn task +Use the `language` attribute to define the language to which the code snippet applies. The documentation uses this attribute to determine which variant to display (e.g., JavaScript, TypeScript, TypeScript 4.9, MDX). + +{/* prettier-ignore-start */} + +````md title="docs/_snippets/button-stories.md" +```ts filename="Button.stories.ts" language="js|ts|ts-4-9|mdx" ``` +```` -Select the option `Synchronize documentation (sync-docs)` and type the path of your `frontpage` project folder. Now every file change inside the monorepo `docs` folder will be reflected in the frontpage repo at `src/content/docs`. +{/* prettier-ignore-end */} -### Add your first snippet +### Framework-specific code -Now that you're familiar with how the documentation is structured, it's time to add the code snippets. First, go to the `docs/snippets/` folder and create a new directory for your framework of choice (e.g., `ember`). +Use the `renderer` attribute to indicate which of the [supported frameworks](../../configure/integration/frameworks-feature-support.mdx) the code snippet belongs to. -Browse the documentation and look for the code snippets you're willing to contribute. For example, on the [setup page](https://github.com/storybookjs/storybook/blob/next/docs/get-started/setup.mdx), you should see something similar to: +{/* prettier-ignore-start */} -```jsx -// /docs/get-started/setup.md +````md title="docs/_snippets/button-stories.md" +```ts filename="Button.stories.ts" language="ts" renderer="react|vue|angular|web-components|ember|html|svelte|preact|qwik|solid" +``` +```` + +{/* prettier-ignore-end */} + +Alternatively, if you're documenting examples that apply to multiple frameworks, use the `renderer` attribute with the `common` value to indicate that the code snippet is framework-agnostic. {/* prettier-ignore-start */} - +````md title="docs/_snippets/button-stories.md" +```ts filename="Button.stories.ts" language="ts" renderer="common" +``` +```` {/* prettier-ignore-end */} + +### Package manager configuration + +Use the `packageManager` attribute to configure the package manager used in the example from the following options: `npm`, `yarn`, or `pnpm`. + + +{/* prettier-ignore-start */} + +````md title="docs/_snippets/storybook-run-dev.md" +```shell renderer="common" language="js" packageManager="npm|yarn|pnpm" ``` +```` -Create the file `ember/your-component.js.mdx`, similar to the other frameworks, and reference it. +{/* prettier-ignore-end */} -```jsx -// /docs/get-started/setup.md +### Working with multiple snippets +Use the `tabTitle` attribute to indicate the tab title in which the code snippet will be displayed. This attribute should only be used when multiple examples are in a single code snippet file. + {/* prettier-ignore-start */} - +````md title="docs/_snippets/component-decorator.md" +```ts filename="YourComponent.stories.ts" language="ts" renderer="common" tabTitle="Story" +``` +```ts filename=".storybook/preview.ts" language="ts" renderer="common" tabTitle="Storybook configuration" +``` +```` {/* prettier-ignore-end */} + +## Contributing code snippets + +You can start contributing to the Storybook documentation by now that you're familiar with how the documentation is organized, the code snippet's structure, and available options. Assuming that you have already set up your [local development environment](../code.mdx#initial-setup) and are ready to contribute, the following steps will guide you through contributing code snippets to the Storybook documentation. + +Start by creating a new branch on your local Storybook monorepo with the following command: + +{/* prettier-ignore-start */} + +```shell +git checkout -b code-snippets-for-framework ``` + +{/* prettier-ignore-end */} - - Code snippets are divided into various file extensions, if you're contributing a TypeScript file use `.ts.mdx`, or if you're adding JavaScript files use `.js.mdx`. - +Browse the documentation and look for the code snippets you want to contribute. For example, on the [setup page](https://github.com/storybookjs/storybook/blob/next/docs/get-started/setup.mdx) you should see the following: + +{/* prettier-ignore-start */} + + ```jsx title="docs/get-started/setup.mdx" +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} +``` + +{/* prettier-ignore-end */} + + +Open the file inside the `docs/_snippets` directory and adjust the content to match the code snippet you're willing to contribute. For example: + +{/* prettier-ignore-start */} + +````md title="docs/_snippets/your-component.md" +```ts filename="YourComponent.stories.ts" renderer="qwik" language="ts-4-9" +import type { Meta, StoryObj } from 'storybook-framework-qwik'; + +import type { YourComponentProps } from './YourComponent'; + +import { YourComponent } from './YourComponent'; + +//👇 This default export determines where your story goes in the story list +const meta = { + component: YourComponent, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const FirstStory: Story = { + args: { + //👇 The args you need here will depend on your component + }, +}; +``` +```` + +{/* prettier-ignore-end */} Go through the rest of the documentation and repeat the process. -### Preview your work +## Preview your work + +Before submitting your contribution, we encourage you to check your work against the Storybook website. Doing this prevents last-minute issues with the documentation and is also an excellent way for the maintainers to merge faster once you submit the pull request. However, failing to do so will lead one of the maintainers to notify you that your contribution has an issue. -Before submitting your contribution, we advise you to check your work against the Storybook website. Doing this prevents last-minute issues with the documentation and is also an excellent way for the maintainers to merge faster once you submit the pull request. However, failing to do so will lead one of the maintainers to notify you that your contribution has an issue. +Start by forking the Storybook [website repository](https://github.com/storybookjs/web) and cloning it locally. -Start by forking [frontpage repo](https://github.com/storybookjs/frontpage) and cloning it locally. +{/* prettier-ignore-start */} ```shell -git clone https://github.com/your-username/frontpage.git +git clone https://github.com/your-username/web.git ``` + +{/* prettier-ignore-end */} + +Navigate to the `web` directory and install the required dependencies. -Navigate to the `frontpage` directory and install the required dependencies with the following command: +{/* prettier-ignore-start */} ```shell -yarn +npm install ``` -Next, make sure that you have running the `Synchronize documentation (sync-docs)` task from Storybook monorepo. Then, execute the following command to launch the Storybook website. +{/* prettier-ignore-end */} + +We recommend that you generate a website build first to ensure you can preview your changes locally and verify that everything is working as expected. To do so, run the following command: + +{/* prettier-ignore-start */} ```shell -yarn start:docs-only +npm run build:frontpage ``` - - During the start process if there's an issue with the documentation, the process will stop and you'll get a notification. +{/* prettier-ignore-end */} + + + +When executed, this command will retrieve the required files needed to successfully build the Storybook website, including current documentation versions (e.g., `6.5`, `7.6`, `8.x`), and copy them to the `apps/frontpage/docs/` directory, organized by version number. + -Open a browser window to `http://localhost:8000`, click the Docs link, and select your framework from the dropdown. +Run the `sync-docs` command to connect the documentation from the Storybook monorepo to the Storybook website. When prompted, provide the path to your local fork of the Storybook monorepo and the documentation version you're working on. + +{/* prettier-ignore-start */} + +```shell +npm run sync-docs +``` + +{/* prettier-ignore-end */} + +Finally, open a new terminal window and run the `dev` command to start the Storybook website. -![Storybook docs with dropdown](../../_assets/contribute/local-storybook-website-dropdown-optimized.png) +{/* prettier-ignore-start */} + +```shell +npm run dev +``` + +{/* prettier-ignore-end */} + +If all goes well, you should see the Storybook website running. Open a browser window to `http://localhost:3000`, click the Docs link to open the documentation, and select your framework from the dropdown. + +{/* TODO: Record video */} + +