diff --git a/.circleci/config.yml b/.circleci/config.yml index 58cd0d7a8823..1dc7e7f2fa17 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -412,10 +412,10 @@ jobs: - report-workflow-on-failure: template: $(yarn get-template --cadence << pipeline.parameters.workflow >> --task e2e-tests-dev) - store_test_results: - path: storybook/test-results + path: test-results - store_artifacts: destination: playwright - path: storybook/code/playwright-results/ + path: code/playwright-results/ e2e-production: executor: class: medium @@ -443,10 +443,10 @@ jobs: - report-workflow-on-failure: template: $(yarn get-template --cadence << pipeline.parameters.workflow >> --task e2e-tests) - store_test_results: - path: storybook/test-results + path: test-results - store_artifacts: destination: playwright - path: storybook/code/playwright-results/ + path: code/playwright-results/ e2e-ui: executor: class: medium diff --git a/.circleci/src/jobs/e2e-dev.yml b/.circleci/src/jobs/e2e-dev.yml index 0dc12f27e782..9b02ddac07c1 100644 --- a/.circleci/src/jobs/e2e-dev.yml +++ b/.circleci/src/jobs/e2e-dev.yml @@ -30,7 +30,7 @@ steps: - report-workflow-on-failure: template: $(yarn get-template --cadence << pipeline.parameters.workflow >> --task e2e-tests-dev) - store_test_results: - path: storybook/test-results + path: test-results - store_artifacts: # this is where playwright puts more complex stuff - path: storybook/code/playwright-results/ + path: code/playwright-results/ destination: playwright diff --git a/.circleci/src/jobs/e2e-production.yml b/.circleci/src/jobs/e2e-production.yml index e467ececd7ef..edd99661e433 100644 --- a/.circleci/src/jobs/e2e-production.yml +++ b/.circleci/src/jobs/e2e-production.yml @@ -30,7 +30,7 @@ steps: - report-workflow-on-failure: template: $(yarn get-template --cadence << pipeline.parameters.workflow >> --task e2e-tests) - store_test_results: - path: storybook/test-results + path: test-results - store_artifacts: # this is where playwright puts more complex stuff - path: storybook/code/playwright-results/ + path: code/playwright-results/ destination: playwright diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fcd6003f4e3..0c6686df25cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## 10.1.9 + +- Telemetry: Remove instance of check for sub-error handling - [#33356](https://github.com/storybookjs/storybook/pull/33356), thanks @valentinpalkovic! + +## 10.1.8 + +- React-Vite: Update @joshwooding/vite-plugin-react-docgen-typescript - [#33349](https://github.com/storybookjs/storybook/pull/33349), thanks @valentinpalkovic! + +## 10.1.7 + +- Automigrate: Fix missing await - [#33333](https://github.com/storybookjs/storybook/pull/33333), thanks @valentinpalkovic! +- CLI: Remove REACT_PROJECT projectType - [#33334](https://github.com/storybookjs/storybook/pull/33334), thanks @valentinpalkovic! +- Core: Exclude open from pre-bundling to make local xdg-open reachable - [#33325](https://github.com/storybookjs/storybook/pull/33325), thanks @Sidnioulz! +- Nextjs-Vite: Install `vite` during migration if not installed yet - [#33316](https://github.com/storybookjs/storybook/pull/33316), thanks @ghengeveld! +- Telemetry: Fix race condition in telemetry cache causing malformed JSON - [#33323](https://github.com/storybookjs/storybook/pull/33323), thanks @valentinpalkovic! + ## 10.1.6 - Manager: Do not display non-existing shortcuts in the settings page - [#32711](https://github.com/storybookjs/storybook/pull/32711), thanks @DKER2! @@ -276,6 +292,10 @@ It also includes features to level up your UI development, documentation, and te +## 9.1.17 + +- Core: Fix .env-file parsing, thanks @jreinhold! + ## 9.1.16 - CLI: Fix Nextjs project creation in empty directories - [#32828](https://github.com/storybookjs/storybook/pull/32828), thanks @yannbf! @@ -821,6 +841,10 @@ Unique contributors: 29 +## 8.6.15 + +- Core: Fix .env-file parsing, thanks @jreinhold! + ## 8.6.14 - CLI: Add skip onboarding, recommended/minimal config - [#30930](https://github.com/storybookjs/storybook/pull/30930), thanks @shilman! @@ -1798,6 +1822,10 @@ It brings major improvements to Storybook's feature set for testing and document Please checkout our [Migration Guide](https://storybook.js.org/docs/8.0/migration-guide) to upgrade from earlier versions of Storybook. To see a comprehensive list of changes that went into 8.0, you can refer to the [8.0 prerelease changelogs](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.prerelease.md). +## 7.6.21 + +- Core: Fix .env-file parsing, thanks @jreinhold! + ## 7.6.17 - Addon-docs: Fix Table of Contents heading leak - [#23677](https://github.com/storybookjs/storybook/pull/23677), thanks [@vmizg](https://github.com/vmizg)! diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index a0f656be416f..ecf709bc9fe6 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,17 @@ +## 10.2.0-alpha.7 + +- Automigrate: Fix missing await - [#33333](https://github.com/storybookjs/storybook/pull/33333), thanks @valentinpalkovic! +- CLI: Remove REACT_PROJECT projectType - [#33334](https://github.com/storybookjs/storybook/pull/33334), thanks @valentinpalkovic! +- Core: Exclude open from pre-bundling to make local xdg-open reachable - [#33325](https://github.com/storybookjs/storybook/pull/33325), thanks @Sidnioulz! +- Core: Fix `.env`-file parsing - [#33383](https://github.com/storybookjs/storybook/pull/33383), thanks @JReinhold! +- Next.js: Handle v14 compatibility for draftMode import - [#33341](https://github.com/storybookjs/storybook/pull/33341), thanks @tanujbhaud! +- Nextjs-Vite: Update vite-plugin-storybook-nextjs to v3.1.7 - [#33351](https://github.com/storybookjs/storybook/pull/33351), thanks @valentinpalkovic! +- React-Vite: Update @joshwooding/vite-plugin-react-docgen-typescript - [#33349](https://github.com/storybookjs/storybook/pull/33349), thanks @valentinpalkovic! +- React: Use self-closing tag for code snippets - [#33342](https://github.com/storybookjs/storybook/pull/33342), thanks @valentinpalkovic! +- Sidebar: Prevent updating non-existent stories - [#33037](https://github.com/storybookjs/storybook/pull/33037), thanks @ia319! +- Telemetry: Fix race condition in telemetry cache causing malformed JSON - [#33323](https://github.com/storybookjs/storybook/pull/33323), thanks @valentinpalkovic! +- Telemetry: Remove instance of check for sub-error handling - [#33356](https://github.com/storybookjs/storybook/pull/33356), thanks @valentinpalkovic! + ## 10.2.0-alpha.6 - Controls: Fix displaying as object instead of select for optional union types - [#33200](https://github.com/storybookjs/storybook/pull/33200), thanks @tanujbhaud! diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 04dadd152610..c3fa90bab337 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -160,7 +160,7 @@ If you want to make code changes to Storybook packages while running a sandbox, 1. In a second terminal, run `yarn build --watch ` in the `code/` directory. -For example, if you want to build the `@storybook/react`, `@storybook/core-server`, `@storybook/api`, and `@storybook/addon-docs` packages, you would run: +For example, to build the `@storybook/react`, `storybook` itself, `@storybook/builder-vite`, and `@storybook/addon-docs` packages, you would run: ```shell # Navigate to the code directory @@ -171,10 +171,11 @@ yarn build --watch react core-server api addon-docs Most package names can be found after `@storybook/` in the published package. -For instance, to build the `@storybook/react @storybook/core-server @storybook/api @storybook/addon-docs` packages at the same time in watch mode: +For instance, to build the `@storybook/react storybook @storybook/builder-vite @storybook/addon-docs` packages at the same time in watch mode: ```shell -cd code yarn build --watch react core-server api addon-docs +cd code +yarn build --watch react storybook builder-vite addon-docs ``` 2. If you are running the sandbox in ["linked"](https://yarnpkg.com/cli/link) mode (the default), you should see the changes reflected on a refresh (you may need to restart it if changing server packages) @@ -198,7 +199,7 @@ yarn task --prod ```shell # Builds the specified packages in production mode -yarn build --prod --watch angular core addon-docs +yarn build --prod --watch angular storybook addon-docs ``` ### Running against different sandbox templates diff --git a/code/addons/a11y/src/types.ts b/code/addons/a11y/src/types.ts index 61034005d9f3..c8be7acf7d0e 100644 --- a/code/addons/a11y/src/types.ts +++ b/code/addons/a11y/src/types.ts @@ -24,7 +24,7 @@ export interface A11yGlobals { * Prevent the addon from executing automated accessibility checks upon visiting a story. You * can still trigger the checks from the addon panel. * - * @see https://storybook.js.org/docs/writing-tests/accessibility-testing#turn-off-automated-a11y-tests + * @see https://storybook.js.org/docs/writing-tests/accessibility-testing#disable-automated-checks */ manual?: boolean; }; diff --git a/code/addons/docs/src/types.ts b/code/addons/docs/src/types.ts index e6b05c876d34..6f7439f58ff1 100644 --- a/code/addons/docs/src/types.ts +++ b/code/addons/docs/src/types.ts @@ -115,8 +115,6 @@ type SourceBlockParameters = { /** * The formatting used on source code. Both true and 'dedent' have the same effect of removing any * extraneous indentation. Supports all valid prettier parser names. - * - * @see https://storybook.js.org/docs/api/doc-blocks/doc-block-source#format */ format?: boolean | 'dedent' | string; // TODO: We could try to extract types from 'SupportedLanguages' in SyntaxHighlihter, but for now we inline them diff --git a/code/addons/vitest/src/postinstall.ts b/code/addons/vitest/src/postinstall.ts index 65d3f76db115..731133213bb9 100644 --- a/code/addons/vitest/src/postinstall.ts +++ b/code/addons/vitest/src/postinstall.ts @@ -164,7 +164,7 @@ export default async function postInstall(options: PostinstallOptions) { Found an existing Vitest setup file: ${vitestSetupFile} Please refer to the documentation to complete the setup manually: - https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#manual-setup + https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#manual-setup-advanced `; logger.line(); logger.error(`${errorMessage}\n`); @@ -256,7 +256,7 @@ export default async function postInstall(options: PostinstallOptions) { your existing workspace file automatically, you must do it yourself. Please refer to the documentation to complete the setup manually: - https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#manual-setup + https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#manual-setup-advanced ` ); errors.push( @@ -304,7 +304,7 @@ export default async function postInstall(options: PostinstallOptions) { We were unable to update your existing ${vitestConfigFile ? 'Vitest' : 'Vite'} config file. Please refer to the documentation to complete the setup manually: - https://storybook.js.org/docs/writing-tests/integrations/vitest-addon#manual-setup + https://storybook.js.org/docs/writing-tests/integrations/vitest-addon#manual-setup-advanced `); errors.push(new AddonVitestPostinstallConfigUpdateError({ filePath: rootConfig })); } @@ -365,7 +365,7 @@ export default async function postInstall(options: PostinstallOptions) { logger.error(dedent` Could not automatically set up ${addonA11yName} for @storybook/addon-vitest. Please refer to the documentation to complete the setup manually: - https://storybook.js.org/docs/writing-tests/accessibility-testing#test-addon-integration + https://storybook.js.org/docs/writing-tests/accessibility-testing#integration-with-vitest-addon `); errors.push(new AddonVitestPostinstallFailedAddonA11yError({ error: e })); } @@ -390,7 +390,7 @@ export default async function postInstall(options: PostinstallOptions) { dedent` Done, but with errors! @storybook/addon-vitest was installed successfully, but there were some errors during the setup process. Please refer to the documentation to complete the setup manually and check the errors above: - https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#manual-setup + https://storybook.js.org/docs/next/${DOCUMENTATION_LINK}#manual-setup-advanced ` ); throw new AddonVitestPostinstallError({ errors }); diff --git a/code/addons/vitest/src/preset.ts b/code/addons/vitest/src/preset.ts index ab32aca082b5..c95d534cd96b 100644 --- a/code/addons/vitest/src/preset.ts +++ b/code/addons/vitest/src/preset.ts @@ -69,9 +69,9 @@ export const experimental_serverChannel = async (channel: Channel, options: Opti if (!resolvedPreviewBuilder?.includes('vite')) { if (framework.includes('nextjs')) { log(dedent` - You're using ${framework}, which is a Webpack-based builder. In order to use Storybook Test, with your project, you need to use '@storybook/nextjs-vite', a high performance Vite-based equivalent. + You're using ${framework}, which is a Webpack-based builder. In order to use Storybook's Vitest addon, with your project, you need to use '@storybook/nextjs-vite', a high performance Vite-based equivalent. - Information on how to upgrade here: ${picocolors.yellow('https://storybook.js.org/docs/get-started/frameworks/nextjs?ref=upgrade#with-vite')}\n + Refer to the following documentation for more information: ${picocolors.yellow('https://storybook.js.org/docs/get-started/frameworks/nextjs-vite?ref=upgrade#choose-between-vite-and-webpack')}\n `); } return channel; diff --git a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts index 0f28b883d413..ab35c51aece8 100644 --- a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts +++ b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts @@ -178,6 +178,7 @@ export default async ( }, }), new DefinePlugin({ + 'process.env': `(${JSON.stringify(envs)})`, ...stringifyProcessEnvs(envs), NODE_ENV: JSON.stringify( features?.developmentModeForBuild && isProd ? 'development' : process.env.NODE_ENV diff --git a/code/builders/builder-webpack5/src/types.ts b/code/builders/builder-webpack5/src/types.ts index 9a68c77b6ad6..1b2e8dd6837b 100644 --- a/code/builders/builder-webpack5/src/types.ts +++ b/code/builders/builder-webpack5/src/types.ts @@ -34,7 +34,7 @@ export interface StorybookConfigWebpack /** * Enable the experimental `.test` function in CSF Next * - * @see https://storybook.js.org/docs/10/api/main-config/main-config-features#experimentalTestSyntax + * @see https://storybook.js.org/docs/api/main-config/main-config-features#experimentaltestsyntax */ experimentalTestSyntax?: boolean; }; diff --git a/code/core/package.json b/code/core/package.json index 33a065d6d73e..ae519db54709 100644 --- a/code/core/package.json +++ b/code/core/package.json @@ -201,6 +201,7 @@ "@vitest/expect": "3.2.4", "@vitest/spy": "3.2.4", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0", + "open": "^10.2.0", "recast": "^0.23.5", "semver": "^7.6.2", "use-sync-external-store": "^1.5.0", @@ -294,7 +295,6 @@ "modern-tar": "^0.5.5", "nanoid": "^4.0.2", "npmlog": "^7.0.0", - "open": "^10.2.0", "p-limit": "^6.2.0", "package-manager-detector": "^1.1.0", "picocolors": "^1.1.0", diff --git a/code/core/src/actions/types.ts b/code/core/src/actions/types.ts index b47e7219bfe3..72d6fe17f950 100644 --- a/code/core/src/actions/types.ts +++ b/code/core/src/actions/types.ts @@ -19,7 +19,13 @@ export interface ActionsParameters { */ argTypesRegex?: string; - /** Remove the addon panel and disable the addon's behavior */ + /** + * Removes the addon panel and turns off the feature's behavior. If you wish to turn off this + * feature for the entire Storybook, you can set the option in your `main.js|ts` configuration + * file. + * + * @see https://storybook.js.org/docs/essentials/actions#disable + */ disable?: boolean; /** @@ -30,8 +36,6 @@ export interface ActionsParameters { * **To enable this feature, you must use the `withActions` decorator.** * * @example `handles: ['mouseover', 'click .btn']` - * - * @see https://storybook.js.org/docs/essentials/actions#action-event-handlers */ handles?: string[]; }; diff --git a/code/core/src/backgrounds/types.ts b/code/core/src/backgrounds/types.ts index 713a1f1d6e52..0abe07747304 100644 --- a/code/core/src/backgrounds/types.ts +++ b/code/core/src/backgrounds/types.ts @@ -28,7 +28,12 @@ export interface BackgroundsParameters { /** Default background color */ default?: string; - /** Remove the addon panel and disable the addon's behavior */ + /** + * Removes the tool and disables the feature's behavior. If you wish to turn off this feature + * for the entire Storybook, you can set the option in your `main.js|ts` configuration file. + * + * @see https://storybook.js.org/docs/essentials/backgrounds#disable + */ disable?: boolean; /** Configuration for the background grid */ diff --git a/code/core/src/cli/eslintPlugin.ts b/code/core/src/cli/eslintPlugin.ts index 665c4fc84419..f660e9e39e87 100644 --- a/code/core/src/cli/eslintPlugin.ts +++ b/code/core/src/cli/eslintPlugin.ts @@ -259,7 +259,7 @@ export const suggestESLintPlugin = async (): Promise => { const shouldInstall = await prompt.confirm({ message: dedent` We have detected that you're using ESLint. Storybook provides a plugin that gives the best experience with Storybook and helps follow best practices: ${picocolors.yellow( - 'https://storybook.js.org/docs/9/configure/integration/eslint-plugin' + 'https://storybook.js.org/docs/configure/integration/eslint-plugin' )} Would you like to install it? diff --git a/code/core/src/cli/projectTypes.ts b/code/core/src/cli/projectTypes.ts index b91f16460c86..2c35cdfa9347 100644 --- a/code/core/src/cli/projectTypes.ts +++ b/code/core/src/cli/projectTypes.ts @@ -11,7 +11,6 @@ export enum ProjectType { REACT_NATIVE = 'react_native', REACT_NATIVE_AND_RNW = 'react_native_and_rnw', REACT_NATIVE_WEB = 'react_native_web', - REACT_PROJECT = 'react_project', REACT_SCRIPTS = 'react_scripts', SERVER = 'server', SOLID = 'solid', diff --git a/code/core/src/common/utils/envs.ts b/code/core/src/common/utils/envs.ts index e825bd6af2ae..d62eeb6048be 100644 --- a/code/core/src/common/utils/envs.ts +++ b/code/core/src/common/utils/envs.ts @@ -11,7 +11,7 @@ export async function loadEnvs(options: { production?: boolean } = {}): Promise< const { getEnvironment } = await import('lazy-universal-dotenv'); const defaultNodeEnv = options.production ? 'production' : 'development'; - const env: Record = { + const baseEnv: Record = { // eslint-disable-next-line @typescript-eslint/dot-notation NODE_ENV: process.env['NODE_ENV'] || defaultNodeEnv, NODE_PATH: process.env['NODE_PATH'] || '', @@ -23,27 +23,23 @@ export async function loadEnvs(options: { production?: boolean } = {}): Promise< PUBLIC_URL: options.production ? '.' : '', }; - Object.keys(process.env) - .filter((name) => /^STORYBOOK_/.test(name)) - .forEach((name) => { - env[name] = process.env[name]; - }); + const dotenv = getEnvironment({ nodeEnv: baseEnv['NODE_ENV'] }); - const base = Object.entries(env).reduce( - (acc, [k, v]) => Object.assign(acc, { [k]: JSON.stringify(v) }), - {} as Record + const envEntries = Object.fromEntries( + Object.entries({ + // TODO: it seems wrong that dotenv overrides process.env, but that's how it has always worked + ...process.env, + ...dotenv.raw, + }).filter(([name]) => /^STORYBOOK_/.test(name)) ); - const { stringified, raw } = getEnvironment({ nodeEnv: env['NODE_ENV'] }); + const raw: Record = { ...baseEnv, ...envEntries }; + (raw as any).NODE_PATH = nodePathsToArray((raw.NODE_PATH as string) || ''); - const fullRaw = { ...env, ...raw }; - - fullRaw.NODE_PATH = nodePathsToArray(fullRaw.NODE_PATH || ''); - - return { - stringified: { ...base, ...stringified }, - raw: fullRaw, - }; + const stringified = Object.fromEntries( + Object.entries(raw).map(([key, value]) => [key, JSON.stringify(value)]) + ); + return { raw, stringified }; } export const stringifyEnvs = (raw: Record): Record => @@ -57,13 +53,6 @@ export const stringifyProcessEnvs = (raw: Record): Record { ...babelDefault, // This override makes sure that we will never transpile babel further down then the browsers that storybook supports. // This is needed to support the mount property of the context described here: - // https://storybook.js.org/docs/writing-tests/interaction-testing#run-code-before-each-test + // https://storybook.js.org/docs/writing-tests/interaction-testing#run-code-before-each-story-in-a-file overrides: [ ...(babelDefault?.overrides ?? []), { diff --git a/code/core/src/core-server/server-channel/preview-initialized-channel.ts b/code/core/src/core-server/server-channel/preview-initialized-channel.ts index 0f689435aa1d..20b139c349ec 100644 --- a/code/core/src/core-server/server-channel/preview-initialized-channel.ts +++ b/code/core/src/core-server/server-channel/preview-initialized-channel.ts @@ -1,11 +1,10 @@ import type { Channel } from 'storybook/internal/channels'; import { PREVIEW_INITIALIZED } from 'storybook/internal/core-events'; import { type InitPayload, telemetry } from 'storybook/internal/telemetry'; +import { type CacheEntry, getLastEvents } from 'storybook/internal/telemetry'; +import { getSessionId } from 'storybook/internal/telemetry'; import type { CoreConfig, Options } from 'storybook/internal/types'; -import { type CacheEntry, getLastEvents } from '../../telemetry/event-cache'; -import { getSessionId } from '../../telemetry/session-id'; - export const makePayload = ( userAgent: string, lastInit: CacheEntry | undefined, diff --git a/code/core/src/core-server/utils/StoryIndexGenerator.ts b/code/core/src/core-server/utils/StoryIndexGenerator.ts index 168694a5659f..ac8c213981f9 100644 --- a/code/core/src/core-server/utils/StoryIndexGenerator.ts +++ b/code/core/src/core-server/utils/StoryIndexGenerator.ts @@ -617,7 +617,7 @@ export class StoryIndexGenerator { if (err && (err as { source: any }).source?.match(/mdast-util-mdx-jsx/g)) { logger.warn( `💡 This seems to be an MDX2 syntax error. Please refer to the MDX section in the following resource for assistance on how to fix this: ${picocolors.yellow( - 'https://storybook.js.org/docs/7/migration-guide?ref=error' + 'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#mdx2-upgrade' )}` ); } diff --git a/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts b/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts index 740720e49d9c..10f34e07eaba 100644 --- a/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts +++ b/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts @@ -44,7 +44,7 @@ export async function warnWhenUsingArgTypesRegex( )} and assigning explicit action with the ${picocolors.cyan( 'fn' )} function from ${picocolors.cyan('storybook/test')} instead: - https://storybook.js.org/docs/essentials/actions#via-storybooktest-fn-spy-function + https://storybook.js.org/docs/essentials/actions#via-storybooktest-fn-spies The build used by the addon for snapshot testing doesn't take the regex into account, which can cause hard to debug problems when a snapshot depends on the presence of action props. `; diff --git a/code/core/src/core-server/withTelemetry.ts b/code/core/src/core-server/withTelemetry.ts index d15cee2560d8..a7e77bd42e83 100644 --- a/code/core/src/core-server/withTelemetry.ts +++ b/code/core/src/core-server/withTelemetry.ts @@ -137,11 +137,9 @@ export async function sendTelemetryError( ); // If this is a StorybookError with sub-errors, send telemetry for each sub-error separately - if (error instanceof StorybookError && error.subErrors.length > 0) { + if (error && 'subErrors' in error && error.subErrors.length > 0) { for (const subError of error.subErrors) { - if (subError instanceof StorybookError) { - await sendTelemetryError(subError, eventType, options, blocking, error); - } + await sendTelemetryError(subError, eventType, options, blocking, error as StorybookError); } } } diff --git a/code/core/src/highlight/types.ts b/code/core/src/highlight/types.ts index 12f6a9f864f1..51f07aebcb16 100644 --- a/code/core/src/highlight/types.ts +++ b/code/core/src/highlight/types.ts @@ -11,7 +11,12 @@ export interface HighlightParameters { * @see https://storybook.js.org/docs/essentials/highlight#parameters */ highlight?: { - /** Remove the addon panel and disable the addon's behavior */ + /** + * Removes the tool and disables the feature's behavior. If you wish to turn off this feature + * for the entire Storybook, you can set the option in your `main.js|ts` configuration file. + * + * @see https://storybook.js.org/docs/essentials/highlight#disable + */ disable?: boolean; }; } diff --git a/code/core/src/manager-api/modules/stories.ts b/code/core/src/manager-api/modules/stories.ts index 21574e76ffd8..157817fc7909 100644 --- a/code/core/src/manager-api/modules/stories.ts +++ b/code/core/src/manager-api/modules/stories.ts @@ -618,13 +618,13 @@ export const init: ModuleFn = ({ ): Promise => { if (!ref) { const { index, filteredIndex } = store.getState(); - if (index) { + if (index && index[storyId]) { index[storyId] = { ...index[storyId], ...update, } as API_StoryEntry; } - if (filteredIndex) { + if (filteredIndex && filteredIndex[storyId]) { filteredIndex[storyId] = { ...filteredIndex[storyId], ...update, @@ -635,14 +635,18 @@ export const init: ModuleFn = ({ } } else { const { id: refId, index, filteredIndex }: any = ref; - index[storyId] = { - ...index[storyId], - ...update, - } as API_StoryEntry; - filteredIndex[storyId] = { - ...filteredIndex[storyId], - ...update, - } as API_StoryEntry; + if (index && index[storyId]) { + index[storyId] = { + ...index[storyId], + ...update, + } as API_StoryEntry; + } + if (filteredIndex && filteredIndex[storyId]) { + filteredIndex[storyId] = { + ...filteredIndex[storyId], + ...update, + } as API_StoryEntry; + } await fullAPI.updateRef(refId, { index, filteredIndex }); } }, diff --git a/code/core/src/manager/components/mobile/about/MobileAbout.tsx b/code/core/src/manager/components/mobile/about/MobileAbout.tsx index 8ef534e73ab8..0968d8c7c50e 100644 --- a/code/core/src/manager/components/mobile/about/MobileAbout.tsx +++ b/code/core/src/manager/components/mobile/about/MobileAbout.tsx @@ -61,7 +61,7 @@ export const MobileAbout: FC = () => { diff --git a/code/core/src/measure/types.ts b/code/core/src/measure/types.ts index ee6a46062a09..ab12ac3e25b9 100644 --- a/code/core/src/measure/types.ts +++ b/code/core/src/measure/types.ts @@ -5,7 +5,12 @@ export interface MeasureParameters { * @see https://storybook.js.org/docs/essentials/measure-and-outline#parameters */ measure?: { - /** Remove the addon panel and disable the addon's behavior */ + /** + * Removes the tool and disables the feature's behavior. If you wish to turn off this feature + * for the entire Storybook, you can set the option in your `main.js|ts` configuration file. + * + * @see https://storybook.js.org/docs/essentials/measure-and-outline#disable + */ disable?: boolean; }; } diff --git a/code/core/src/outline/types.ts b/code/core/src/outline/types.ts index 959fc653ea01..6702d5205d1f 100644 --- a/code/core/src/outline/types.ts +++ b/code/core/src/outline/types.ts @@ -5,7 +5,12 @@ export interface OutlineParameters { * @see https://storybook.js.org/docs/essentials/measure-and-outline#parameters */ outline?: { - /** Remove the addon panel and disable the addon's behavior */ + /** + * Removes the tool and disables the feature's behavior. If you wish to turn off this feature + * for the entire Storybook, you can set the option in your `main.js|ts` configuration file. + * + * @see https://storybook.js.org/docs/essentials/measure-and-outline#disable + */ disable?: boolean; }; } diff --git a/code/core/src/preview-api/modules/preview-web/parseArgsParam.ts b/code/core/src/preview-api/modules/preview-web/parseArgsParam.ts index bacf9f71b3ca..c6011e730621 100644 --- a/code/core/src/preview-api/modules/preview-web/parseArgsParam.ts +++ b/code/core/src/preview-api/modules/preview-web/parseArgsParam.ts @@ -114,7 +114,7 @@ export const parseArgsParam = (argsString: string): Args => { once.warn(dedent` Omitted potentially unsafe URL args. - More info: https://storybook.js.org/docs/writing-stories/args#setting-args-through-the-url?ref=error + More info: https://storybook.js.org/docs/writing-stories/args?ref=error#setting-args-through-the-url `); return acc; }, {} as Args); diff --git a/code/core/src/preview-errors.ts b/code/core/src/preview-errors.ts index a5418969d0bc..4fec858e2747 100644 --- a/code/core/src/preview-errors.ts +++ b/code/core/src/preview-errors.ts @@ -318,7 +318,8 @@ export class NextJsSharpError extends StorybookError { name: 'NextJsSharpError', category: Category.FRAMEWORK_NEXTJS, code: 1, - documentation: 'https://storybook.js.org/docs/get-started/nextjs#faq', + documentation: + 'https://storybook.js.org/docs/get-started/frameworks/nextjs#error-you-are-importing-avif-images-but-you-dont-have-sharp-installed-you-have-to-install-sharp-in-order-to-use-image-optimization-features-in-nextjs', message: dedent` You are importing avif images, but you don't have sharp installed. diff --git a/code/core/src/server-errors.ts b/code/core/src/server-errors.ts index 0e2edce795db..d163f611864d 100644 --- a/code/core/src/server-errors.ts +++ b/code/core/src/server-errors.ts @@ -309,7 +309,7 @@ export class GoogleFontsDownloadError extends StorybookError { category: Category.FRAMEWORK_NEXTJS, code: 1, documentation: - 'https://github.com/storybookjs/storybook/blob/next/code/frameworks/nextjs/README.md#nextjs-font-optimization', + 'https://storybook.js.org/docs/get-started/frameworks/nextjs#nextjs-font-optimization', message: dedent` Failed to fetch \`${data.fontFamily}\` from Google Fonts with URL: \`${data.url}\``, }); @@ -323,7 +323,7 @@ export class GoogleFontsLoadingError extends StorybookError { category: Category.FRAMEWORK_NEXTJS, code: 2, documentation: - 'https://github.com/storybookjs/storybook/blob/next/code/frameworks/nextjs/README.md#nextjs-font-optimization', + 'https://storybook.js.org/docs/get-started/frameworks/nextjs#nextjs-font-optimization', message: dedent` An error occurred when trying to load Google Fonts with URL \`${data.url}\`. @@ -374,12 +374,12 @@ export class MainFileMissingError extends StorybookError { const map = { storybook: { helperMessage: - 'You can pass a --config-dir flag to tell Storybook, where your main.js file is located at.', + 'You can pass a --config-dir flag to tell Storybook, where your main.js|ts file is located at.', documentation: 'https://storybook.js.org/docs/configure?ref=error', }, vitest: { helperMessage: - 'You can pass a configDir plugin option to tell where your main.js file is located at.', + 'You can pass a configDir plugin option to tell where your main.js|ts file is located at.', // TODO: add proper docs once available documentation: 'https://storybook.js.org/docs/configure?ref=error', }, @@ -392,7 +392,7 @@ export class MainFileMissingError extends StorybookError { documentation, message: dedent` No configuration files have been found in your configDir: ${picocolors.yellow(data.location)}. - Storybook needs a "main.js" file, please add it. + Storybook needs a "main.js|ts" file, please add it. ${helperMessage}`, }); @@ -489,7 +489,7 @@ export class AddonVitestPostinstallExistingSetupFileError extends StorybookError category: Category.CLI_INIT, isHandledError: true, code: 7, - documentation: `https://storybook.js.org/docs/writing-tests/integrations/vitest-addon#manual-setup`, + documentation: `https://storybook.js.org/docs/writing-tests/integrations/vitest-addon#manual-setup-advanced`, message: dedent` Found an existing Vitest setup file: ${data.filePath} Please refer to the documentation to complete the setup manually. @@ -505,7 +505,7 @@ export class AddonVitestPostinstallWorkspaceUpdateError extends StorybookError { category: Category.CLI_INIT, isHandledError: true, code: 8, - documentation: `https://storybook.js.org/docs/writing-tests/integrations/vitest-addon#manual-setup`, + documentation: `https://storybook.js.org/docs/writing-tests/integrations/vitest-addon#manual-setup-advanced`, message: dedent` Could not update existing Vitest workspace file: ${data.filePath} Please refer to the documentation to complete the setup manually. @@ -521,7 +521,7 @@ export class AddonVitestPostinstallConfigUpdateError extends StorybookError { category: Category.CLI_INIT, isHandledError: true, code: 9, - documentation: `https://storybook.js.org/docs/writing-tests/integrations/vitest-addon#manual-setup`, + documentation: `https://storybook.js.org/docs/writing-tests/integrations/vitest-addon#manual-setup-advanced`, message: dedent` Unable to update existing Vitest config file: ${data.filePath} Please refer to the documentation to complete the setup manually. diff --git a/code/core/src/telemetry/event-cache.test.ts b/code/core/src/telemetry/event-cache.test.ts index 08fef0a117e0..b45d125d0f8f 100644 --- a/code/core/src/telemetry/event-cache.test.ts +++ b/code/core/src/telemetry/event-cache.test.ts @@ -3,7 +3,9 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { cache } from 'storybook/internal/common'; -import { get, getLastEvents, getPrecedingUpgrade, set } from './event-cache'; +import type { CacheEntry } from './event-cache'; +import { getLastEvents, getPrecedingUpgrade, set } from './event-cache'; +import type { TelemetryEvent } from './types'; vi.mock('storybook/internal/common', { spy: true }); @@ -12,54 +14,94 @@ expect.addSnapshotSerializer({ test: (val) => typeof val !== 'string', }); +// Helper to create valid TelemetryEvent objects +const createTelemetryEvent = ( + eventType: TelemetryEvent['eventType'], + eventId: string, + overrides?: Partial +): TelemetryEvent => ({ + eventType, + eventId, + sessionId: 'test-session', + context: {}, + payload: {}, + ...overrides, +}); + describe('event-cache', () => { - const init = { body: { eventType: 'init', eventId: 'init' }, timestamp: 1 }; - const upgrade = { body: { eventType: 'upgrade', eventId: 'upgrade' }, timestamp: 2 }; - const dev = { body: { eventType: 'dev', eventId: 'dev' }, timestamp: 3 }; - const build = { body: { eventType: 'build', eventId: 'build' }, timestamp: 3 }; - const error = { body: { eventType: 'build', eventId: 'error' }, timestamp: 4 }; - const versionUpdate = { - body: { eventType: 'version-update', eventId: 'version-update' }, + const init: CacheEntry = { + body: createTelemetryEvent('init', 'init'), + timestamp: 1, + }; + const upgrade: CacheEntry = { + body: createTelemetryEvent('upgrade', 'upgrade'), + timestamp: 2, + }; + const dev: CacheEntry = { + body: createTelemetryEvent('dev', 'dev'), + timestamp: 3, + }; + const build: CacheEntry = { + body: createTelemetryEvent('build', 'build'), + timestamp: 3, + }; + const error: CacheEntry = { + body: createTelemetryEvent('build', 'error'), + timestamp: 4, + }; + const versionUpdate: CacheEntry = { + body: createTelemetryEvent('version-update', 'version-update'), timestamp: 5, }; describe('data handling', () => { it('errors', async () => { const preceding = await getPrecedingUpgrade({ - init: { timestamp: 1, body: { ...init.body, error: {} } }, + init: { + timestamp: 1, + body: { ...init.body, error: {} } as TelemetryEvent & { error: unknown }, + }, }); expect(preceding).toMatchInlineSnapshot(` { "timestamp": 1, "eventType": "init", - "eventId": "init" + "eventId": "init", + "sessionId": "test-session" } `); }); it('session IDs', async () => { const preceding = await getPrecedingUpgrade({ - init: { timestamp: 1, body: { ...init.body, sessionId: 100 } }, + init: { + timestamp: 1, + body: { ...init.body, sessionId: '100' }, + }, }); expect(preceding).toMatchInlineSnapshot(` { "timestamp": 1, "eventType": "init", "eventId": "init", - "sessionId": 100 + "sessionId": "100" } `); }); it('extra fields', async () => { const preceding = await getPrecedingUpgrade({ - init: { timestamp: 1, body: { ...init.body, foobar: 'baz' } }, + init: { + timestamp: 1, + body: { ...init.body, foobar: 'baz' } as TelemetryEvent & { foobar: string }, + }, }); expect(preceding).toMatchInlineSnapshot(` { "timestamp": 1, "eventType": "init", - "eventId": "init" + "eventId": "init", + "sessionId": "test-session" } `); }); @@ -77,7 +119,8 @@ describe('event-cache', () => { { "timestamp": 1, "eventType": "init", - "eventId": "init" + "eventId": "init", + "sessionId": "test-session" } `); }); @@ -88,7 +131,8 @@ describe('event-cache', () => { { "timestamp": 2, "eventType": "upgrade", - "eventId": "upgrade" + "eventId": "upgrade", + "sessionId": "test-session" } `); }); @@ -99,7 +143,8 @@ describe('event-cache', () => { { "timestamp": 2, "eventType": "upgrade", - "eventId": "upgrade" + "eventId": "upgrade", + "sessionId": "test-session" } `); }); @@ -127,8 +172,8 @@ describe('event-cache', () => { }); it('both init and upgrade with intervening dev', async () => { - const secondUpgrade = { - body: { eventType: 'upgrade', eventId: 'secondUpgrade' }, + const secondUpgrade: CacheEntry = { + body: createTelemetryEvent('upgrade', 'secondUpgrade'), timestamp: 4, }; const preceding = await getPrecedingUpgrade({ init, dev, upgrade: secondUpgrade }); @@ -136,14 +181,15 @@ describe('event-cache', () => { { "timestamp": 4, "eventType": "upgrade", - "eventId": "secondUpgrade" + "eventId": "secondUpgrade", + "sessionId": "test-session" } `); }); it('both init and upgrade with non-intervening dev', async () => { - const earlyDev = { - body: { eventType: 'dev', eventId: 'earlyDev' }, + const earlyDev: CacheEntry = { + body: createTelemetryEvent('dev', 'earlyDev'), timestamp: -1, }; const preceding = await getPrecedingUpgrade({ dev: earlyDev, init, upgrade }); @@ -151,7 +197,8 @@ describe('event-cache', () => { { "timestamp": 2, "eventType": "upgrade", - "eventId": "upgrade" + "eventId": "upgrade", + "sessionId": "test-session" } `); }); @@ -174,7 +221,8 @@ describe('event-cache', () => { { "timestamp": 2, "eventType": "upgrade", - "eventId": "upgrade" + "eventId": "upgrade", + "sessionId": "test-session" } `); }); @@ -192,46 +240,28 @@ describe('event-cache', () => { it('getLastEvents waits for pending set operations to complete', async () => { const initialData = { - init: { timestamp: 1, body: { eventType: 'init', eventId: 'init-1' } }, + init: { timestamp: 1, body: createTelemetryEvent('init', 'init-1') }, }; const updatedData = { - init: { timestamp: 1, body: { eventType: 'init', eventId: 'init-1' } }, - upgrade: { timestamp: 2, body: { eventType: 'upgrade', eventId: 'upgrade-1' } }, + init: { timestamp: 1, body: createTelemetryEvent('init', 'init-1') }, + upgrade: { timestamp: 2, body: createTelemetryEvent('upgrade', 'upgrade-1') }, }; - // Use a simple delay to simulate async operations - let setGetResolved = false; - let setSetResolved = false; + // Mock cache.get to return initial data first, then updated data + cacheGetMock + .mockResolvedValueOnce(initialData) // First call in setHelper + .mockResolvedValueOnce(updatedData); // Second call in getLastEvents - cacheGetMock.mockImplementationOnce(async () => { - while (!setGetResolved) { - await new Promise((resolve) => setTimeout(resolve, 10)); - } - return initialData; - }); - - cacheSetMock.mockImplementationOnce(async () => { - while (!setSetResolved) { - await new Promise((resolve) => setTimeout(resolve, 10)); - } - }); + // Mock cache.set to resolve immediately + cacheSetMock.mockResolvedValue(undefined); - // Mock cache.get to return updated data after set completes - cacheGetMock.mockResolvedValueOnce(updatedData); - - // Start a set operation (this will be pending) - const setPromiseResult = set('upgrade', { eventType: 'upgrade', eventId: 'upgrade-1' }); + // Start a set operation (this will be queued and processed) + const setPromiseResult = set('upgrade', createTelemetryEvent('upgrade', 'upgrade-1')); // Immediately call getLastEvents() - it should wait for set() to complete const getPromise = getLastEvents(); - // Verify that getLastEvents hasn't resolved yet (it's waiting) - await new Promise((resolve) => setTimeout(resolve, 50)); - - // Resolve the set operations - setGetResolved = true; - await new Promise((resolve) => setTimeout(resolve, 50)); - setSetResolved = true; + // Wait for set operation to complete await setPromiseResult; // Now getLastEvents should complete and return the updated data @@ -242,5 +272,79 @@ describe('event-cache', () => { expect(cacheGetMock).toHaveBeenCalledTimes(2); // Once in setHelper, once in getLastEvents expect(cacheSetMock).toHaveBeenCalledTimes(1); }); + + it('queues multiple set operations sequentially', async () => { + const initialData = {}; + const afterFirst = { + init: { timestamp: 1, body: createTelemetryEvent('init', 'init-1') }, + }; + const afterSecond = { + init: { timestamp: 1, body: createTelemetryEvent('init', 'init-1') }, + upgrade: { timestamp: 2, body: createTelemetryEvent('upgrade', 'upgrade-1') }, + }; + const afterThird = { + init: { timestamp: 1, body: createTelemetryEvent('init', 'init-1') }, + upgrade: { timestamp: 2, body: createTelemetryEvent('upgrade', 'upgrade-1') }, + dev: { timestamp: 3, body: createTelemetryEvent('dev', 'dev-1') }, + }; + + // Mock cache.get to return data in sequence + cacheGetMock + .mockResolvedValueOnce(initialData) // First set: get initial + .mockResolvedValueOnce(afterFirst) // Second set: get after first + .mockResolvedValueOnce(afterSecond) // Third set: get after second + .mockResolvedValueOnce(afterThird); // getLastEvents: get after third + + // Mock cache.set to resolve immediately + cacheSetMock.mockResolvedValue(undefined); + + // Queue multiple set operations + const set1 = set('init', createTelemetryEvent('init', 'init-1')); + const set2 = set('upgrade', createTelemetryEvent('upgrade', 'upgrade-1')); + const set3 = set('dev', createTelemetryEvent('dev', 'dev-1')); + + // Wait for all operations to complete + await Promise.all([set1, set2, set3]); + + // Now getLastEvents should return the final state + const result = await getLastEvents(); + + // Verify all operations were processed sequentially + expect(result).toEqual(afterThird); + expect(cacheGetMock).toHaveBeenCalledTimes(4); // 3 sets + 1 getLastEvents + expect(cacheSetMock).toHaveBeenCalledTimes(3); // One for each set + }); + + it('handles errors in queued operations', async () => { + const initialData = { + init: { timestamp: 1, body: createTelemetryEvent('init', 'init-1') }, + }; + const afterDev = { + init: { timestamp: 1, body: createTelemetryEvent('init', 'init-1') }, + dev: { timestamp: 3, body: createTelemetryEvent('dev', 'dev-1') }, + }; + + // First operation will fail + cacheGetMock.mockResolvedValueOnce(initialData); + cacheSetMock.mockRejectedValueOnce(new Error('Cache write failed')); + + // Queue an operation that will fail + const failedOperation = set('upgrade', createTelemetryEvent('upgrade', 'upgrade-1')); + await expect(failedOperation).rejects.toThrow('Cache write failed'); + + // Wait a bit to ensure queue processing completes + await new Promise((resolve) => setTimeout(resolve, 10)); + + // Verify subsequent operations can still be queued and succeed + cacheGetMock.mockResolvedValueOnce(initialData); + cacheSetMock.mockResolvedValueOnce(undefined); + cacheGetMock.mockResolvedValueOnce(afterDev); + + await expect(set('dev', createTelemetryEvent('dev', 'dev-1'))).resolves.toBeUndefined(); + + // Verify the successful operation was processed + const result = await getLastEvents(); + expect(result).toEqual(afterDev); + }); }); }); diff --git a/code/core/src/telemetry/event-cache.ts b/code/core/src/telemetry/event-cache.ts index 6f7516afdfdd..06654f28be48 100644 --- a/code/core/src/telemetry/event-cache.ts +++ b/code/core/src/telemetry/event-cache.ts @@ -14,7 +14,7 @@ export interface CacheEntry { body: TelemetryEvent; } -let operation: Promise = Promise.resolve(); +let processingPromise: Promise = Promise.resolve(); const setHelper = async (eventType: EventType, body: TelemetryEvent) => { const lastEvents = (await cache.get('lastEvents')) || {}; @@ -22,10 +22,15 @@ const setHelper = async (eventType: EventType, body: TelemetryEvent) => { await cache.set('lastEvents', lastEvents); }; -export const set = async (eventType: EventType, body: any) => { - await operation; - operation = setHelper(eventType, body); - return operation; +export const set = (eventType: EventType, body: TelemetryEvent): Promise => { + const run = processingPromise.then(async () => { + await setHelper(eventType, body); + }); + + // Keep the chain alive even if this operation rejects, so later callers still queue + processingPromise = run.catch(() => {}); + + return run; }; export const get = async (eventType: EventType): Promise => { @@ -35,9 +40,7 @@ export const get = async (eventType: EventType): Promise export const getLastEvents = async (): Promise> => { // Wait for any pending set operations to complete before reading - // This prevents race conditions where getLastEvents() reads stale data - // while a set() operation is still in progress - await operation; + await processingPromise; return (await cache.get('lastEvents')) || {}; }; @@ -54,16 +57,19 @@ const upgradeFields = (event: CacheEntry): UpgradeSummary => { const UPGRADE_EVENTS: EventType[] = ['init', 'upgrade']; const RUN_EVENTS: EventType[] = ['build', 'dev', 'error']; -const lastEvent = (lastEvents: Record, eventTypes: EventType[]) => { +const lastEvent = (lastEvents: Partial>, eventTypes: EventType[]) => { const descendingEvents = eventTypes .map((eventType) => lastEvents?.[eventType]) - .filter(Boolean) + .filter((event): event is CacheEntry => Boolean(event)) .sort((a, b) => b.timestamp - a.timestamp); return descendingEvents.length > 0 ? descendingEvents[0] : undefined; }; -export const getPrecedingUpgrade = async (events: any = undefined) => { - const lastEvents = events || (await cache.get('lastEvents')) || {}; +export const getPrecedingUpgrade = async ( + events: Partial> | undefined = undefined +) => { + const lastEvents = + events || ((await cache.get('lastEvents')) as Partial>) || {}; const lastUpgradeEvent = lastEvent(lastEvents, UPGRADE_EVENTS); const lastRunEvent = lastEvent(lastEvents, RUN_EVENTS); diff --git a/code/core/src/telemetry/index.ts b/code/core/src/telemetry/index.ts index 71224cdedde1..bfa5840eb1bd 100644 --- a/code/core/src/telemetry/index.ts +++ b/code/core/src/telemetry/index.ts @@ -16,7 +16,9 @@ export * from './sanitize'; export * from './error-collector'; -export { getPrecedingUpgrade } from './event-cache'; +export { getPrecedingUpgrade, getLastEvents, type CacheEntry } from './event-cache'; + +export { getSessionId } from './session-id'; export { addToGlobalContext } from './telemetry'; diff --git a/code/core/src/viewport/types.ts b/code/core/src/viewport/types.ts index 2388b0949d9b..d53de5771d0c 100644 --- a/code/core/src/viewport/types.ts +++ b/code/core/src/viewport/types.ts @@ -35,10 +35,10 @@ export interface ViewportParameters { */ viewport?: { /** - * Remove the addon panel and disable the addon's behavior . If you wish to turn off this addon - * for the entire Storybook, you should do so when registering addon-essentials + * Removes the tool and disables the feature's behavior. If you wish to turn off this feature + * for the entire Storybook, you can set the option in your `main.js|ts` configuration file. * - * @see https://storybook.js.org/docs/essentials/index#disabling-addons + * @see https://storybook.js.org/docs/essentials/viewport#disable */ disable?: boolean; diff --git a/code/frameworks/angular/src/client/public-types.ts b/code/frameworks/angular/src/client/public-types.ts index 2c32a1b8ec52..953c11e30f3a 100644 --- a/code/frameworks/angular/src/client/public-types.ts +++ b/code/frameworks/angular/src/client/public-types.ts @@ -20,7 +20,7 @@ export type { AngularRenderer }; /** * Metadata to configure the stories for a component. * - * @see [Default export](https://storybook.js.org/docs/formats/component-story-format/#default-export) + * @see [Default export](https://storybook.js.org/docs/api/csf#default-export) */ export type Meta = ComponentAnnotations< AngularRenderer, @@ -30,7 +30,7 @@ export type Meta = ComponentAnnotations< /** * Story function that represents a CSFv2 component example. * - * @see [Named Story exports](https://storybook.js.org/docs/formats/component-story-format/#named-story-exports) + * @see [Named Story exports](https://storybook.js.org/docs/api/csf#named-story-exports) */ export type StoryFn = AnnotatedStoryFn< AngularRenderer, @@ -40,7 +40,7 @@ export type StoryFn = AnnotatedStoryFn< /** * Story object that represents a CSFv3 component example. * - * @see [Named Story exports](https://storybook.js.org/docs/formats/component-story-format/#named-story-exports) + * @see [Named Story exports](https://storybook.js.org/docs/api/csf#named-story-exports) */ export type StoryObj = StoryAnnotations< AngularRenderer, diff --git a/code/frameworks/angular/template/stories/others/ngx-translate/README.mdx b/code/frameworks/angular/template/stories/others/ngx-translate/README.mdx index 5bb491b3a5ce..c011a4ab4cf6 100644 --- a/code/frameworks/angular/template/stories/others/ngx-translate/README.mdx +++ b/code/frameworks/angular/template/stories/others/ngx-translate/README.mdx @@ -9,7 +9,7 @@ import { Meta } from '@storybook/addon-docs/blocks'; There are several ways to configure ngx-translate in storybook which will depend on your context. Here is a simple example with a storybook decorator that you can place in the `preview.ts` or locally on the stories. -[See the doc on decorators](https://storybook.js.org/docs/angular/writing-stories/decorators) +[See the doc on decorators](https://storybook.js.org/docs/writing-stories/decorators?renderer=angular) ```ts import { HttpClient, HttpClientModule } from '@angular/common/http'; diff --git a/code/frameworks/html-vite/template/cli/ts/Header.stories.ts b/code/frameworks/html-vite/template/cli/ts/Header.stories.ts index ddd6f5d3a230..033bb1ef3a55 100644 --- a/code/frameworks/html-vite/template/cli/ts/Header.stories.ts +++ b/code/frameworks/html-vite/template/cli/ts/Header.stories.ts @@ -14,7 +14,6 @@ const meta = { // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout layout: 'fullscreen', }, - // More on argTypes: https://storybook.js.org/docs/api/argtypes args: { onLogin: fn(), onLogout: fn(), diff --git a/code/frameworks/nextjs-vite/README.md b/code/frameworks/nextjs-vite/README.md index 5c8d9577dd13..c7c4709a982f 100644 --- a/code/frameworks/nextjs-vite/README.md +++ b/code/frameworks/nextjs-vite/README.md @@ -1,6 +1,6 @@ # Storybook for Next.js with Vite Builder -See [documentation](https://storybook.js.org/docs/get-started/frameworks/nextjs?renderer=react&ref=readme) for installation instructions, usage examples, APIs, and more. +See [documentation](https://storybook.js.org/docs/get-started/frameworks/nextjs-vite?renderer=react&ref=readme) for installation instructions, usage examples, APIs, and more. ## Acknowledgements diff --git a/code/frameworks/nextjs-vite/package.json b/code/frameworks/nextjs-vite/package.json index 7e8dd520d32d..e733d0caeee3 100644 --- a/code/frameworks/nextjs-vite/package.json +++ b/code/frameworks/nextjs-vite/package.json @@ -79,7 +79,7 @@ "@storybook/react": "workspace:*", "@storybook/react-vite": "workspace:*", "styled-jsx": "5.1.6", - "vite-plugin-storybook-nextjs": "^3.1.0" + "vite-plugin-storybook-nextjs": "^3.1.7" }, "devDependencies": { "@types/node": "^22.0.0", diff --git a/code/frameworks/nextjs-vite/src/types.ts b/code/frameworks/nextjs-vite/src/types.ts index cf5cb8e1a524..881e70c45510 100644 --- a/code/frameworks/nextjs-vite/src/types.ts +++ b/code/frameworks/nextjs-vite/src/types.ts @@ -43,7 +43,7 @@ export interface NextJsParameters { /** * Next.js framework configuration * - * @see https://storybook.js.org/docs/get-started/frameworks/nextjs + * @see https://storybook.js.org/docs/get-started/frameworks/nextjs-vite */ nextjs?: { /** diff --git a/code/frameworks/nextjs/src/export-mocks/headers/index.ts b/code/frameworks/nextjs/src/export-mocks/headers/index.ts index f1e27b49c646..0ae9091dd927 100644 --- a/code/frameworks/nextjs/src/export-mocks/headers/index.ts +++ b/code/frameworks/nextjs/src/export-mocks/headers/index.ts @@ -1,4 +1,3 @@ -import { draftMode as originalDraftMode } from 'next/dist/server/request/draft-mode'; import * as headers from 'next/dist/server/request/headers'; import { fn } from 'storybook/test'; @@ -10,5 +9,18 @@ export { headers } from './headers'; export { cookies } from './cookies'; // passthrough mocks - keep original implementation but allow for spying -const draftMode = fn(originalDraftMode ?? (headers as any).draftMode).mockName('draftMode'); +// In Next.js 14, draftMode is exported from 'next/dist/client/components/headers' +// In Next.js 15+, draftMode is exported from 'next/dist/server/request/draft-mode' +// The webpack alias handles this, but we need to avoid the top-level import +// to prevent build errors when the module doesn't exist +let originalDraftMode: any; +try { + // This will be resolved by webpack alias to the correct location based on Next.js version + originalDraftMode = require('next/dist/server/request/draft-mode').draftMode; +} catch { + // Fallback to the location in the headers module (Next.js 14) + originalDraftMode = (headers as any).draftMode; +} + +const draftMode = fn(originalDraftMode).mockName('draftMode'); export { draftMode }; diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index 65c084a79422..668bda4b2ed1 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -49,7 +49,7 @@ "!src/**/*" ], "dependencies": { - "@joshwooding/vite-plugin-react-docgen-typescript": "0.6.1", + "@joshwooding/vite-plugin-react-docgen-typescript": "^0.6.3", "@rollup/pluginutils": "^5.0.2", "@storybook/builder-vite": "workspace:*", "@storybook/react": "workspace:*", diff --git a/code/frameworks/react-vite/src/types.ts b/code/frameworks/react-vite/src/types.ts index 7439f0210032..938139710843 100644 --- a/code/frameworks/react-vite/src/types.ts +++ b/code/frameworks/react-vite/src/types.ts @@ -45,7 +45,7 @@ type StorybookConfigFramework = { /** * Enable the experimental `.test` function in CSF Next * - * @see https://storybook.js.org/docs/10/api/main-config/main-config-features#experimentalTestSyntax + * @see https://storybook.js.org/docs/api/main-config/main-config-features#experimentaltestsyntax */ experimentalTestSyntax?: boolean; }; diff --git a/code/lib/cli-storybook/src/automigrate/fixes/eslint-plugin.ts b/code/lib/cli-storybook/src/automigrate/fixes/eslint-plugin.ts index e8dc4549e3d8..7875547dd878 100644 --- a/code/lib/cli-storybook/src/automigrate/fixes/eslint-plugin.ts +++ b/code/lib/cli-storybook/src/automigrate/fixes/eslint-plugin.ts @@ -24,7 +24,7 @@ interface EslintPluginRunOptions { */ export const eslintPlugin: Fix = { id: 'eslintPlugin', - link: 'https://storybook.js.org/docs/9/configure/integration/eslint-plugin', + link: 'https://storybook.js.org/docs/configure/integration/eslint-plugin', async check({ packageManager }) { const { diff --git a/code/lib/cli-storybook/src/automigrate/fixes/nextjs-to-nextjs-vite.ts b/code/lib/cli-storybook/src/automigrate/fixes/nextjs-to-nextjs-vite.ts index 033b9499f82d..e96dfc7b31df 100644 --- a/code/lib/cli-storybook/src/automigrate/fixes/nextjs-to-nextjs-vite.ts +++ b/code/lib/cli-storybook/src/automigrate/fixes/nextjs-to-nextjs-vite.ts @@ -139,7 +139,7 @@ export const nextjsToNextjsVite: Fix = { logger.step('Migration completed successfully!'); logger.log( - `For more information, see: https://storybook.js.org/docs/nextjs/get-started/nextjs-vite` + `For more information, see: https://storybook.js.org/docs/get-started/frameworks/nextjs-vite` ); }, }; diff --git a/code/lib/cli-storybook/src/automigrate/index.ts b/code/lib/cli-storybook/src/automigrate/index.ts index 9078efc00d7c..040f427ba5ec 100644 --- a/code/lib/cli-storybook/src/automigrate/index.ts +++ b/code/lib/cli-storybook/src/automigrate/index.ts @@ -84,7 +84,7 @@ export const doAutomigrate = async (options: AutofixOptionsFromCLI) => { ); if (hasAppliedFixes && !options.skipInstall) { - packageManager.installDependencies(); + await packageManager.installDependencies(); } if (outcome && !options.skipDoctor) { diff --git a/code/lib/cli-storybook/src/codemod/csf-factories.ts b/code/lib/cli-storybook/src/codemod/csf-factories.ts index ec089e3f087c..98c244f70e0c 100644 --- a/code/lib/cli-storybook/src/codemod/csf-factories.ts +++ b/code/lib/cli-storybook/src/codemod/csf-factories.ts @@ -62,7 +62,7 @@ export const csfFactories: CommandFix = { However, we cannot broadly recommend it for all projects, because it might not work in some monorepo setups or if you have an outdated tsconfig, use custom paths, or have type alias plugins configured in your project. You can always rerun this codemod and select another option to update your code later. - More info: ${picocolors.yellow('https://storybook.js.org/docs/10/api/csf/csf-next#subpath-imports?ref=upgrade')} + More info: ${picocolors.yellow('https://storybook.js.org/docs/api/csf/csf-next?ref=upgrade#previewmeta')} `); useSubPathImports = await prompt.select({ @@ -117,7 +117,7 @@ export const csfFactories: CommandFix = { You can now run Storybook with the new CSF factories format. For more info, check out the docs: - ${picocolors.yellow('https://storybook.js.org/docs/10/api/csf/csf-next?ref=upgrade')} + ${picocolors.yellow('https://storybook.js.org/docs/api/csf/csf-next?ref=upgrade')} ` ); }, diff --git a/code/lib/cli-storybook/src/warn.ts b/code/lib/cli-storybook/src/warn.ts index 7de253963cef..ad8a16b43359 100644 --- a/code/lib/cli-storybook/src/warn.ts +++ b/code/lib/cli-storybook/src/warn.ts @@ -20,7 +20,7 @@ export const warn = async ({ hasTSDependency }: Options) => { ); logger.warn('Storybook will continue as though this is a JavaScript project.'); logger.info( - 'For more information, see: https://storybook.js.org/docs/configurations/typescript-config/' + 'For more information, see: https://storybook.js.org/docs/configure/integration/typescript' ); } } diff --git a/code/lib/create-storybook/src/commands/AddonConfigurationCommand.ts b/code/lib/create-storybook/src/commands/AddonConfigurationCommand.ts index fced261362fd..222710d0f186 100644 --- a/code/lib/create-storybook/src/commands/AddonConfigurationCommand.ts +++ b/code/lib/create-storybook/src/commands/AddonConfigurationCommand.ts @@ -10,7 +10,7 @@ import { TelemetryService } from '../services'; const ADDON_INSTALLATION_INSTRUCTIONS = { '@storybook/addon-vitest': - 'https://storybook.js.org/docs/writing-tests/integrations/vitest-addon#manual-setup', + 'https://storybook.js.org/docs/writing-tests/integrations/vitest-addon#manual-setup-advanced', } as { [key: string]: string }; type ExecuteAddonConfigurationParams = { diff --git a/code/lib/create-storybook/src/services/FeatureCompatibilityService.ts b/code/lib/create-storybook/src/services/FeatureCompatibilityService.ts index b8c52c0cbba8..032d73bcaecf 100644 --- a/code/lib/create-storybook/src/services/FeatureCompatibilityService.ts +++ b/code/lib/create-storybook/src/services/FeatureCompatibilityService.ts @@ -7,7 +7,6 @@ const ONBOARDING_PROJECT_TYPES: ProjectType[] = [ ProjectType.REACT, ProjectType.REACT_SCRIPTS, ProjectType.REACT_NATIVE_WEB, - ProjectType.REACT_PROJECT, ProjectType.NEXTJS, ProjectType.VUE3, ProjectType.ANGULAR, diff --git a/code/lib/create-storybook/src/services/ProjectTypeService.test.ts b/code/lib/create-storybook/src/services/ProjectTypeService.test.ts index 1d0609a95b14..5c15dcc1b9db 100644 --- a/code/lib/create-storybook/src/services/ProjectTypeService.test.ts +++ b/code/lib/create-storybook/src/services/ProjectTypeService.test.ts @@ -68,17 +68,6 @@ describe('ProjectTypeService', () => { expect(result).toBe(ProjectType.NEXTJS); }); - it('detects REACT_PROJECT via peerDependencies', async () => { - (pm as any).primaryPackageJson.packageJson = { - peerDependencies: { react: '^18.0.0' }, - }; - const service = new ProjectTypeService(pm); - // @ts-expect-error private method spy - vi.spyOn(service, 'isNxProject').mockReturnValue(false); - const result = await service.autoDetectProjectType({ html: false } as CommandOptions); - expect(result).toBe(ProjectType.REACT_PROJECT); - }); - it('detects VUE3 when vue major is 3', async () => { (pm as any).primaryPackageJson.packageJson = { dependencies: { vue: '^3.2.0' }, diff --git a/code/lib/create-storybook/src/services/ProjectTypeService.ts b/code/lib/create-storybook/src/services/ProjectTypeService.ts index fe25cb5fda2a..87514b976ad0 100644 --- a/code/lib/create-storybook/src/services/ProjectTypeService.ts +++ b/code/lib/create-storybook/src/services/ProjectTypeService.ts @@ -74,13 +74,6 @@ export class ProjectTypeService { return dependencies?.every(Boolean) ?? true; }, }, - { - preset: ProjectType.REACT_PROJECT, - peerDependencies: ['react'], - matcherFunction: ({ peerDependencies }) => { - return peerDependencies?.every(Boolean) ?? true; - }, - }, { preset: ProjectType.REACT_NATIVE, dependencies: ['react-native', 'react-native-scripts'], diff --git a/code/package.json b/code/package.json index 7e4a81d260db..96b89b0f82e6 100644 --- a/code/package.json +++ b/code/package.json @@ -248,5 +248,6 @@ "Dependency Upgrades" ] ] - } + }, + "deferredNextVersion": "10.2.0-alpha.7" } diff --git a/code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx b/code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx index 2b4272a0a0c8..9c8662fa2ace 100644 --- a/code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx +++ b/code/renderers/react/src/componentManifest/generateCodeSnippet.test.tsx @@ -59,6 +59,21 @@ test('Default', () => { ); }); +test('Synthesizes self-closing when no children', () => { + const input = dedent` + import type { Meta } from '@storybook/react'; + import { Button } from '@design-system/button'; + + const meta: Meta = { + component: Button, + }; + export default meta; + + export const NoChildren: Story = {}; + `; + expect(generateExample(input)).toMatchInlineSnapshot(`"const NoChildren = () => ;", - "summary": undefined, - }, - { - "description": undefined, - "name": "Secondary", - "snippet": "const Secondary = () => ;", - "summary": undefined, - }, - { - "description": undefined, - "name": "Large", - "snippet": "const Large = () => ;", - "summary": undefined, - }, - { - "description": undefined, - "name": "Small", - "snippet": "const Small = () => ;", - "summary": undefined, + "size": { + "defaultValue": { + "computed": false, + "value": "'medium'", + }, + "description": "", + "required": false, + "tsType": { + "elements": [ + { + "name": "literal", + "value": "'small'", + }, + { + "name": "literal", + "value": "'medium'", + }, + { + "name": "literal", + "value": "'large'", + }, + ], + "name": "union", + "raw": "'small' | 'medium' | 'large'", + }, }, - ], - "summary": undefined, + }, }, - "example-header": { - "description": "Description from meta and very long.", - "error": undefined, - "id": "example-header", - "import": "import { Header } from "some-package";", - "jsDocTags": { - "summary": [ - "Component summary", - ], + "stories": [ + { + "description": undefined, + "name": "Primary", + "snippet": "const Primary = () => ;\\n", + code: "const Primary = () => ;\\n", + code: "const Secondary = () => + ); +} +``` + +```ts filename="src/components/Button.ts" renderer="react" language="ts" +// This import will work in Storybook +import styles from './Button.module.css'; +// Sass/Scss modules are also supported +// import styles from './Button.module.scss' +// import styles from './Button.module.sass' + +export function Button() { + return ( + + ); +} +``` diff --git a/docs/_snippets/nextjs-styling-sass-config.md b/docs/_snippets/nextjs-styling-sass-config.md new file mode 100644 index 000000000000..90b636fd9494 --- /dev/null +++ b/docs/_snippets/nextjs-styling-sass-config.md @@ -0,0 +1,25 @@ +```js filename="next.config.js" language="js" renderer="react" +import path from 'node:path'; + +export default { + // Any options here are included in Sass compilation for your stories + sassOptions: { + includePaths: [path.join(process.cwd(), 'styles')], + }, +}; +``` + +```ts filename="next.config.ts" language="ts" renderer="react" +import type { NextConfig } from 'next'; + +import * as path from 'node:path'; + +const config: NextConfig = { + // Any options here are included in Sass compilation for your stories + sassOptions: { + includePaths: [path.join(process.cwd(), 'styles')], + }, +}; + +export default config; +``` diff --git a/docs/_snippets/nextjs-styling-sass-preview.md b/docs/_snippets/nextjs-styling-sass-preview.md new file mode 100644 index 000000000000..f4f29374d43b --- /dev/null +++ b/docs/_snippets/nextjs-styling-sass-preview.md @@ -0,0 +1,7 @@ +```js filename=".storybook/preview.js" language="js" renderer="react" +import '../styles/globals.scss'; +``` + +```ts filename=".storybook/preview.ts" language="ts" renderer="react" +import '../styles/globals.scss'; +``` diff --git a/docs/_snippets/nextjs-styling-styled-jsx-component.md b/docs/_snippets/nextjs-styling-styled-jsx-component.md new file mode 100644 index 000000000000..672625479c2c --- /dev/null +++ b/docs/_snippets/nextjs-styling-styled-jsx-component.md @@ -0,0 +1,63 @@ +```js filename="src/components/HelloWorld.js" renderer="react" language="js" +// This will work in Storybook +function HelloWorld() { + return ( +
+ Hello world +

scoped!

+ + +
+ ); +} + +export default HelloWorld; +``` + +```ts filename="src/components/HelloWorld.ts" renderer="react" language="ts" +// This will work in Storybook +function HelloWorld() { + return ( +
+ Hello world +

scoped!

+ + +
+ ); +} + +export default HelloWorld; +``` diff --git a/docs/_snippets/nextjs-styling-tailwind.md b/docs/_snippets/nextjs-styling-tailwind.md new file mode 100644 index 000000000000..fead37d5ca49 --- /dev/null +++ b/docs/_snippets/nextjs-styling-tailwind.md @@ -0,0 +1,7 @@ +```js filename=".storybook/preview.js" language="js" renderer="react" +import '../app/globals.css'; +``` + +```ts filename=".storybook/preview.ts" language="ts" renderer="react" +import '../app/globals.css'; +``` diff --git a/docs/_snippets/react-native-web-vite-add-framework.md b/docs/_snippets/react-native-web-vite-add-framework.md index 764fa47df059..e3946dc1f8d8 100644 --- a/docs/_snippets/react-native-web-vite-add-framework.md +++ b/docs/_snippets/react-native-web-vite-add-framework.md @@ -1,4 +1,4 @@ -```js filename=".storybook/main.js" renderer="react-native-web" language="js" +```js filename=".storybook/main.js" renderer="react" language="js" export default { addons: [ '@storybook/addon-react-native-web', // 👈 Remove the addon @@ -8,7 +8,7 @@ export default { }; ``` -```ts filename=".storybook/main.ts" renderer="react-native-web" language="ts" +```ts filename=".storybook/main.ts" renderer="react" language="ts" import type { StorybookConfig } from '@storybook/react-native-web-vite'; const config: StorybookConfig = { diff --git a/docs/_snippets/react-native-web-vite-install.md b/docs/_snippets/react-native-web-vite-install.md index 719993c04e77..76927ec1956f 100644 --- a/docs/_snippets/react-native-web-vite-install.md +++ b/docs/_snippets/react-native-web-vite-install.md @@ -1,11 +1,11 @@ -```shell renderer="react-native-web" language="js" packageManager="npm" +```shell renderer="common" language="sh" packageManager="npm" npm install --save-dev @storybook/react-native-web-vite vite ``` -```shell renderer="react-native-web" language="js" packageManager="pnpm" +```shell renderer="common" language="sh" packageManager="pnpm" pnpm add --save-dev @storybook/react-native-web-vite vite ``` -```shell renderer="react-native-web" language="js" packageManager="yarn" +```shell renderer="common" language="sh" packageManager="yarn" yarn add --dev @storybook/react-native-web-vite vite ``` diff --git a/docs/get-started/frameworks/angular.mdx b/docs/get-started/frameworks/angular.mdx index 7804057956e4..2493f964c5b5 100644 --- a/docs/get-started/frameworks/angular.mdx +++ b/docs/get-started/frameworks/angular.mdx @@ -14,7 +14,7 @@ To install Storybook in an existing Angular project, run this command in your pr -You can then get started [writing stories](/docs/get-started/whats-a-story/), [running tests](/docs/writing-tests/) and [documenting your components](/docs/writing-docs/). For more control over the installation process, refer to the [installation guide](/docs/install/). +You can then get started [writing stories](../whats-a-story.mdx), [running tests](../../writing-tests/index.mdx) and [documenting your components](../../writing-docs/index.mdx). For more control over the installation process, refer to the [installation guide](../install.mdx). ### Requirements @@ -46,7 +46,7 @@ You will find the output in the configured `outputDir` (default is `dist/storybo ## Configure -To make the most out of Storybook in your Angular project, you can set up Compodoc integration and Storybook [decorators](/docs/writing-stories/decorators/) based on your project needs. +To make the most out of Storybook in your Angular project, you can set up Compodoc integration and Storybook [decorators](../../writing-stories/decorators.mdx) based on your project needs. ### Compodoc @@ -122,7 +122,7 @@ export default preview; ### Application-wide providers -If your component relies on application-wide providers, like the ones defined by [`BrowserAnimationsModule`](https://angular.dev/api/platform-browser/animations/BrowserAnimationsModule) or any other modules that use the forRoot pattern to provide a [`ModuleWithProviders`](https://angular.dev/api/core/ModuleWithProviders), you can apply the `applicationConfig` [decorator](../../writing-stories/decorators.mdx) to all stories for that component. This will provide them with the [bootstrapApplication function](https://angular.io/guide/standalone-components#configuring-dependency-injection), used to bootstrap the component in Storybook. +If your component relies on application-wide providers, like the ones defined by [`BrowserAnimationsModule`](https://angular.dev/api/platform-browser/animations/BrowserAnimationsModule) or any other modules that use the forRoot pattern to provide a [`ModuleWithProviders`](https://angular.dev/api/core/ModuleWithProviders), you can apply the `applicationConfig` [decorator](../../writing-stories/decorators.mdx) to all stories for that component. This will provide them with the [bootstrapApplication function](https://angular.dev/api/platform-browser/bootstrapApplication), used to bootstrap the component in Storybook. ```ts title="ChipsModule.stories.ts" import { Meta, applicationConfig, StoryObj } from '@storybook/angular'; @@ -203,7 +203,6 @@ export const WithCustomProvider: Story = { }; ``` - ## FAQ ### How do I manually install the Angular framework? diff --git a/docs/get-started/frameworks/nextjs-vite.mdx b/docs/get-started/frameworks/nextjs-vite.mdx index 47dce128fc5e..b39271a09c8e 100644 --- a/docs/get-started/frameworks/nextjs-vite.mdx +++ b/docs/get-started/frameworks/nextjs-vite.mdx @@ -6,7 +6,7 @@ sidebar: title: Next.js (Vite) --- -Storybook for Next.js (Vite) is the **recommended** [framework](../../contribute/framework.mdx) for developing and testing UI components in isolation for [Next.js](https://nextjs.org/) applications. It uses [Vite](https://vitejs.dev/) for faster builds, better performance and [Storybook Testing](https://storybook.js.org/docs/writing-tests) support. +Storybook for Next.js (Vite) is the **recommended** [framework](../../contribute/framework.mdx) for developing and testing UI components in isolation for [Next.js](https://nextjs.org/) applications. It uses [Vite](https://vitejs.dev/) for faster builds, better performance and [Storybook Testing](../../writing-tests/index.mdx) support. ## Install @@ -14,8 +14,7 @@ To install Storybook in an existing Next.js project, run this command in your pr -You can then get started [writing stories](/docs/get-started/whats-a-story/), [running tests](/docs/writing-tests/) and [documenting your components](/docs/writing-docs/). For more control over the installation process, refer to the [installation guide](/docs/install/). - +You can then get started [writing stories](../whats-a-story.mdx), [running tests](../../writing-tests/index.mdx) and [documenting your components](../../writing-docs/index.mdx). For more control over the installation process, refer to the [installation guide](../install.mdx). ### Requirements @@ -56,9 +55,6 @@ To build Storybook, run: You will find the output in the configured `outputDir` (default is `storybook-static`). - - - ## Configure Storybook for Next.js with Vite supports many Next.js features including: @@ -410,54 +406,60 @@ const preview: Preview = { [`next/head`](https://nextjs.org/docs/pages/api-reference/components/head) is supported out of the box. You can use it in your stories like you would in your Next.js application. Please keep in mind, that the Head `children` are placed into the head element of the iframe that Storybook uses to render your stories. -### Styling -#### Sass/Scss +## Next.js styling -[Global Sass/Scss stylesheets](https://nextjs.org/docs/pages/building-your-application/styling/sass) are supported without any additional configuration as well. Just import them into [`.storybook/preview.js|ts`](../../configure/index.mdx#configure-story-rendering) +### Sass/Scss -```js title=".storybook/preview.js|ts" -import '../styles/globals.scss'; -``` +[Global Sass/SCSS stylesheets](https://nextjs.org/docs/pages/building-your-application/styling/sass) are also supported without any additional configuration. Just import them into [the preview config file](../../configure/index.mdx#configure-story-rendering). -This will automatically include any of your [custom Sass configurations](https://nextjs.org/docs/pages/building-your-application/styling/sass#customizing-sass-options) in your `next.config.js` file. +{/* prettier-ignore-start */} -```js title="next.config.js" -import * as path from 'path'; + -export default { - // Any options here are included in Sass compilation for your stories - sassOptions: { - includePaths: [path.join(process.cwd(), 'styles')], - }, -}; -``` +{/* prettier-ignore-end */} + +This will automatically include any of your [custom Sass configurations](https://nextjs.org/docs/pages/building-your-application/styling/sass#customizing-sass-options) in your Next.js config file. -#### CSS/Sass/Scss Modules +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} + +### CSS/Sass/Scss Modules [CSS modules](https://nextjs.org/docs/pages/building-your-application/styling/css-modules) work as expected. -```jsx title="src/components/Button.jsx" -// This import will work in Storybook -import styles from './Button.module.css'; -// Sass/Scss is also supported -// import styles from './Button.module.scss' -// import styles from './Button.module.sass' +{/* prettier-ignore-start */} -export function Button() { - return ( - - ); -} -``` + + +{/* prettier-ignore-end */} -#### PostCSS +### Styled JSX -Next.js lets you [customize PostCSS config](https://nextjs.org/docs/pages/building-your-application/configuring/post-css). Thus this framework will automatically handle your PostCSS config for you. +The built-in CSS-in-JS solution for Next.js is [styled-jsx](https://nextjs.org/docs/pages/building-your-application/styling/css-in-js), and this framework supports that out of the box, too, with zero config. + +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} + +### Tailwind -This allows for cool things like zero-config Tailwind! (See [Next.js' example](https://github.com/vercel/next.js/tree/canary/packages/create-next-app/templates/default-tw)) +Tailwind in Next.js [is supported via PostCSS](https://nextjs.org/docs/app/getting-started/css#tailwind-css). Storybook will automatically handle the PostCSS config for you, including any custom PostCSS configuration, so that you can import your global CSS directly into [the preview config file](../../configure/index.mdx#configure-story-rendering): + +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} + +### PostCSS + +Next.js lets you [customize PostCSS config](https://nextjs.org/docs/pages/building-your-application/configuring/post-css). Thus this framework will automatically handle your PostCSS config for you. ### Imports #### Absolute imports @@ -638,7 +640,7 @@ To enable this set the `experimentalRSC` feature flag in your `.storybook/main.j Setting this flag automatically wraps your story in a [Suspense](https://react.dev/reference/react/Suspense) wrapper, which is able to render asynchronous components in NextJS's version of React. -If this wrapper causes problems in any of your existing stories, you can selectively disable it using the `react.rsc` [parameter](https://storybook.js.org/docs/writing-stories/parameters) at the global/component/story level: +If this wrapper causes problems in any of your existing stories, you can selectively disable it using the `react.rsc` [parameter](../../writing-stories/parameters.mdx) at the global/component/story level: {/* prettier-ignore-start */} @@ -654,7 +656,6 @@ In the future we will provide better mocking support in Storybook and support fo ## FAQ - ### How do I migrate from the `nextjs` (Webpack 5) addon? #### Automatic migration @@ -673,7 +674,7 @@ This automigration tool performs the following actions: -If your project has custom Webpack configurations in `.storybook/main.js|ts` (via `webpackFinal`), you'll need to migrate those to Vite configuration (via `viteFinal`) after running this automigration. See the [Vite builder documentation](../builders/vite.mdx#migrating-from-webpack) for more information. +If your project has custom Webpack configurations in `.storybook/main.js|ts` (via `webpackFinal`), you'll need to migrate those to Vite configuration (via `viteFinal`) after running this automigration. See the [Vite builder documentation](../../builders/vite.mdx#migrating-from-webpack) for more information. @@ -711,8 +712,6 @@ Finally, if you were using Storybook plugins to integrate with Next.js, those ar {/* prettier-ignore-end */} - - ### Stories for pages/components which fetch data Next.js pages can fetch data directly within server components in the `app` directory, which often include module imports that only run in a node environment. This does not (currently) work within Storybook, because if you import from a Next.js page file containing those node module imports in your stories, your Storybook's Vite build will crash because those modules will not run in a browser. To get around this, you can extract the component in your page file into a separate file and import that pure component in your stories. Or, if that's not feasible for some reason, you can [configure Vite to handle those modules](https://vitejs.dev/config/dep-optimization-options.html#optimizedeps-exclude) in your Storybook's [`viteFinal` configuration](../../builders/vite.mdx#configuration). diff --git a/docs/get-started/frameworks/nextjs.mdx b/docs/get-started/frameworks/nextjs.mdx index 8ad200257846..c1d62f0c4f0c 100644 --- a/docs/get-started/frameworks/nextjs.mdx +++ b/docs/get-started/frameworks/nextjs.mdx @@ -8,7 +8,6 @@ sidebar: Storybook for Next.js (Webpack) is a [framework](../../contribute/framework.mdx) that makes it easy to develop and test UI components in isolation for [Next.js](https://nextjs.org/) applications using [Webpack 5](https://webpack.js.org/). - **We recommend using [`@storybook/nextjs-vite`](./nextjs-vite.mdx)** for most Next.js projects. The Vite-based framework is faster, more modern, and offers better support for testing features. @@ -27,8 +26,7 @@ To install Storybook in an existing Next.js project, run this command in your pr The command will prompt you to choose between this framework and [`@storybook/nextjs-vite`](./nextjs-vite.mdx). We recommend the Vite-based framework ([learn why](./nextjs-vite.mdx#choose-between-vite-and-webpack)). -You can then get started [writing stories](/docs/get-started/whats-a-story/), [running tests](/docs/writing-tests/) and [documenting your components](/docs/writing-docs/). For more control over the installation process, refer to the [installation guide](/docs/install/). - +You can then get started [writing stories](../whats-a-story.mdx), [running tests](../../writing-tests/index.mdx) and [documenting your components](../../writing-docs/index.mdx). For more control over the installation process, refer to the [installation guide](../install.mdx). ### Requirements @@ -54,9 +52,6 @@ To build Storybook, run: You will find the output in the configured `outputDir` (default is `storybook-static`). - - - ## Configure Storybook for Next.js with Vite supports many Next.js features including: @@ -70,16 +65,6 @@ Storybook for Next.js with Vite supports many Next.js features including: * 🎭 [Module mocking](#mocking-modules) * ☁️ [React Server Component (experimental)](#react-server-components-rsc) - - - - - - - - - - ### Next.js's Image component This framework allows you to use Next.js's [next/image](https://nextjs.org/docs/pages/api-reference/components/image) with no configuration. @@ -416,86 +401,47 @@ const preview: Preview = { [`next/head`](https://nextjs.org/docs/pages/api-reference/components/head) is supported out of the box. You can use it in your stories like you would in your Next.js application. Please keep in mind, that the Head `children` are placed into the head element of the iframe that Storybook uses to render your stories. -### Styling +## Next.js styling -#### Sass/Scss +### Sass/Scss -[Global Sass/Scss stylesheets](https://nextjs.org/docs/pages/building-your-application/styling/sass) are supported without any additional configuration as well. Just import them into [`.storybook/preview.js|ts`](../../configure/index.mdx#configure-story-rendering) +[Global Sass/SCSS stylesheets](https://nextjs.org/docs/pages/building-your-application/styling/sass) are also supported without any additional configuration. Just import them into [the preview config file](../../configure/index.mdx#configure-story-rendering). -```js title=".storybook/preview.js|ts" -import '../styles/globals.scss'; -``` +{/* prettier-ignore-start */} -This will automatically include any of your [custom Sass configurations](https://nextjs.org/docs/pages/building-your-application/styling/sass#customizing-sass-options) in your `next.config.js` file. + -```js title="next.config.js" -import * as path from 'path'; +{/* prettier-ignore-end */} -export default { - // Any options here are included in Sass compilation for your stories - sassOptions: { - includePaths: [path.join(process.cwd(), 'styles')], - }, -}; -``` +This will automatically include any of your [custom Sass configurations](https://nextjs.org/docs/pages/building-your-application/styling/sass#customizing-sass-options) in your Next.js config file. + +{/* prettier-ignore-start */} + + -#### CSS/Sass/Scss Modules +{/* prettier-ignore-end */} + +### CSS/Sass/Scss Modules [CSS modules](https://nextjs.org/docs/pages/building-your-application/styling/css-modules) work as expected. -```jsx title="src/components/Button.jsx" -// This import will work in Storybook -import styles from './Button.module.css'; -// Sass/Scss is also supported -// import styles from './Button.module.scss' -// import styles from './Button.module.sass' +{/* prettier-ignore-start */} -export function Button() { - return ( - - ); -} -``` + -#### Styled JSX +{/* prettier-ignore-end */} -The built in CSS-in-JS solution for Next.js is [styled-jsx](https://nextjs.org/docs/pages/building-your-application/styling/css-in-js), and this framework supports that out of the box too, zero config. +### Styled JSX -```jsx title="src/components/HelloWorld.jsx" -// This will work in Storybook -function HelloWorld() { - return ( -
- Hello world -

scoped!

- - -
- ); -} +The built-in CSS-in-JS solution for Next.js is [styled-jsx](https://nextjs.org/docs/pages/building-your-application/styling/css-in-js), and this framework supports that out of the box, too, with zero config. -export default HelloWorld; -``` +{/* prettier-ignore-start */} -You can use your own babel config too. This is an example of how you can customize styled-jsx. + + +{/* prettier-ignore-end */} + +You can use your own Babel config, too. This is an example of how you can customize styled-jsx. ```jsonc // .babelrc (or whatever config file you use) @@ -513,11 +459,19 @@ You can use your own babel config too. This is an example of how you can customi } ``` -#### PostCSS +### Tailwind -Next.js lets you [customize PostCSS config](https://nextjs.org/docs/pages/building-your-application/configuring/post-css). Thus this framework will automatically handle your PostCSS config for you. +Tailwind in Next.js [is supported via PostCSS](https://nextjs.org/docs/app/getting-started/css#tailwind-css). Storybook will automatically handle the PostCSS config for you, including any custom PostCSS configuration, so that you can import your global CSS directly into [the preview config file](../../configure/index.mdx#configure-story-rendering): -This allows for cool things like zero-config Tailwind! (See [Next.js' example](https://github.com/vercel/next.js/tree/canary/packages/create-next-app/templates/default-tw)) +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} + +### PostCSS + +Next.js lets you [customize PostCSS config](https://nextjs.org/docs/pages/building-your-application/configuring/post-css). Thus this framework will automatically handle your PostCSS config for you. ### Imports #### Absolute imports @@ -704,7 +658,7 @@ To enable this set the `experimentalRSC` feature flag in your `.storybook/main.j Setting this flag automatically wraps your story in a [Suspense](https://react.dev/reference/react/Suspense) wrapper, which is able to render asynchronous components in NextJS's version of React. -If this wrapper causes problems in any of your existing stories, you can selectively disable it using the `react.rsc` [parameter](https://storybook.js.org/docs/writing-stories/parameters) at the global/component/story level: +If this wrapper causes problems in any of your existing stories, you can selectively disable it using the `react.rsc` [parameter](../../writing-stories/parameters.mdx) at the global/component/story level: {/* prettier-ignore-start */} diff --git a/docs/get-started/frameworks/preact-vite.mdx b/docs/get-started/frameworks/preact-vite.mdx index c21d619800d0..a316186defd2 100644 --- a/docs/get-started/frameworks/preact-vite.mdx +++ b/docs/get-started/frameworks/preact-vite.mdx @@ -14,7 +14,7 @@ To install Storybook in an existing Preact project, run this command in your pro -You can then get started [writing stories](/docs/get-started/whats-a-story/), [running tests](/docs/writing-tests/) and [documenting your components](/docs/writing-docs/). For more control over the installation process, refer to the [installation guide](/docs/install/). +You can then get started [writing stories](../whats-a-story.mdx), [running tests](../../writing-tests/index.mdx) and [documenting your components](../../writing-docs/index.mdx). For more control over the installation process, refer to the [installation guide](../install.mdx). ### Requirements @@ -41,7 +41,6 @@ To build Storybook, run: You will find the output in the configured `outputDir` (default is `storybook-static`). - ## FAQ ### How do I manually install the Preact framework? diff --git a/docs/get-started/frameworks/react-native-web-vite.mdx b/docs/get-started/frameworks/react-native-web-vite.mdx index 55ce40124f3f..9806207aff08 100644 --- a/docs/get-started/frameworks/react-native-web-vite.mdx +++ b/docs/get-started/frameworks/react-native-web-vite.mdx @@ -12,18 +12,13 @@ Storybook for React Native Web is a [framework](../../contribute/framework.mdx) In addition to React Native Web, Storybook supports on-device [React Native](https://github.com/storybookjs/react-native) development. If you're unsure what's right for you, read our [comparison](#react-native-vs-react-native-web).
- - - - ## Install To install Storybook in an existing React Native project, run this command in your project's root directory: -You can then get started [writing stories](/docs/get-started/whats-a-story/), [running tests](/docs/writing-tests/) and [documenting your components](/docs/writing-docs/). For more control over the installation process, refer to the [installation guide](/docs/install/). - +You can then get started [writing stories](../whats-a-story.mdx), [running tests](../../writing-tests/index.mdx) and [documenting your components](../../writing-docs/index.mdx). For more control over the installation process, refer to the [installation guide](../install.mdx). ### Requirements @@ -41,7 +36,6 @@ You can then get started [writing stories](/docs/get-started/whats-a-story/), [r icon: '/images/logos/builders/vite.svg' }]} /> - ## Run Storybook To run Storybook for a particular project, run the following: @@ -54,8 +48,6 @@ To build Storybook, run: You will find the output in the configured `outputDir` (default is `storybook-static`). - - ## React Native vs React Native Web If you’re building React Native (RN) components, Storybook has two options: Native and Web. @@ -87,7 +79,6 @@ So, which option is right for you? **Both.** It’s also possible to use both options together. This increases Storybook’s install footprint but is a good option if you want native fidelity in addition to all of the web features. Learn more below. - ### Using both React Native and React Native Web The easiest way to use React Native and React Native Web is to select the **"Both"** option when installing Storybook. This will install and create configurations for both environments, allowing you to run Storybook for both in the same project. @@ -103,7 +94,6 @@ After installation, you'll see instructions for both environments: However, you can install them separately if one version is installed. You can add a React Native Web Storybook alongside an existing React Native Storybook by running the install command and selecting "React Native Web" in the setup wizard, and vice versa. - ## FAQ ### How do I migrate from the React Native Web addon? @@ -140,7 +130,6 @@ Update your `.storybook/main.js|ts` to change the framework property and remove Finally, remove the addon and similar packages (i.e., `@storybook/react-webpack5` and `@storybook/addon-react-native-web`) from your project. - ## API ### Options @@ -180,7 +169,7 @@ export default config; #### Example configuration for reanimated ```ts title=".storybook/main.ts" -const main: StorybookConfig = { +const config: StorybookConfig = { // ... rest of config framework: { @@ -205,7 +194,7 @@ const main: StorybookConfig = { ```ts title=".storybook/main.ts" -const main: StorybookConfig = { +const config: StorybookConfig = { // ... rest of config framework: { @@ -225,7 +214,7 @@ Let's say you need to transpile a library called `my-library` that is not transp You can add it to the `modulesToTranspile` option. ```ts title=".storybook/main.ts" -const main: StorybookConfig = { +const config: StorybookConfig = { // ... rest of config framework: { diff --git a/docs/get-started/frameworks/react-vite.mdx b/docs/get-started/frameworks/react-vite.mdx index 6269b5ddd7d8..c04f4e4ffcba 100644 --- a/docs/get-started/frameworks/react-vite.mdx +++ b/docs/get-started/frameworks/react-vite.mdx @@ -14,8 +14,7 @@ To install Storybook in an existing React project, run this command in your proj -You can then get started [writing stories](/docs/get-started/whats-a-story/), [running tests](/docs/writing-tests/) and [documenting your components](/docs/writing-docs/). For more control over the installation process, refer to the [installation guide](/docs/install/). - +You can then get started [writing stories](../whats-a-story.mdx), [running tests](../../writing-tests/index.mdx) and [documenting your components](../../writing-docs/index.mdx). For more control over the installation process, refer to the [installation guide](../install.mdx). ### Requirements @@ -29,7 +28,6 @@ You can then get started [writing stories](/docs/get-started/whats-a-story/), [r icon: '/images/logos/builders/vite.svg' }]} /> - ## Run Storybook To run Storybook for a particular project, run the following: @@ -42,7 +40,6 @@ To build Storybook, run: You will find the output in the configured `outputDir` (default is `storybook-static`). - ## FAQ ### How do I migrate from the React Webpack framework? @@ -74,7 +71,6 @@ Then, update your `.storybook/main.js|ts` to change the framework property: {/* prettier-ignore-end */} - ## API ### Options diff --git a/docs/get-started/frameworks/react-webpack5.mdx b/docs/get-started/frameworks/react-webpack5.mdx index 64dd18c8ac53..c37cf6bdec7f 100644 --- a/docs/get-started/frameworks/react-webpack5.mdx +++ b/docs/get-started/frameworks/react-webpack5.mdx @@ -21,7 +21,7 @@ To install Storybook in an existing React project, run this command in your proj -You can then get started [writing stories](/docs/get-started/whats-a-story/), [running tests](/docs/writing-tests/) and [documenting your components](/docs/writing-docs/). For more control over the installation process, refer to the [installation guide](/docs/install/). +You can then get started [writing stories](../whats-a-story.mdx), [running tests](../../writing-tests/index.mdx) and [documenting your components](../../writing-docs/index.mdx). For more control over the installation process, refer to the [installation guide](../install.mdx). ### Requirements @@ -35,7 +35,6 @@ You can then get started [writing stories](/docs/get-started/whats-a-story/), [r icon: '/images/logos/builders/webpack.svg' }]} /> - ## Run Storybook To run Storybook for a particular project, run the following: @@ -48,7 +47,6 @@ To build Storybook, run: You will find the output in the configured `outputDir` (default is `storybook-static`). - ## Configure ### Create React App (CRA) @@ -61,7 +59,6 @@ This preset enables support for all CRA features, including Sass/SCSS and TypeSc If you're working on an app that was initialized manually (i.e., without the use of CRA), ensure that your app has [react-dom](https://www.npmjs.com/package/react-dom) included as a dependency. Failing to do so can lead to unforeseen issues with Storybook and your project. - ## FAQ ### How do I manually install the React Webpack framework? diff --git a/docs/get-started/frameworks/svelte-vite.mdx b/docs/get-started/frameworks/svelte-vite.mdx index a3a87498cf43..f5d8408e815c 100644 --- a/docs/get-started/frameworks/svelte-vite.mdx +++ b/docs/get-started/frameworks/svelte-vite.mdx @@ -8,14 +8,13 @@ sidebar: Storybook for Svelte & Vite is a [framework](../../contribute/framework.mdx) that makes it easy to develop and test UI components in isolation for applications using [Svelte](https://svelte.dev/) built with [Vite](https://vitejs.dev/). - ## Install To install Storybook in an existing Svelte project, run this command in your project's root directory: -You can then get started [writing stories](/docs/get-started/whats-a-story/), [running tests](/docs/writing-tests/) and [documenting your components](/docs/writing-docs/). For more control over the installation process, refer to the [installation guide](/docs/install/). +You can then get started [writing stories](../whats-a-story.mdx), [running tests](../../writing-tests/index.mdx) and [documenting your components](../../writing-docs/index.mdx). For more control over the installation process, refer to the [installation guide](../install.mdx). ### Requirements @@ -29,7 +28,6 @@ You can then get started [writing stories](/docs/get-started/whats-a-story/), [r icon: '/images/logos/builders/vite.svg' }]} /> - ## Run Storybook To run Storybook for a particular project, run the following: @@ -42,7 +40,6 @@ To build Storybook, run: You will find the output in the configured `outputDir` (default is `storybook-static`). - ## Writing native Svelte stories Storybook provides a Svelte [addon](https://storybook.js.org/addons/@storybook/addon-svelte-csf) maintained by the community, enabling you to write stories for your Svelte components using the template syntax. @@ -65,7 +62,7 @@ Run the following command to install the addon. - The CLI's [`add`](../../api/cli-options.mdx#add) command automates the addon's installation and setup. To install it manually, see our [documentation](../addons/install-addons.mdx#manual-installation) on how to install addons. + The CLI's [`add`](../../api/cli-options.mdx#add) command automates the addon's installation and setup. To install it manually, see our [documentation](../../addons/install-addons.mdx#manual-installation) on how to install addons. @@ -159,7 +156,6 @@ If you enabled automatic documentation generation with the `autodocs` story prop {/* prettier-ignore-end */} - ## FAQ ### How do I manually install the Svelte framework? @@ -179,7 +175,6 @@ Then, update your `.storybook/main.js|ts` to change the framework property: {/* prettier-ignore-end */} - ## API ### Options diff --git a/docs/get-started/frameworks/sveltekit.mdx b/docs/get-started/frameworks/sveltekit.mdx index 78e1bf196d0b..ff46962f7051 100644 --- a/docs/get-started/frameworks/sveltekit.mdx +++ b/docs/get-started/frameworks/sveltekit.mdx @@ -14,7 +14,7 @@ To install Storybook in an existing SvelteKit project, run this command in your -You can then get started [writing stories](/docs/get-started/whats-a-story/), [running tests](/docs/writing-tests/) and [documenting your components](/docs/writing-docs/). For more control over the installation process, refer to the [installation guide](/docs/install/). +You can then get started [writing stories](../whats-a-story.mdx), [running tests](../../writing-tests/index.mdx) and [documenting your components](../../writing-docs/index.mdx). For more control over the installation process, refer to the [installation guide](../install.mdx). ### Requirements @@ -28,7 +28,6 @@ You can then get started [writing stories](/docs/get-started/whats-a-story/), [r icon: '/images/logos/builders/vite.svg' }]} /> - ## Run Storybook To run Storybook for a particular project, run the following: @@ -41,7 +40,6 @@ To build Storybook, run: You will find the output in the configured `outputDir` (default is `storybook-static`). - ## Configure This section covers SvelteKit support and configuration options. @@ -115,7 +113,7 @@ Run the following command to install the addon. - The CLI's [`add`](../../api/cli-options.mdx#add) command automates the addon's installation and setup. To install it manually, see our [documentation](../addons/install-addons.mdx#manual-installation) on how to install addons. + The CLI's [`add`](../../api/cli-options.mdx#add) command automates the addon's installation and setup. To install it manually, see our [documentation](../../addons/install-addons.mdx#manual-installation) on how to install addons. @@ -235,7 +233,6 @@ Finally, these packages are now either obsolete or part of `@storybook/sveltekit * `storybook-builder-vite` * `@storybook/builder-vite` - ## API ### Parameters diff --git a/docs/get-started/frameworks/vue3-vite.mdx b/docs/get-started/frameworks/vue3-vite.mdx index 32db1034f25d..a62dd6eb1421 100644 --- a/docs/get-started/frameworks/vue3-vite.mdx +++ b/docs/get-started/frameworks/vue3-vite.mdx @@ -14,7 +14,7 @@ To install Storybook in an existing Vue project, run this command in your projec -You can then get started [writing stories](/docs/get-started/whats-a-story/), [running tests](/docs/writing-tests/) and [documenting your components](/docs/writing-docs/). For more control over the installation process, refer to the [installation guide](/docs/install/). +You can then get started [writing stories](../whats-a-story.mdx), [running tests](../../writing-tests/index.mdx) and [documenting your components](../../writing-docs/index.mdx). For more control over the installation process, refer to the [installation guide](../install.mdx). ### Requirements @@ -40,16 +40,6 @@ To build Storybook, run: You will find the output in the configured `outputDir` (default is `storybook-static`). - - - - - - - - - - ## Configure Storybook for Vue 3 with Vite is designed to work out of the box with minimal configuration. This section covers configuration options for the framework. @@ -246,8 +236,6 @@ export default config; Otherwise, you might face missing component types/descriptions or unresolvable import aliases like `@/some/import`. - - ## FAQ ### How do I manually install the Vue framework? @@ -278,9 +266,6 @@ Then, update your `.storybook/main.js|ts` to change the framework property: {/* prettier-ignore-end */} - - - ## API ### Options diff --git a/docs/get-started/frameworks/web-components-vite.mdx b/docs/get-started/frameworks/web-components-vite.mdx index bba67d69de30..a7717aa7bc65 100644 --- a/docs/get-started/frameworks/web-components-vite.mdx +++ b/docs/get-started/frameworks/web-components-vite.mdx @@ -8,14 +8,13 @@ sidebar: Storybook for Web components & Vite is a [framework](../../contribute/framework.mdx) that makes it easy to develop and test UI components in isolation for applications using [Web components](https://www.webcomponents.org/introduction) built with [Vite](https://vitejs.dev/). - ## Install To install Storybook in an existing project, run this command in your project's root directory: -You can then get started [writing stories](/docs/get-started/whats-a-story/), [running tests](/docs/writing-tests/) and [documenting your components](/docs/writing-docs/). For more control over the installation process, refer to the [installation guide](/docs/install/). +You can then get started [writing stories](../whats-a-story.mdx), [running tests](../../writing-tests/index.mdx) and [documenting your components](../../writing-docs/index.mdx). For more control over the installation process, refer to the [installation guide](../install.mdx). ### Requirements @@ -25,7 +24,6 @@ You can then get started [writing stories](/docs/get-started/whats-a-story/), [r icon: '/images/logos/builders/vite.svg' }]} /> - ## Run Storybook To run Storybook for a particular project, run the following: @@ -38,7 +36,6 @@ To build Storybook, run: You will find the output in the configured `outputDir` (default is `storybook-static`). - ## FAQ ### How do I manually install the Web Components framework? diff --git a/docs/versions/next.json b/docs/versions/next.json index e458aeee7b15..4d1168f40225 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"10.2.0-alpha.6","info":{"plain":"- Controls: Fix displaying as object instead of select for optional union types - [#33200](https://github.com/storybookjs/storybook/pull/33200), thanks @tanujbhaud!\n- Controls: Force object control JSON mode to reset - [#33330](https://github.com/storybookjs/storybook/pull/33330), thanks @Sidnioulz!\n- Docs-Blocks: Fix broken tooltip in ArgValue details - [#33264](https://github.com/storybookjs/storybook/pull/33264), thanks @Sidnioulz!\n- Manager: Ensure reset item only appears in globals toolbar when specified - [#33276](https://github.com/storybookjs/storybook/pull/33276), thanks @mrginglymus!\n- Nextjs-Vite: Install `vite` during migration if not installed yet - [#33316](https://github.com/storybookjs/storybook/pull/33316), thanks @ghengeveld!\n- UI: Make vertical alignment of TestStatusIcon more robust - [#33305](https://github.com/storybookjs/storybook/pull/33305), thanks @Sidnioulz!"}} \ No newline at end of file +{"version":"10.2.0-alpha.7","info":{"plain":"- Automigrate: Fix missing await - [#33333](https://github.com/storybookjs/storybook/pull/33333), thanks @valentinpalkovic!\n- CLI: Remove REACT_PROJECT projectType - [#33334](https://github.com/storybookjs/storybook/pull/33334), thanks @valentinpalkovic!\n- Core: Exclude open from pre-bundling to make local xdg-open reachable - [#33325](https://github.com/storybookjs/storybook/pull/33325), thanks @Sidnioulz!\n- Core: Fix `.env`-file parsing - [#33383](https://github.com/storybookjs/storybook/pull/33383), thanks @JReinhold!\n- Next.js: Handle v14 compatibility for draftMode import - [#33341](https://github.com/storybookjs/storybook/pull/33341), thanks @tanujbhaud!\n- Nextjs-Vite: Update vite-plugin-storybook-nextjs to v3.1.7 - [#33351](https://github.com/storybookjs/storybook/pull/33351), thanks @valentinpalkovic!\n- React-Vite: Update @joshwooding/vite-plugin-react-docgen-typescript - [#33349](https://github.com/storybookjs/storybook/pull/33349), thanks @valentinpalkovic!\n- React: Use self-closing tag for code snippets - [#33342](https://github.com/storybookjs/storybook/pull/33342), thanks @valentinpalkovic!\n- Sidebar: Prevent updating non-existent stories - [#33037](https://github.com/storybookjs/storybook/pull/33037), thanks @ia319!\n- Telemetry: Fix race condition in telemetry cache causing malformed JSON - [#33323](https://github.com/storybookjs/storybook/pull/33323), thanks @valentinpalkovic!\n- Telemetry: Remove instance of check for sub-error handling - [#33356](https://github.com/storybookjs/storybook/pull/33356), thanks @valentinpalkovic!"}} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 0c21fb00352c..37c5934bfb6c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3771,12 +3771,11 @@ __metadata: languageName: node linkType: hard -"@joshwooding/vite-plugin-react-docgen-typescript@npm:0.6.1": - version: 0.6.1 - resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.6.1" +"@joshwooding/vite-plugin-react-docgen-typescript@npm:^0.6.3": + version: 0.6.3 + resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.6.3" dependencies: - glob: "npm:^10.0.0" - magic-string: "npm:^0.30.0" + glob: "npm:^11.1.0" react-docgen-typescript: "npm:^2.2.2" peerDependencies: typescript: ">= 4.3.x" @@ -3784,7 +3783,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/0bcc2adbb49158018102bd9d84cd8572c770daee3d46733157933ef0330953bd5b9e102c26f2338ee7dfb8f21a7bb937134d23f8a7935d5dc88525a253557467 + checksum: 10c0/e68d2884235b8290673c17a13bc303a088feba6ce0a275ab0778b50e90b967f5dffdcf71ed3197e9cdf07607594a9cb2a86e3ea6e4eb8962b50d61078107bac3 languageName: node linkType: hard @@ -8438,7 +8437,7 @@ __metadata: semver: "npm:^7.3.5" styled-jsx: "npm:5.1.6" typescript: "npm:^5.8.3" - vite-plugin-storybook-nextjs: "npm:^3.1.0" + vite-plugin-storybook-nextjs: "npm:^3.1.7" peerDependencies: next: ^14.1.0 || ^15.0.0 || ^16.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -8655,7 +8654,7 @@ __metadata: version: 0.0.0-use.local resolution: "@storybook/react-vite@workspace:code/frameworks/react-vite" dependencies: - "@joshwooding/vite-plugin-react-docgen-typescript": "npm:0.6.1" + "@joshwooding/vite-plugin-react-docgen-typescript": "npm:^0.6.3" "@rollup/pluginutils": "npm:^5.0.2" "@storybook/builder-vite": "workspace:*" "@storybook/react": "workspace:*" @@ -18766,7 +18765,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^11.0.3": +"glob@npm:^11.0.3, glob@npm:^11.1.0": version: 11.1.0 resolution: "glob@npm:11.1.0" dependencies: @@ -31504,9 +31503,9 @@ __metadata: languageName: node linkType: hard -"vite-plugin-storybook-nextjs@npm:^3.1.0": - version: 3.1.1 - resolution: "vite-plugin-storybook-nextjs@npm:3.1.1" +"vite-plugin-storybook-nextjs@npm:^3.1.7": + version: 3.1.7 + resolution: "vite-plugin-storybook-nextjs@npm:3.1.7" dependencies: "@next/env": "npm:16.0.0" image-size: "npm:^2.0.0" @@ -31516,9 +31515,9 @@ __metadata: vite-tsconfig-paths: "npm:^5.1.4" peerDependencies: next: ^14.1.0 || ^15.0.0 || ^16.0.0 - storybook: ^0.0.0-0 || ^9.0.0 || ^10.0.0 || ^10.0.0-0 || ^10.1.0-0 + storybook: ^0.0.0-0 || ^9.0.0 || ^10.0.0 || ^10.0.0-0 || ^10.1.0-0 || ^10.2.0-0 vite: ^5.0.0 || ^6.0.0 || ^7.0.0 - checksum: 10c0/7bcb93fbea285685032f949f0d5e5fe0153ea762a12803eb3e559bf11797a3fa053b80d4975deac3e2a8e858aa118d0ac058929eae878bb7acd3b8a04082ba7a + checksum: 10c0/5254ff5cd9168740659752053316b7d14f270ebc41134926adc02cb2d162674f268b0b4a808b01694d1d7a3f958b694de3dc4132137d6e337c78f4a5b8fee50c languageName: node linkType: hard