diff --git a/.circleci/config.yml b/.circleci/config.yml index 385972ef21d8..a4132bb6b381 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -263,6 +263,31 @@ jobs: name: Ensure no changes pending - report-workflow-on-failure - cancel-workflow-on-failure + check-sandboxes: + executor: + class: medium + name: sb_node_22_classic + parallelism: << parameters.parallelism >> + parameters: + parallelism: + type: integer + steps: + - git-shallow-clone/checkout_advanced: + clone_options: --depth 1 --verbose + - attach_workspace: + at: . + - run: + command: | + TEMPLATE=$(yarn get-template --cadence << pipeline.parameters.workflow >> --task check-sandbox) + cd sandbox/$(yarn get-sandbox-dir --template $TEMPLATE) && yarn + name: Install sandbox dependencies + - run: + command: yarn task --task check-sandbox --template $(yarn get-template --cadence << pipeline.parameters.workflow >> --task check-sandbox) --no-link --start-from=never --junit + name: Type check Sandboxes + - report-workflow-on-failure: + template: $(yarn get-template --cadence << pipeline.parameters.workflow >> --task check-sandbox) + - store_test_results: + path: test-results chromatic-internal-storybook: environment: NODE_OPTIONS: --max_old_space_size=4096 @@ -884,6 +909,26 @@ jobs: template: $(yarn get-template --cadence << pipeline.parameters.workflow >> --task test-runner) - store_test_results: path: test-results + test-yarn-pnp: + executor: + class: medium + name: sb_playwright + steps: + - git-shallow-clone/checkout_advanced: + clone_options: --depth 1 --verbose + - attach_workspace: + at: . + - run: + command: yarn install --no-immutable + environment: + YARN_ENABLE_IMMUTABLE_INSTALLS: false + name: Install dependencies + working_directory: test-storybooks/yarn-pnp + - run: + command: yarn storybook --smoke-test + name: Run Storybook smoke test + working_directory: test-storybooks/yarn-pnp + - report-workflow-on-failure unit-tests: executor: class: xlarge @@ -994,6 +1039,10 @@ workflows: parallelism: 34 requires: - build + - check-sandboxes: + parallelism: 1 + requires: + - create-sandboxes - chromatic-sandboxes: parallelism: 31 requires: @@ -1024,6 +1073,9 @@ workflows: - svelte requires: - build + - test-yarn-pnp: + requires: + - build - e2e-ui: requires: - build @@ -1109,6 +1161,10 @@ workflows: parallelism: 7 requires: - create-sandboxes + - check-sandboxes: + parallelism: 1 + requires: + - create-sandboxes - test-portable-stories: matrix: parameters: @@ -1119,6 +1175,9 @@ workflows: - svelte requires: - build + - test-yarn-pnp: + requires: + - build - e2e-ui: requires: - build @@ -1185,6 +1244,13 @@ workflows: parallelism: 5 requires: - create-sandboxes + - check-sandboxes: + parallelism: 1 + requires: + - create-sandboxes + - test-yarn-pnp: + requires: + - build - e2e-ui: requires: - build diff --git a/.circleci/src/jobs/check-sandboxes.yml b/.circleci/src/jobs/check-sandboxes.yml new file mode 100644 index 000000000000..bbc893b9fad1 --- /dev/null +++ b/.circleci/src/jobs/check-sandboxes.yml @@ -0,0 +1,27 @@ +executor: + class: medium + name: sb_node_22_classic + +parameters: + parallelism: + type: integer + +parallelism: << parameters.parallelism >> + +steps: + - git-shallow-clone/checkout_advanced: + clone_options: '--depth 1 --verbose' + - attach_workspace: + at: . + - run: + name: Install sandbox dependencies + command: | + TEMPLATE=$(yarn get-template --cadence << pipeline.parameters.workflow >> --task check-sandbox) + cd sandbox/$(yarn get-sandbox-dir --template $TEMPLATE) && yarn + - run: + name: Type check Sandboxes + command: yarn task --task check-sandbox --template $(yarn get-template --cadence << pipeline.parameters.workflow >> --task check-sandbox) --no-link --start-from=never --junit + - report-workflow-on-failure: + template: $(yarn get-template --cadence << pipeline.parameters.workflow >> --task check-sandbox) + - store_test_results: + path: test-results diff --git a/.circleci/src/jobs/test-yarn-pnp.yml b/.circleci/src/jobs/test-yarn-pnp.yml new file mode 100644 index 000000000000..b89e4d8bd540 --- /dev/null +++ b/.circleci/src/jobs/test-yarn-pnp.yml @@ -0,0 +1,21 @@ +executor: + name: sb_playwright + class: medium + +steps: + - git-shallow-clone/checkout_advanced: + clone_options: '--depth 1 --verbose' + - attach_workspace: + at: . + - run: + name: Install dependencies + command: yarn install --no-immutable + working_directory: test-storybooks/yarn-pnp + environment: + YARN_ENABLE_IMMUTABLE_INSTALLS: false + - run: + name: Run Storybook smoke test + command: yarn storybook --smoke-test + working_directory: test-storybooks/yarn-pnp + + - report-workflow-on-failure diff --git a/.circleci/src/workflows/daily.yml b/.circleci/src/workflows/daily.yml index 0f31c5279609..1dfde022f3bc 100644 --- a/.circleci/src/workflows/daily.yml +++ b/.circleci/src/workflows/daily.yml @@ -34,6 +34,10 @@ jobs: parallelism: 34 requires: - build + - check-sandboxes: + parallelism: 1 + requires: + - create-sandboxes # - smoke-test-sandboxes: # disabled for now # requires: # - create-sandboxes @@ -63,6 +67,9 @@ jobs: matrix: parameters: directory: ['react', 'vue3', 'nextjs', 'svelte'] + - test-yarn-pnp: + requires: + - build - e2e-ui: requires: - build diff --git a/.circleci/src/workflows/merged.yml b/.circleci/src/workflows/merged.yml index bdf687d408a4..90d9cc46fdc1 100644 --- a/.circleci/src/workflows/merged.yml +++ b/.circleci/src/workflows/merged.yml @@ -57,12 +57,19 @@ jobs: parallelism: 7 requires: - create-sandboxes + - check-sandboxes: + parallelism: 1 + requires: + - create-sandboxes - test-portable-stories: requires: - build matrix: parameters: directory: ['react', 'vue3', 'nextjs', 'svelte'] + - test-yarn-pnp: + requires: + - build - e2e-ui: requires: - build diff --git a/.circleci/src/workflows/normal.yml b/.circleci/src/workflows/normal.yml index 5aa63679dffb..1fe5bf46ed63 100644 --- a/.circleci/src/workflows/normal.yml +++ b/.circleci/src/workflows/normal.yml @@ -57,11 +57,18 @@ jobs: parallelism: 5 requires: - create-sandboxes + - check-sandboxes: + parallelism: 1 + requires: + - create-sandboxes # TODO: don't forget to reenable this # - bench-sandboxes: # parallelism: 5 # requires: # - create-sandboxes + - test-yarn-pnp: + requires: + - build - e2e-ui: requires: - build diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ef6c6a401a2..72640fdebbf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 10.0.6 + +- CSF: Fix export interface declaration for NextPreview - [#32914](https://github.com/storybookjs/storybook/pull/32914), thanks @icopp! +- Controls: Add range validation in Number Control - [#32539](https://github.com/storybookjs/storybook/pull/32539), thanks @ia319! +- Fix: Export interface declaration for ReactMeta - [#32915](https://github.com/storybookjs/storybook/pull/32915), thanks @icopp! +- Vitest Addon: Add support for Preact - [#32948](https://github.com/storybookjs/storybook/pull/32948), thanks @yannbf! + ## 10.0.5 - Core: Add reentry guard to focus patch - [#32655](https://github.com/storybookjs/storybook/pull/32655), thanks @ia319! diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index 83a07ed7e133..fceaee6655ea 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,10 @@ +## 10.1.0-alpha.8 + +- ESLint: Only apply csf-strict rules on stories files - [#31963](https://github.com/storybookjs/storybook/pull/31963), thanks @cylewaitforit! +- Middleware: Prepend `file://` to middleware `import` for Windows support - [#32955](https://github.com/storybookjs/storybook/pull/32955), thanks @ndelangen! +- Next.js: Update SWC loader to support new wasm detection - [#33003](https://github.com/storybookjs/storybook/pull/33003), thanks @yannbf! +- React Native Web: Update vite-plugin-rnw for overall improvements - [#32991](https://github.com/storybookjs/storybook/pull/32991), thanks @dannyhw! + ## 10.1.0-alpha.7 - CSF: Fix export interface declaration for NextPreview - [#32914](https://github.com/storybookjs/storybook/pull/32914), thanks @icopp! diff --git a/code/addons/docs/src/index.ts b/code/addons/docs/src/index.ts index 20953c9bc649..3a13c486dde2 100644 --- a/code/addons/docs/src/index.ts +++ b/code/addons/docs/src/index.ts @@ -1,3 +1,5 @@ +import type React from 'react'; + import { definePreviewAddon } from 'storybook/internal/csf'; import * as addonAnnotations from './preview'; @@ -6,4 +8,13 @@ import type { DocsTypes } from './types'; export { DocsRenderer } from './DocsRenderer'; export type { DocsTypes }; +declare module 'mdx/types' { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace JSX { + type Element = React.JSX.Element; + type ElementClass = React.JSX.ElementClass; + type IntrinsicElements = React.JSX.IntrinsicElements; + } +} + export default () => definePreviewAddon(addonAnnotations); diff --git a/code/core/src/core-server/utils/middleware.ts b/code/core/src/core-server/utils/middleware.ts index 702d862472b1..db2816723f64 100644 --- a/code/core/src/core-server/utils/middleware.ts +++ b/code/core/src/core-server/utils/middleware.ts @@ -11,7 +11,7 @@ const fileExists = (basename: string) => export async function getMiddleware(configDir: string) { const middlewarePath = fileExists(resolve(configDir, 'middleware')); if (middlewarePath) { - const middlewareModule = await import(middlewarePath); + const middlewareModule = await import('file://' + middlewarePath); return middlewareModule.default ?? middlewareModule; } return () => {}; diff --git a/code/frameworks/nextjs/src/swc/next-swc-loader-patch.ts b/code/frameworks/nextjs/src/swc/next-swc-loader-patch.ts index ec4ec7b35141..45fa7612b054 100644 --- a/code/frameworks/nextjs/src/swc/next-swc-loader-patch.ts +++ b/code/frameworks/nextjs/src/swc/next-swc-loader-patch.ts @@ -29,7 +29,7 @@ DEALINGS IN THE SOFTWARE. import { isAbsolute, relative } from 'node:path'; import type { NextConfig } from 'next'; -import { isWasm, transform } from 'next/dist/build/swc/index.js'; +import * as nextSwcUtils from 'next/dist/build/swc/index.js'; import { getLoaderSWCOptions } from 'next/dist/build/swc/options.js'; export interface SWCLoaderOptions { @@ -136,7 +136,7 @@ async function loaderTransform(this: any, parentTrace: any, source?: string, inp const swcSpan = parentTrace.traceChild('next-swc-transform'); return swcSpan.traceAsyncFn(() => - transform(source as any, programmaticOptions).then((output) => { + nextSwcUtils.transform(source as any, programmaticOptions).then((output) => { if (output.eliminatedPackages && this.eliminatedPackages) { for (const pkg of JSON.parse(output.eliminatedPackages)) { this.eliminatedPackages.add(pkg); @@ -152,6 +152,17 @@ const EXCLUDED_PATHS = /[\\/](cache[\\/][^\\/]+\.zip[\\/]node_modules|__virtual_ export function pitch(this: any) { const callback = this.async(); (async () => { + let isWasm: boolean = false; + + if (!!nextSwcUtils.isWasm) { + isWasm = await nextSwcUtils.isWasm(); + // @ts-expect-error Relevant from Next.js >= 16.0.2-canary.12 + } else if (!!nextSwcUtils.getBindingsSync) { + await nextSwcUtils.loadBindings(); + // @ts-expect-error Relevant from Next.js >= 16.0.2-canary.12 + isWasm = nextSwcUtils.getBindingsSync().isWasm; + } + if ( // TODO: Evaluate if this is correct after removing pnp compatibility code in SB11 // TODO: investigate swc file reading in PnP mode? @@ -159,7 +170,7 @@ export function pitch(this: any) { !EXCLUDED_PATHS.test(this.resourcePath) && this.loaders.length - 1 === this.loaderIndex && isAbsolute(this.resourcePath) && - !(await isWasm()) + !isWasm ) { const loaderSpan = mockCurrentTraceSpan.traceChild('next-swc-loader'); this.addDependency(this.resourcePath); diff --git a/code/frameworks/react-native-web-vite/package.json b/code/frameworks/react-native-web-vite/package.json index 3c1ed133538e..0347bc58ed9d 100644 --- a/code/frameworks/react-native-web-vite/package.json +++ b/code/frameworks/react-native-web-vite/package.json @@ -56,7 +56,7 @@ "@storybook/builder-vite": "workspace:*", "@storybook/react": "workspace:*", "@storybook/react-vite": "workspace:*", - "vite-plugin-rnw": "^0.0.6", + "vite-plugin-rnw": "^0.0.8", "vite-tsconfig-paths": "^5.1.4" }, "devDependencies": { diff --git a/code/frameworks/react-native-web-vite/src/types.ts b/code/frameworks/react-native-web-vite/src/types.ts index cc0a60733199..b4d55d6c93a3 100644 --- a/code/frameworks/react-native-web-vite/src/types.ts +++ b/code/frameworks/react-native-web-vite/src/types.ts @@ -5,7 +5,7 @@ import type { StorybookConfig as StorybookConfigBase, } from '@storybook/react-vite'; -import type { BabelOptions, Options as ReactOptions } from 'vite-plugin-rnw'; +import type { RnwOptions } from 'vite-plugin-rnw'; export type FrameworkOptions = FrameworkOptionsBase & { /** @@ -16,7 +16,7 @@ export type FrameworkOptions = FrameworkOptionsBase & { * @example {modulesToTranspile: ['my-library']} */ modulesToTranspile?: string[]; - pluginReactOptions?: Omit & { babel?: BabelOptions }; + pluginReactOptions?: RnwOptions; /** * @deprecated These options will be ignored. Use `pluginReactOptions` now for everything and * override includes in order to transpile node_modules pluginBabelOptions will be removed in diff --git a/code/lib/cli-storybook/src/sandbox-templates.ts b/code/lib/cli-storybook/src/sandbox-templates.ts index c9f9302cfbf3..8211002ebf8c 100644 --- a/code/lib/cli-storybook/src/sandbox-templates.ts +++ b/code/lib/cli-storybook/src/sandbox-templates.ts @@ -64,6 +64,11 @@ export type Template = { * to run the other tasks. Set the ones to skip in this property. */ skipTasks?: SkippableTask[]; + /** + * Should the sandbox be type checked after build. Not part of skipTasks as the default answer + * will be 'no', at least initially + */ + typeCheck?: boolean; /** * Set this only while developing a newly created framework, to avoid using it in CI. NOTE: Make * sure to always add a TODO comment to remove this flag in a subsequent PR. @@ -342,7 +347,7 @@ export const baseTemplates = { }, modifications: { useCsfFactory: true, - extraDependencies: ['prop-types'], + extraDependencies: ['prop-types', '@types/prop-types'], mainConfig: { features: { developmentModeForBuild: true, @@ -351,6 +356,7 @@ export const baseTemplates = { }, }, skipTasks: ['bench'], + typeCheck: true, }, 'react-vite/prerelease-ts': { name: 'React Prerelease (Vite | TypeScript)', @@ -791,6 +797,7 @@ const benchTemplates = { 'chromatic', 'vitest-integration', ], + typeCheck: false, }, 'bench/react-webpack-18-ts': { ...baseTemplates['react-webpack/18-ts'], @@ -824,6 +831,7 @@ const benchTemplates = { 'chromatic', 'vitest-integration', ], + typeCheck: false, }, 'bench/react-vite-default-ts-test-build': { ...baseTemplates['react-vite/default-ts'], @@ -840,6 +848,7 @@ const benchTemplates = { 'e2e-tests-dev', 'vitest-integration', ], + typeCheck: false, }, 'bench/react-webpack-18-ts-test-build': { ...baseTemplates['react-webpack/18-ts'], diff --git a/code/lib/eslint-plugin/scripts/update-lib-configs.ts b/code/lib/eslint-plugin/scripts/update-lib-configs.ts index c122dfeab948..067aac41ce5e 100644 --- a/code/lib/eslint-plugin/scripts/update-lib-configs.ts +++ b/code/lib/eslint-plugin/scripts/update-lib-configs.ts @@ -50,7 +50,10 @@ function formatCategory(category: TCategory) { // This file is bundled in an index.js file at the root // so the reference is relative to the src directory extends: './configs/${extendsCategoryId}', - rules: ${formatRules(category.rules)} + overrides: [{ + files: [${STORIES_GLOBS.join(', ')}], + rules: ${formatRules(category.rules)} + },] } `; } diff --git a/code/lib/eslint-plugin/scripts/update-lib-flat-configs.ts b/code/lib/eslint-plugin/scripts/update-lib-flat-configs.ts index b5d9cc662933..e36b5193e2b3 100644 --- a/code/lib/eslint-plugin/scripts/update-lib-flat-configs.ts +++ b/code/lib/eslint-plugin/scripts/update-lib-flat-configs.ts @@ -64,6 +64,7 @@ function formatCategory(category: TCategory) { ...config, { name: 'storybook:${category.categoryId}:rules', + files: [${STORIES_GLOBS.join(', ')}], rules: ${formatRules(category.rules)} } ] diff --git a/code/lib/eslint-plugin/src/configs/csf-strict.ts b/code/lib/eslint-plugin/src/configs/csf-strict.ts index 5a99039d9287..ca88aaaf6ad7 100644 --- a/code/lib/eslint-plugin/src/configs/csf-strict.ts +++ b/code/lib/eslint-plugin/src/configs/csf-strict.ts @@ -7,10 +7,15 @@ export default { // This file is bundled in an index.js file at the root // so the reference is relative to the src directory extends: './configs/csf', - rules: { - 'react-hooks/rules-of-hooks': 'off', - 'import/no-anonymous-default-export': 'off', - 'storybook/no-stories-of': 'error', - 'storybook/no-title-property-in-meta': 'error', - } as const, + overrides: [ + { + files: ['**/*.stories.@(ts|tsx|js|jsx|mjs|cjs)', '**/*.story.@(ts|tsx|js|jsx|mjs|cjs)'], + rules: { + 'react-hooks/rules-of-hooks': 'off', + 'import/no-anonymous-default-export': 'off', + 'storybook/no-stories-of': 'error', + 'storybook/no-title-property-in-meta': 'error', + } as const, + }, + ], }; diff --git a/code/lib/eslint-plugin/src/configs/flat/csf-strict.ts b/code/lib/eslint-plugin/src/configs/flat/csf-strict.ts index bfffc92a693a..32f41846e314 100644 --- a/code/lib/eslint-plugin/src/configs/flat/csf-strict.ts +++ b/code/lib/eslint-plugin/src/configs/flat/csf-strict.ts @@ -9,6 +9,7 @@ export default [ ...config, { name: 'storybook:csf-strict:rules', + files: ['**/*.stories.@(ts|tsx|js|jsx|mjs|cjs)', '**/*.story.@(ts|tsx|js|jsx|mjs|cjs)'], rules: { 'react-hooks/rules-of-hooks': 'off', 'import/no-anonymous-default-export': 'off', diff --git a/code/package.json b/code/package.json index 19987cde5729..88cc1b282829 100644 --- a/code/package.json +++ b/code/package.json @@ -283,5 +283,6 @@ "Dependency Upgrades" ] ] - } + }, + "deferredNextVersion": "10.1.0-alpha.8" } diff --git a/code/renderers/preact/src/render.tsx b/code/renderers/preact/src/render.tsx index 56c599006e86..b413306a2f63 100644 --- a/code/renderers/preact/src/render.tsx +++ b/code/renderers/preact/src/render.tsx @@ -16,9 +16,7 @@ export const render: ArgsStoryFn = (args, context) => { ); } - // @ts-expect-error I think the type of Component should be Preact.ComponentType, but even that - // doesn't make TS happy, I suspect because TS wants "react" components. - return ; + return h(Component, args); }; let renderedStory: Element; diff --git a/code/renderers/react/template/stories/csf4.stories.tsx b/code/renderers/react/template/stories/csf4.stories.tsx index ae0e65e08a30..2a68cfef500b 100644 --- a/code/renderers/react/template/stories/csf4.stories.tsx +++ b/code/renderers/react/template/stories/csf4.stories.tsx @@ -1,4 +1,5 @@ -// @ts-expect-error this will be part of the package.json of the sandbox +// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- we can't expect error as it is an error in development but it isn't sandbox +// @ts-ignore only present in sandbox import preview from '#.storybook/preview'; const meta = preview.meta({ diff --git a/code/renderers/react/template/stories/decorators.stories.tsx b/code/renderers/react/template/stories/decorators.stories.tsx index f4f9fd9e4e73..340ffaeb6606 100644 --- a/code/renderers/react/template/stories/decorators.stories.tsx +++ b/code/renderers/react/template/stories/decorators.stories.tsx @@ -43,7 +43,7 @@ export const Context: StoryObj = { ), ], - render: function Render(args, context) { + render: function Render() { const value = useContext(TestContext); if (!value) { diff --git a/code/renderers/react/template/stories/docgen-components/10278-ts-multiple-components/input.tsx b/code/renderers/react/template/stories/docgen-components/10278-ts-multiple-components/input.tsx index 4490901b9790..476a6ef2d22c 100644 --- a/code/renderers/react/template/stories/docgen-components/10278-ts-multiple-components/input.tsx +++ b/code/renderers/react/template/stories/docgen-components/10278-ts-multiple-components/input.tsx @@ -10,12 +10,12 @@ interface IBProps { } /** A component */ -const A = (props: IAProps): JSX.Element => { +const A = (props: IAProps): React.JSX.Element => { return <>Hi {props.aProperty}; }; /** B component */ -const B = (props: IBProps): JSX.Element => { +const B = (props: IBProps): React.JSX.Element => { return <>Hi {props.bProperty}; }; diff --git a/code/renderers/react/template/stories/docgen-components/8740-ts-multi-props/docgen.snapshot b/code/renderers/react/template/stories/docgen-components/8740-ts-multi-props/docgen.snapshot index 12be491a61b6..a865c06da03b 100644 --- a/code/renderers/react/template/stories/docgen-components/8740-ts-multi-props/docgen.snapshot +++ b/code/renderers/react/template/stories/docgen-components/8740-ts-multi-props/docgen.snapshot @@ -11,6 +11,9 @@ export const Paragraph = ({ }) => /*#__PURE__*/React.createElement("div", { className: size }, children); + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- we can't expect error as it isn't an error in 18 (development) but it is in 19 (sandbox) +// @ts-ignore not present on react 19 Paragraph.defaultProps = { size: 'md' }; diff --git a/code/renderers/react/template/stories/docgen-components/8740-ts-multi-props/input.tsx b/code/renderers/react/template/stories/docgen-components/8740-ts-multi-props/input.tsx index 1fb6607d0b71..9813008e9ef0 100644 --- a/code/renderers/react/template/stories/docgen-components/8740-ts-multi-props/input.tsx +++ b/code/renderers/react/template/stories/docgen-components/8740-ts-multi-props/input.tsx @@ -18,6 +18,8 @@ export const Paragraph: React.FC = ({ size, children }) => (
{children}
); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- we can't expect error as it isn't an error in 18 (development) but it is in 19 (sandbox) +// @ts-ignore not present on react 19 Paragraph.defaultProps = { size: 'md' }; export const component = Header; diff --git a/code/renderers/react/template/stories/docgen-components/9575-ts-camel-case/docgen.snapshot b/code/renderers/react/template/stories/docgen-components/9575-ts-camel-case/docgen.snapshot index 71d4150ec9d1..347886754338 100644 --- a/code/renderers/react/template/stories/docgen-components/9575-ts-camel-case/docgen.snapshot +++ b/code/renderers/react/template/stories/docgen-components/9575-ts-camel-case/docgen.snapshot @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -const iconButton = function IconButton(props) { +const iconButton = function IconButton() { return /*#__PURE__*/React.createElement("div", { className: "icon-button" }, "icon-button"); @@ -9,6 +9,9 @@ iconButton.propTypes = { // deepscan-disable-next-line color: PropTypes.string }; + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- we can't expect error as it isn't an error in 18 (development) but it is in 19 (sandbox) +// @ts-ignore not present on react 19 iconButton.defaultProps = { color: 'primary' }; diff --git a/code/renderers/react/template/stories/docgen-components/9575-ts-camel-case/input.tsx b/code/renderers/react/template/stories/docgen-components/9575-ts-camel-case/input.tsx index feee06599e1f..fd721e12299c 100644 --- a/code/renderers/react/template/stories/docgen-components/9575-ts-camel-case/input.tsx +++ b/code/renderers/react/template/stories/docgen-components/9575-ts-camel-case/input.tsx @@ -8,7 +8,7 @@ export interface IProps { color?: string; } -const iconButton: FC = function IconButton(props) { +const iconButton: FC = function IconButton() { return
icon-button
; }; @@ -17,6 +17,8 @@ iconButton.propTypes = { color: PropTypes.string, }; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- we can't expect error as it isn't an error in 18 (development) but it is in 19 (sandbox) +// @ts-ignore not present on react 19 iconButton.defaultProps = { color: 'primary', }; diff --git a/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx b/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx index ba15a430f025..2f84aee82ba5 100644 --- a/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx +++ b/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx @@ -4,7 +4,7 @@ import React from 'react'; // @ts-ignore (js import not supported in TS) import { imported } from '../imported'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore (css import not supported in TS) +// @ts-ignore no types for this import * as styles from '../imported.module.css'; const local = 'local-value'; @@ -29,7 +29,9 @@ interface PropsWriterProps { importedReference?: string; globalReference?: any; stringGlobalName?: string; - myClass: typeof styles.foo; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore no types for this + myClass: typeof styles; } /** A component that renders its props */ @@ -37,6 +39,8 @@ export const PropsWriter: React.FC = (props: PropsWriterProps)
{JSON.stringify(props)}
); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- we can't expect error as it isn't an error in 18 (development) but it is in 19 (sandbox) +// @ts-ignore not present on react 19 PropsWriter.defaultProps = { numberOptional: 1, stringOptional: 'stringOptional', @@ -49,6 +53,8 @@ PropsWriter.defaultProps = { importedReference: imported, globalReference: Date, stringGlobalName: 'top', + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore no types for this myClass: styles.foo, }; diff --git a/code/renderers/react/template/stories/docgen-components/ts-react-fc/docgen.snapshot b/code/renderers/react/template/stories/docgen-components/ts-react-fc/docgen.snapshot index 1bbff1967396..fca0d799199d 100644 --- a/code/renderers/react/template/stories/docgen-components/ts-react-fc/docgen.snapshot +++ b/code/renderers/react/template/stories/docgen-components/ts-react-fc/docgen.snapshot @@ -17,7 +17,7 @@ var StringEnum = /*#__PURE__*/function (StringEnum) { StringEnum["TopCenter"] = "top-center"; return StringEnum; }(StringEnum || {}); -export const TypeScriptProps = props => /*#__PURE__*/React.createElement("div", null, "TypeScript!"); +export const TypeScriptProps = () => /*#__PURE__*/React.createElement("div", null, "TypeScript!"); export const component = TypeScriptProps; TypeScriptProps.__docgenInfo = { "description": "", diff --git a/code/renderers/react/template/stories/docgen-components/ts-react-fc/input.tsx b/code/renderers/react/template/stories/docgen-components/ts-react-fc/input.tsx index 2e6e3d6821b1..56ad85711dc4 100644 --- a/code/renderers/react/template/stories/docgen-components/ts-react-fc/input.tsx +++ b/code/renderers/react/template/stories/docgen-components/ts-react-fc/input.tsx @@ -88,6 +88,6 @@ interface TypeScriptPropsProps { inlinedNumericLiteralUnion: 0 | 1 | 2; } -export const TypeScriptProps: FC = (props) =>
TypeScript!
; +export const TypeScriptProps: FC = () =>
TypeScript!
; export const component = TypeScriptProps; diff --git a/code/renderers/react/template/stories/docgen-components/ts-types/docgen.snapshot b/code/renderers/react/template/stories/docgen-components/ts-types/docgen.snapshot index 8b77d5696cdb..2a865e70565e 100644 --- a/code/renderers/react/template/stories/docgen-components/ts-types/docgen.snapshot +++ b/code/renderers/react/template/stories/docgen-components/ts-types/docgen.snapshot @@ -21,6 +21,8 @@ var StringEnum = /*#__PURE__*/function (StringEnum) { return StringEnum; }(StringEnum || {}); export const TypeScriptProps = () => /*#__PURE__*/React.createElement("div", null, "TypeScript!"); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- we can't expect error as it isn't an error in 18 (development) but it is in 19 (sandbox) +// @ts-ignore not present on react 19 TypeScriptProps.defaultProps = { any: 'Any value', string: 'A string value', diff --git a/code/renderers/react/template/stories/docgen-components/ts-types/input.tsx b/code/renderers/react/template/stories/docgen-components/ts-types/input.tsx index 4cb8703a9daa..23c7682a57ea 100644 --- a/code/renderers/react/template/stories/docgen-components/ts-types/input.tsx +++ b/code/renderers/react/template/stories/docgen-components/ts-types/input.tsx @@ -93,6 +93,8 @@ interface TypeScriptPropsProps { } export const TypeScriptProps: FC = () =>
TypeScript!
; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- we can't expect error as it isn't an error in 18 (development) but it is in 19 (sandbox) +// @ts-ignore not present on react 19 TypeScriptProps.defaultProps = { any: 'Any value', string: 'A string value', diff --git a/code/yarn.lock b/code/yarn.lock index 04808c099b33..defc2a7f6fcf 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -498,6 +498,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.28.4": + version: 7.28.5 + resolution: "@babel/core@npm:7.28.5" + dependencies: + "@babel/code-frame": "npm:^7.27.1" + "@babel/generator": "npm:^7.28.5" + "@babel/helper-compilation-targets": "npm:^7.27.2" + "@babel/helper-module-transforms": "npm:^7.28.3" + "@babel/helpers": "npm:^7.28.4" + "@babel/parser": "npm:^7.28.5" + "@babel/template": "npm:^7.27.2" + "@babel/traverse": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" + "@jridgewell/remapping": "npm:^2.3.5" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 10c0/535f82238027621da6bdffbdbe896ebad3558b311d6f8abc680637a9859b96edbf929ab010757055381570b29cf66c4a295b5618318d27a4273c0e2033925e72 + languageName: node + linkType: hard + "@babel/generator@npm:7.17.7": version: 7.17.7 resolution: "@babel/generator@npm:7.17.7" @@ -535,6 +558,19 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/generator@npm:7.28.5" + dependencies: + "@babel/parser": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" + "@jridgewell/gen-mapping": "npm:^0.3.12" + "@jridgewell/trace-mapping": "npm:^0.3.28" + jsesc: "npm:^3.0.2" + checksum: 10c0/9f219fe1d5431b6919f1a5c60db8d5d34fe546c0d8f5a8511b32f847569234ffc8032beb9e7404649a143f54e15224ecb53a3d11b6bb85c3203e573d91fca752 + languageName: node + linkType: hard + "@babel/helper-annotate-as-pure@npm:7.25.9": version: 7.25.9 resolution: "@babel/helper-annotate-as-pure@npm:7.25.9" @@ -765,6 +801,17 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/parser@npm:7.28.5" + dependencies: + "@babel/types": "npm:^7.28.5" + bin: + parser: ./bin/babel-parser.js + checksum: 10c0/5bbe48bf2c79594ac02b490a41ffde7ef5aa22a9a88ad6bcc78432a6ba8a9d638d531d868bd1f104633f1f6bba9905746e15185b8276a3756c42b765d131b1ef + languageName: node + linkType: hard + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.25.9, @babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.27.1" @@ -5723,13 +5770,6 @@ __metadata: languageName: node linkType: hard -"@rolldown/pluginutils@npm:1.0.0-beta.24": - version: 1.0.0-beta.24 - resolution: "@rolldown/pluginutils@npm:1.0.0-beta.24" - checksum: 10c0/148af131a0a91f1d0786742068417768de97de0492483cc3e0a928212f33a8afd9a4e48cb5551436193b6099903217849ff5f414dd9a9ccaa37f3c62ff1f4bce - languageName: node - linkType: hard - "@rolldown/pluginutils@npm:1.0.0-beta.27": version: 1.0.0-beta.27 resolution: "@rolldown/pluginutils@npm:1.0.0-beta.27" @@ -5737,6 +5777,20 @@ __metadata: languageName: node linkType: hard +"@rolldown/pluginutils@npm:1.0.0-beta.43": + version: 1.0.0-beta.43 + resolution: "@rolldown/pluginutils@npm:1.0.0-beta.43" + checksum: 10c0/1c17a0b16c277a0fdbab080fd22ef91e37c1f0d710ecfdacb6a080068062eb14ff030d0e9d2ec2325a1d4246dba0c49625755c82c0090f6cbf98d16e80183e02 + languageName: node + linkType: hard + +"@rolldown/pluginutils@npm:1.0.0-beta.46": + version: 1.0.0-beta.46 + resolution: "@rolldown/pluginutils@npm:1.0.0-beta.46" + checksum: 10c0/45664c89b2e24262b103457ca14e1aa0b7f658f5ace4eb4f10f327d88810cad908ec3150d8fc646fe285b96eb66b25defce97aa6eb0a45fe23a8a2dbcda0040c + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^5.0.2": version: 5.3.0 resolution: "@rollup/pluginutils@npm:5.3.0" @@ -6754,7 +6808,7 @@ __metadata: "@storybook/react-vite": "workspace:*" "@types/node": "npm:^22.0.0" typescript: "npm:^5.8.3" - vite-plugin-rnw: "npm:^0.0.6" + vite-plugin-rnw: "npm:^0.0.8" vite-tsconfig-paths: "npm:^5.1.4" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -8572,6 +8626,22 @@ __metadata: languageName: node linkType: hard +"@vitejs/plugin-react@npm:^5.1.0": + version: 5.1.0 + resolution: "@vitejs/plugin-react@npm:5.1.0" + dependencies: + "@babel/core": "npm:^7.28.4" + "@babel/plugin-transform-react-jsx-self": "npm:^7.27.1" + "@babel/plugin-transform-react-jsx-source": "npm:^7.27.1" + "@rolldown/pluginutils": "npm:1.0.0-beta.43" + "@types/babel__core": "npm:^7.20.5" + react-refresh: "npm:^0.18.0" + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + checksum: 10c0/e192a12e2b854df109eafb1d06c0bc848e8e2b162c686aa6b999b1048658983e72674b2068ccc37562fcce44d32ad92b65f3a4e1897a0cb7859c2ee69cc63eac + languageName: node + linkType: hard + "@vitejs/plugin-vue@npm:^4.4.0": version: 4.6.2 resolution: "@vitejs/plugin-vue@npm:4.6.2" @@ -22430,6 +22500,13 @@ __metadata: languageName: node linkType: hard +"react-refresh@npm:^0.18.0": + version: 0.18.0 + resolution: "react-refresh@npm:0.18.0" + checksum: 10c0/34a262f7fd803433a534f50deb27a148112a81adcae440c7d1cbae7ef14d21ea8f2b3d783e858cb7698968183b77755a38b4d4b5b1d79b4f4689c2f6d358fff2 + languageName: node + linkType: hard + "react-remove-scroll-bar@npm:^2.3.7": version: 2.3.8 resolution: "react-remove-scroll-bar@npm:2.3.8" @@ -26417,25 +26494,20 @@ __metadata: languageName: node linkType: hard -"vite-plugin-rnw@npm:^0.0.6": - version: 0.0.6 - resolution: "vite-plugin-rnw@npm:0.0.6" +"vite-plugin-rnw@npm:^0.0.8": + version: 0.0.8 + resolution: "vite-plugin-rnw@npm:0.0.8" dependencies: - "@babel/core": "npm:^7.28.0" - "@babel/plugin-transform-flow-strip-types": "npm:^7.27.1" - "@babel/plugin-transform-modules-commonjs": "npm:^7.27.1" - "@babel/plugin-transform-react-jsx-self": "npm:^7.27.1" - "@babel/plugin-transform-react-jsx-source": "npm:^7.27.1" "@bunchtogether/vite-plugin-flow": "npm:^1.0.2" - "@rolldown/pluginutils": "npm:1.0.0-beta.24" - "@types/babel__core": "npm:^7.20.5" - react-refresh: "npm:^0.17.0" + "@rolldown/pluginutils": "npm:1.0.0-beta.46" + "@vitejs/plugin-react": "npm:^5.1.0" + magic-string: "npm:^0.30.11" vite-plugin-commonjs: "npm:^0.10.4" peerDependencies: react-native-web: "*" typescript: ^5 vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - checksum: 10c0/a2b90d45ad9484fe02273a35b3b7125b8d6aaf6e7f0c239f2d9dafe12b2b38bdfe14257d3fe05c913d02312b4b75d006d9cc92c874a1deb2840c6168f07ffff9 + checksum: 10c0/91dba6f09974ab3f8496e23f45866ef2fba297ab423622174e75e0cebfbfd36a547faf513de5f9bcaa22f8d88f6f222f4fac17bbb8107a4274e9529b14d18ab9 languageName: node linkType: hard diff --git a/docs/_snippets/component-story-with-custom-render-function.md b/docs/_snippets/component-story-with-custom-render-function.md index 6dcfb9b69e08..22469fcfd584 100644 --- a/docs/_snippets/component-story-with-custom-render-function.md +++ b/docs/_snippets/component-story-with-custom-render-function.md @@ -325,3 +325,31 @@ export const Example = meta.story({ ), }); ``` + +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" + + + + {#snippet template(args)} + +
+

Example

+
+
+ +
+
+ {/snippet} +
+``` diff --git a/docs/_snippets/svelte-framework-options-docgen.md b/docs/_snippets/svelte-framework-options-docgen.md new file mode 100644 index 000000000000..ed1eb1da1d65 --- /dev/null +++ b/docs/_snippets/svelte-framework-options-docgen.md @@ -0,0 +1,27 @@ +```js filename=".storybook/main.js" renderer="svelte" language="js" +// Replace your-framework with svelte-vite or sveltekit +export default { + framework: { + name: '@storybook/your-framework', + options: { + docgen: false, // Disable docgen for better performance + }, + }, +}; +``` + +```ts filename=".storybook/main.ts" renderer="svelte" language="ts" +// Replace your-framework with svelte-vite or sveltekit +import type { StorybookConfig } from '@storybook/your-framework'; + +const config: StorybookConfig = { + framework: { + name: '@storybook/your-framework', + options: { + docgen: false, // Disable docgen for better performance + }, + }, +}; + +export default config; +``` diff --git a/docs/_snippets/sveltekit-mock-features.md b/docs/_snippets/sveltekit-mock-features.md new file mode 100644 index 000000000000..d6133ef12447 --- /dev/null +++ b/docs/_snippets/sveltekit-mock-features.md @@ -0,0 +1,142 @@ +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" + + + +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, +}; + +export const MyStory = { + parameters: { + sveltekit_experimental: { + state: { + page: { + data: { + test: 'passed', + }, + }, + navigating: { + to: { + route: { id: '/storybook' }, + params: {}, + url: new URL('http://localhost/storybook'), + }, + }, + updated: { + current: true, + }, + }, + }, + }, +}; +``` + +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" + + + +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/sveltekit'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const MyStory: Story = { + parameters: { + sveltekit_experimental: { + state: { + page: { + data: { + test: 'passed', + }, + }, + navigating: { + to: { + route: { id: '/storybook' }, + params: {}, + url: new URL('http://localhost/storybook'), + }, + }, + updated: { + current: true, + }, + }, + }, + }, +}; +``` diff --git a/docs/_snippets/sveltekit-mock-links.md b/docs/_snippets/sveltekit-mock-links.md new file mode 100644 index 000000000000..dab06cea2a63 --- /dev/null +++ b/docs/_snippets/sveltekit-mock-links.md @@ -0,0 +1,118 @@ +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="js" tabTitle="Svelte CSF" + + + { + console.log(to, event); + }, + '/root.*': { + callback: (to, event) => { + console.log(to, event); + }, + asRegex: true, + }, + }, + }, + }} +/> +``` + +```js filename="MyComponent.stories.js" renderer="svelte" language="js" tabTitle="CSF" +import MyComponent from './MyComponent.svelte'; + +export default { + component: MyComponent, +}; + +export const MyStory = { + parameters: { + sveltekit_experimental: { + hrefs: { + '/basic-href': (to, event) => { + console.log(to, event); + }, + '/root.*': { + callback: (to, event) => { + console.log(to, event); + }, + asRegex: true, + }, + }, + }, + }, +}; +``` + +```svelte filename="MyComponent.stories.svelte" renderer="svelte" language="ts" tabTitle="Svelte CSF" + + + { + console.log(to, event); + }, + '/root.*': { + callback: (to, event) => { + console.log(to, event); + }, + asRegex: true, + }, + }, + }, + }} +/> +``` + +```ts filename="MyComponent.stories.ts" renderer="svelte" language="ts" tabTitle="CSF" +import type { Meta, StoryObj } from '@storybook/sveltekit'; + +import MyComponent from './MyComponent.svelte'; + +const meta = { + component: MyComponent, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const MyStory: Story = { + parameters: { + sveltekit_experimental: { + hrefs: { + '/basic-href': (to, event) => { + console.log(to, event); + }, + '/root.*': { + callback: (to, event) => { + console.log(to, event); + }, + asRegex: true, + }, + }, + }, + }, +}; +``` diff --git a/docs/api/csf/index.mdx b/docs/api/csf/index.mdx index b212450a8bfe..50afb12d6183 100644 --- a/docs/api/csf/index.mdx +++ b/docs/api/csf/index.mdx @@ -139,6 +139,19 @@ When the story renders in the UI, Storybook executes each step defined in the `p When Storybook loads this story, it will detect the existence of a `render` function and adjust the component rendering accordingly based on what's defined. + + ## Custom render functions + + If you're using Svelte CSF to write your stories, you can add a custom snippet to allow you additional control over how your story renders. For example, if you were writing a story and you wanted to specify how your component should render, you could write the following: + + {/* prettier-ignore-start */} + + + + {/* prettier-ignore-end */} + + + ## Storybook export vs. name handling Storybook handles named exports and the `name` option slightly differently. When should you use one vs. the other? diff --git a/docs/get-started/frameworks/svelte-vite.mdx b/docs/get-started/frameworks/svelte-vite.mdx index 46e0bd7e87a7..f38d41573155 100644 --- a/docs/get-started/frameworks/svelte-vite.mdx +++ b/docs/get-started/frameworks/svelte-vite.mdx @@ -203,21 +203,12 @@ Default: `true` Enables or disables automatic documentation generation for component properties. When disabled, Storybook will skip the docgen processing step during build, which can improve build performance. -```ts title=".storybook/main.ts" -import type { StorybookConfig } from '@storybook/svelte-vite'; - -const config: StorybookConfig = { - framework: { - name: '@storybook/svelte-vite', - options: { - docgen: false, // Disable docgen for better performance - }, - }, -}; - -export default config; -``` +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} -##### When to disable docgen +#### When to disable docgen Disabling docgen can improve build performance for large projects, but [argTypes won't be inferred automatically](../../api/arg-types.mdx#automatic-argtype-inference), which will prevent features like [Controls](../../essentials/controls.mdx) and [docs](../../writing-docs/autodocs.mdx) from working as expected. To use those features, you will need to [define `argTypes` manually](../../api/arg-types.mdx#manually-specifying-argtypes). diff --git a/docs/get-started/frameworks/sveltekit.mdx b/docs/get-started/frameworks/sveltekit.mdx index a099ef60c09a..84b787e96a3c 100644 --- a/docs/get-started/frameworks/sveltekit.mdx +++ b/docs/get-started/frameworks/sveltekit.mdx @@ -76,49 +76,29 @@ However, SvelteKit has some [Kit-specific modules](https://kit.svelte.dev/docs/m | Module | Status | Note | | ---------------------------------------------------------------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -| [`$app/environment`](https://kit.svelte.dev/docs/modules#$app-environment) | ✅ Supported | `version` is always empty in Storybook. | -| [`$app/forms`](https://kit.svelte.dev/docs/modules#$app-forms) | ⚠️ **Experimental** | See [How to mock](#how-to-mock). | -| [`$app/navigation`](https://kit.svelte.dev/docs/modules#$app-navigation) | ⚠️ **Experimental** | See [How to mock](#how-to-mock). | -| [`$app/paths`](https://kit.svelte.dev/docs/modules#$app-paths) | ✅ Supported | Requires SvelteKit 1.4.0 or newer. | +| [`$app/environment`](https://svelte.dev/docs/kit/$app-environment) | ✅ Supported | `version` is always empty in Storybook. | +| [`$app/forms`](https://svelte.dev/docs/kit/$app-forms) | ⚠️ **Experimental** | See [How to mock](#how-to-mock). | +| [`$app/navigation`](https://svelte.dev/docs/kit/$app-navigation) | ⚠️ **Experimental** | See [How to mock](#how-to-mock). | +| [`$app/paths`](https://svelte.dev/docs/kit/$app-paths) | ✅ Supported | Requires SvelteKit 1.4.0 or newer. | | [`$app/state`](https://svelte.dev/docs/kit/$app-state) | ⚠️ **Experimental** | Requires SvelteKit `v2.12` or newer. See [How to mock](#how-to-mock). | -| [`$app/stores`](https://kit.svelte.dev/docs/modules#$app-stores) | ⚠️ **Experimental** | See [How to mock](#how-to-mock). | -| [`$env/dynamic/public`](https://kit.svelte.dev/docs/modules#$env-dynamic-public) | 🚧 Partially supported | Only supported in development mode. Storybook is built as a static app with no server-side API, so it cannot dynamically serve content. | -| [`$env/static/public`](https://kit.svelte.dev/docs/modules#$env-static-public) | ✅ Supported | | -| [`$lib`](https://kit.svelte.dev/docs/modules#$lib) | ✅ Supported | | -| [`@sveltejs/kit/*`](https://kit.svelte.dev/docs/modules#sveltejs-kit) | ✅ Supported | | -| [`$env/dynamic/private`](https://kit.svelte.dev/docs/modules#$env-dynamic-private) | ⛔ Not supported | This is a server-side feature, and Storybook renders all components on the client. | -| [`$env/static/private`](https://kit.svelte.dev/docs/modules#$env-static-private) | ⛔ Not supported | This is a server-side feature, and Storybook renders all components on the client. | -| [`$service-worker`](https://kit.svelte.dev/docs/modules#$service-worker) | ⛔ Not supported | This is a service worker feature, which does not apply to Storybook. | +| [`$app/stores`](https://svelte.dev/docs/kit/$app-stores) | ⚠️ **Experimental** | See [How to mock](#how-to-mock). | +| [`$env/dynamic/public`](https://svelte.dev/docs/kit/$env-dynamic-public) | 🚧 Partially supported | Only supported in development mode. Storybook is built as a static app with no server-side API, so it cannot dynamically serve content. | +| [`$env/static/public`](https://svelte.dev/docs/kit/$env-static-public) | ✅ Supported | | +| [`$lib`](https://svelte.dev/docs/kit/$lib) | ✅ Supported | | +| [`@sveltejs/kit/*`](https://svelte.dev/docs/kit/@sveltejs-kit) | ✅ Supported | | +| [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private) | ⛔ Not supported | This is a server-side feature, and Storybook renders all components on the client. | +| [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private) | ⛔ Not supported | This is a server-side feature, and Storybook renders all components on the client. | +| [`$service-worker`](https://svelte.dev/docs/kit/$service-worker) | ⛔ Not supported | This is a service worker feature, which does not apply to Storybook. | ## How to mock To mock a SvelteKit import you can define it within `parameters.sveltekit_experimental`: -```ts title="MyComponent.stories.js|ts" -export const MyStory = { - parameters: { - sveltekit_experimental: { - state: { - page: { - data: { - test: 'passed', - }, - }, - navigating: { - to: { - route: { id: '/storybook' }, - params: {}, - url: new URL('http://localhost/storybook'), - }, - }, - updated: { - current: true, - }, - }, - }, - }, -}; -``` +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} The [available parameters](#parameters) are documented in the API section, below. @@ -128,25 +108,11 @@ The default link-handling behavior (e.g., when clicking an `` el You can override this by assigning an object to `parameters.sveltekit_experimental.hrefs`, where the keys are strings representing an href, and the values define your mock. For example: -```ts title="MyComponent.stories.js|ts" -export const MyStory = { - parameters: { - sveltekit_experimental: { - hrefs: { - '/basic-href': (to, event) => { - console.log(to, event); - }, - '/root.*': { - callback: (to, event) => { - console.log(to, event); - }, - asRegex: true, - }, - }, - }, - }, -}; -``` +{/* prettier-ignore-start */} + + + +{/* prettier-ignore-end */} See the [API reference](#hrefs) for more information. @@ -276,7 +242,7 @@ This framework contributes the following [parameters](../../writing-stories/para Type: `{ enhance: () => void }` -Provides mocks for the [`$app/forms`](https://kit.svelte.dev/docs/modules#$app-forms) module. +Provides mocks for the [`$app/forms`](https://svelte.dev/docs/kit/$app-forms) module. ##### `forms.enhance` @@ -292,69 +258,69 @@ If you have an `` tag inside your code with the `href` attribute that match #### `navigation` -Type: See [SvelteKit docs](https://kit.svelte.dev/docs/modules#$app-navigation) +Type: See [SvelteKit docs](https://svelte.dev/docs/kit/$app-navigation) -Provides mocks for the [`$app/navigation`](https://kit.svelte.dev/docs/modules#$app-navigation) module. +Provides mocks for the [`$app/navigation`](https://svelte.dev/docs/kit/$app-navigation) module. ##### `navigation.goto` -Type: See [SvelteKit docs](https://kit.svelte.dev/docs/modules#$app-navigation-goto) +Type: See [SvelteKit docs](https://svelte.dev/docs/kit/$app-navigation#goto) -A callback that will be called whenever [`goto`](https://kit.svelte.dev/docs/modules#$app-navigation-goto) is called. If no function is provided, an action will be logged to the [Actions panel](../../essentials/actions.mdx). +A callback that will be called whenever [`goto`](https://svelte.dev/docs/kit/$app-navigation#goto) is called. If no function is provided, an action will be logged to the [Actions panel](../../essentials/actions.mdx). ##### `navigation.pushState` -Type: See [SvelteKit docs](https://kit.svelte.dev/docs/modules#$app-navigation-pushstate) +Type: See [SvelteKit docs](https://svelte.dev/docs/kit/$app-navigation#pushState) -A callback that will be called whenever [`pushState`](https://kit.svelte.dev/docs/modules#$app-navigation-pushstate) is called. If no function is provided, an action will be logged to the [Actions panel](../../essentials/actions.mdx). +A callback that will be called whenever [`pushState`](https://svelte.dev/docs/kit/$app-navigation#pushState) is called. If no function is provided, an action will be logged to the [Actions panel](../../essentials/actions.mdx). ##### `navigation.replaceState` -Type: See [SvelteKit docs](https://kit.svelte.dev/docs/modules#$app-navigation-replacestate) +Type: See [SvelteKit docs](https://svelte.dev/docs/kit/$app-navigation#replaceState) -A callback that will be called whenever [`replaceState`](https://kit.svelte.dev/docs/modules#$app-navigation-replacestate) is called. If no function is provided, an action will be logged to the [Actions panel](../../essentials/actions.mdx). +A callback that will be called whenever [`replaceState`](https://svelte.dev/docs/kit/$app-navigation#replaceState) is called. If no function is provided, an action will be logged to the [Actions panel](../../essentials/actions.mdx). ##### `navigation.invalidate` -Type: See [SvelteKit docs](https://kit.svelte.dev/docs/modules#$app-navigation-invalidate) +Type: See [SvelteKit docs](https://svelte.dev/docs/kit/$app-navigation#invalidate) -A callback that will be called whenever [`invalidate`](https://kit.svelte.dev/docs/modules#$app-navigation-invalidate) is called. If no function is provided, an action will be logged to the [Actions panel](../../essentials/actions.mdx). +A callback that will be called whenever [`invalidate`](https://svelte.dev/docs/kit/$app-navigation#invalidate) is called. If no function is provided, an action will be logged to the [Actions panel](../../essentials/actions.mdx). ##### `navigation.invalidateAll` -Type: See [SvelteKit docs](https://kit.svelte.dev/docs/modules#$app-navigation-invalidateall) +Type: See [SvelteKit docs](https://svelte.dev/docs/kit/$app-navigation#invalidateAll) -A callback that will be called whenever [`invalidateAll`](https://kit.svelte.dev/docs/modules#$app-navigation-invalidateall) is called. If no function is provided, an action will be logged to the [Actions panel](../../essentials/actions.mdx). +A callback that will be called whenever [`invalidateAll`](https://svelte.dev/docs/kit/$app-navigation#invalidateAll) is called. If no function is provided, an action will be logged to the [Actions panel](../../essentials/actions.mdx). ##### `navigation.afterNavigate` -Type: See [SvelteKit docs](https://kit.svelte.dev/docs/modules#$app-navigation-afternavigate) +Type: See [SvelteKit docs](https://svelte.dev/docs/kit/$app-navigation#afterNavigate) -An object that will be passed to the [`afterNavigate`](https://kit.svelte.dev/docs/modules#$app-navigation-afternavigate) function, which will be invoked when the `onMount` event fires. +An object that will be passed to the [`afterNavigate`](https://svelte.dev/docs/kit/$app-navigation#afterNavigate) function, which will be invoked when the `onMount` event fires. #### `stores` -Type: See [SvelteKit docs](https://kit.svelte.dev/docs/modules#$app-stores) +Type: See [SvelteKit docs](https://svelte.dev/docs/kit/$app-stores) -Provides mocks for the [`$app/stores`](https://kit.svelte.dev/docs/modules#$app-stores) module. +Provides mocks for the [`$app/stores`](https://svelte.dev/docs/kit/$app-stores) module. ##### `stores.navigating` -Type: See [SvelteKit docs](https://kit.svelte.dev/docs/modules#$app-stores-navigating) +Type: See [SvelteKit docs](https://svelte.dev/docs/kit/$app-stores#navigating) -A partial version of the [`navigating`](https://kit.svelte.dev/docs/modules#$app-stores-navigating) store. +A partial version of the [`navigating`](https://svelte.dev/docs/kit/$app-stores#navigating) store. ##### `stores.page` -Type: See [SvelteKit docs](https://kit.svelte.dev/docs/modules#$app-stores-page) +Type: See [SvelteKit docs](https://svelte.dev/docs/kit/$app-stores#page) -A partial version of the [`page`](https://kit.svelte.dev/docs/modules#$app-stores-page) store. +A partial version of the [`page`](https://svelte.dev/docs/kit/$app-stores#page) store. ##### `stores.updated` Type: boolean -A boolean representing the value of [`updated`](https://kit.svelte.dev/docs/modules#$app-stores-updated) (you can also access `updated.check()` which will be a no-op). +A boolean representing the value of [`updated`](https://svelte.dev/docs/kit/$app-stores#updated) (you can also access `updated.check()` which will be a no-op). #### `state` @@ -406,22 +372,13 @@ Default: `true` Enables or disables automatic documentation generation for component properties. When disabled, Storybook will skip the docgen processing step during build, which can improve build performance. -```ts title=".storybook/main.ts" -import type { StorybookConfig } from '@storybook/sveltekit'; +{/* prettier-ignore-start */} -const config: StorybookConfig = { - framework: { - name: '@storybook/sveltekit', - options: { - docgen: false, // Disable docgen for better performance - }, - }, -}; + -export default config; -``` +{/* prettier-ignore-end */} -##### When to disable docgen +#### When to disable docgen Disabling docgen can improve build performance for large projects, but [argTypes won't be inferred automatically](../../api/arg-types.mdx#automatic-argtype-inference), which will prevent features like [Controls](../../essentials/controls.mdx) and [docs](../../writing-docs/autodocs.mdx) from working as expected. To use those features, you will need to [define `argTypes` manually](../../api/arg-types.mdx#manually-specifying-argtypes). diff --git a/docs/versions/next.json b/docs/versions/next.json index fa4ab0f27d6e..fcc882fcca9d 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"10.1.0-alpha.7","info":{"plain":"- CSF: Fix export interface declaration for NextPreview - [#32914](https://github.com/storybookjs/storybook/pull/32914), thanks @icopp!\n- Controls: Add range validation in Number Control - [#32539](https://github.com/storybookjs/storybook/pull/32539), thanks @ia319!\n- Fix: Export interface declaration for ReactMeta - [#32915](https://github.com/storybookjs/storybook/pull/32915), thanks @icopp!\n- React: Improve error messages in component manifest - [#32954](https://github.com/storybookjs/storybook/pull/32954), thanks @kasperpeulen!\n- Vitest Addon: Add support for Preact - [#32948](https://github.com/storybookjs/storybook/pull/32948), thanks @yannbf!"}} \ No newline at end of file +{"version":"10.1.0-alpha.8","info":{"plain":"- ESLint: Only apply csf-strict rules on stories files - [#31963](https://github.com/storybookjs/storybook/pull/31963), thanks @cylewaitforit!\n- Middleware: Prepend `file://` to middleware `import` for Windows support - [#32955](https://github.com/storybookjs/storybook/pull/32955), thanks @ndelangen!\n- Next.js: Update SWC loader to support new wasm detection - [#33003](https://github.com/storybookjs/storybook/pull/33003), thanks @yannbf!\n- React Native Web: Update vite-plugin-rnw for overall improvements - [#32991](https://github.com/storybookjs/storybook/pull/32991), thanks @dannyhw!"}} \ No newline at end of file diff --git a/scripts/get-template.ts b/scripts/get-template.ts index edba3a3b071f..984325dbf9eb 100644 --- a/scripts/get-template.ts +++ b/scripts/get-template.ts @@ -17,7 +17,7 @@ import { esMain } from './utils/esmain'; const sandboxDir = process.env.SANDBOX_ROOT || SANDBOX_DIRECTORY; -type Template = Pick; +type Template = Pick; export type TemplateKey = keyof typeof allTemplates; export type Templates = Record; @@ -36,6 +36,14 @@ async function pathExists(path: string) { } } +function isTaskSkipped(template: Template, script: string): boolean { + return ( + template.inDevelopment !== true && + !template.skipTasks?.includes(script as SkippableTask) && + (script !== 'check-sandbox' || template.typeCheck) + ); +} + export async function getTemplate( cadence: Cadence, scriptName: string, @@ -62,10 +70,7 @@ export async function getTemplate( potentialTemplateKeys = potentialTemplateKeys.filter((t) => { const currentTemplate = allTemplates[t] as Template; - return ( - currentTemplate.inDevelopment !== true && - !currentTemplate.skipTasks?.includes(scriptName as SkippableTask) - ); + return isTaskSkipped(currentTemplate, scriptName); }); if (potentialTemplateKeys.length !== total) { @@ -86,6 +91,7 @@ export async function getTemplate( const tasksMap = { sandbox: 'create-sandboxes', build: 'build-sandboxes', + 'check-sandbox': 'check-sandboxes', chromatic: 'chromatic-sandboxes', 'e2e-tests': 'e2e-production', 'e2e-tests-dev': 'e2e-dev', @@ -122,10 +128,7 @@ async function checkParallelism(cadence?: Cadence, scriptName?: TaskKey) { const templateKeysPerScript = potentialTemplateKeys.filter((t) => { const currentTemplate = allTemplates[t] as Template; - return ( - currentTemplate.inDevelopment !== true && - !currentTemplate.skipTasks?.includes(script as SkippableTask) - ); + return isTaskSkipped(currentTemplate, script); }); const workflowJobsRaw: (string | { [key: string]: any })[] = data.workflows[cad].jobs; const workflowJobs = workflowJobsRaw diff --git a/scripts/run-registry.ts b/scripts/run-registry.ts index 4dd99f8e3d48..fc03fe5a3039 100755 --- a/scripts/run-registry.ts +++ b/scripts/run-registry.ts @@ -13,6 +13,7 @@ import { parseConfigFile, runServer } from 'verdaccio'; import { maxConcurrentTasks } from './utils/concurrency'; import { PACKS_DIRECTORY } from './utils/constants'; +import { killProcessOnPort } from './utils/kill-process-on-port'; import { getWorkspaces } from './utils/workspace'; program @@ -37,6 +38,10 @@ const pathExists = async (p: string) => { }; const startVerdaccio = async () => { + // Kill Verdaccio related processes if they are already running + await killProcessOnPort(6001); + await killProcessOnPort(6002); + const ready = { proxy: false, verdaccio: false, diff --git a/scripts/task.ts b/scripts/task.ts index c2e477953964..42a235448b70 100644 --- a/scripts/task.ts +++ b/scripts/task.ts @@ -17,6 +17,7 @@ import { version } from '../code/package.json'; import { bench } from './tasks/bench'; import { build } from './tasks/build'; import { check } from './tasks/check'; +import { checkSandbox } from './tasks/check-sandbox'; import { chromatic } from './tasks/chromatic'; import { compile } from './tasks/compile'; import { dev } from './tasks/dev'; @@ -91,6 +92,7 @@ export const tasks = { // These tasks pertain to a single sandbox in the ../sandboxes dir generate, sandbox, + 'check-sandbox': checkSandbox, dev, 'smoke-test': smokeTest, build, diff --git a/scripts/tasks/check-sandbox.ts b/scripts/tasks/check-sandbox.ts new file mode 100644 index 000000000000..86932f724ee7 --- /dev/null +++ b/scripts/tasks/check-sandbox.ts @@ -0,0 +1,13 @@ +import type { Task } from '../task'; +import { exec } from '../utils/exec'; + +export const checkSandbox: Task = { + description: 'Typecheck a sandbox', + dependsOn: ['sandbox'], + async ready() { + return false; + }, + async run({ sandboxDir }, { dryRun, debug }) { + await exec(`yarn typecheck`, { cwd: sandboxDir }, { dryRun, debug }); + }, +}; diff --git a/scripts/tasks/sandbox-parts.ts b/scripts/tasks/sandbox-parts.ts index cbdc406db623..b7f0ec391d9e 100644 --- a/scripts/tasks/sandbox-parts.ts +++ b/scripts/tasks/sandbox-parts.ts @@ -229,6 +229,10 @@ export const init: Task['run'] = async ( default: } + if (template.typeCheck) { + await prepareTypeChecking(cwd); + } + if (!skipTemplateStories) { for (const addon of addons) { await executeCLIStep(steps.add, { @@ -917,6 +921,44 @@ async function prepareSvelteSandbox(cwd: string) { await writeConfig(svelteConfig); } +/** + * Prepare a sandbox for typechecking. + * + * 1. Add a typecheck script + * 2. Ensure typescript compiler options compatible with our example code + * 3. Set skipLibCheck to false to test storybook's public types + * + * This is currently configured for manipulating the output of `create vite` so will need some + * adjustment when we extend to type checking webpack sandboxes (if we ever do). + */ +async function prepareTypeChecking(cwd: string) { + const packageJsonPath = join(cwd, 'package.json'); + const packageJson = await readJson(packageJsonPath); + + packageJson.scripts = { + ...packageJson.scripts, + typecheck: 'yarn tsc -p tsconfig.app.json', + }; + await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)); + + const tsConfigPath = join(cwd, 'tsconfig.app.json'); + const tsConfigContent = await readFile(tsConfigPath, { encoding: 'utf-8' }); + // This does not preserve comments, but that shouldn't be an issue for sandboxes + const tsConfigJson = JSON5.parse(tsConfigContent); + + // We use enums + tsConfigJson.compilerOptions.erasableSyntaxOnly = false; + // Lots of unnecessary imports of react that need fixing + tsConfigJson.compilerOptions.noUnusedLocals = false; + // This is much better done by eslint + tsConfigJson.compilerOptions.noUnusedParameters = false; + // Means we can check our own public types + tsConfigJson.compilerOptions.skipLibCheck = false; + // Add chai global types + (tsConfigJson.compilerOptions.types ??= []).push('chai'); + await writeFile(tsConfigPath, JSON.stringify(tsConfigJson, null, 2)); +} + async function prepareAngularSandbox(cwd: string, templateName: string) { const angularJson = await readJson(join(cwd, 'angular.json')); diff --git a/scripts/tasks/sandbox.ts b/scripts/tasks/sandbox.ts index df31c0aaaed8..fca0e61dabee 100644 --- a/scripts/tasks/sandbox.ts +++ b/scripts/tasks/sandbox.ts @@ -46,6 +46,7 @@ export const sandbox: Task = { 'serve', 'chromatic', 'bench', + 'check-sandbox', ]; const isSelectedTaskAfterSandboxCreation = tasksAfterSandbox.includes(selectedTask); return isSelectedTaskAfterSandboxCreation && pathExists(sandboxDir); @@ -84,6 +85,8 @@ export const sandbox: Task = { // Adding the dep makes sure that even npx will use the linked workspace version. '@storybook/cli', 'lodash-es', + '@types/lodash-es', + '@types/aria-query', 'uuid', ]; diff --git a/scripts/utils/kill-process-on-port.ts b/scripts/utils/kill-process-on-port.ts new file mode 100644 index 000000000000..5654010f9f10 --- /dev/null +++ b/scripts/utils/kill-process-on-port.ts @@ -0,0 +1,54 @@ +// eslint-disable-next-line depend/ban-dependencies +import { execa } from 'execa'; + +const isWindows = process.platform === 'win32'; + +/** Kills any process that is listening on the specified port. */ +export const killProcessOnPort = async (port: number): Promise => { + try { + let pids: string[] = []; + + if (isWindows) { + // Windows: use netstat to find the process + try { + const { stdout } = await execa('netstat', ['-ano']); + const lines = stdout.split('\n'); + const regex = new RegExp(`TCP.*:${port}.*LISTENING\\s+(\\d+)`, 'i'); + + for (const line of lines) { + const match = line.match(regex); + if (match && match[1]) { + pids.push(match[1]); + } + } + } catch { + // netstat failed, ignore + } + } else { + // Unix-like (macOS, Linux): use lsof + try { + const { stdout } = await execa('lsof', ['-ti', `:${port}`]); + pids = stdout.trim().split('\n').filter(Boolean); + } catch { + // lsof failed or no process found + } + } + + if (pids.length > 0) { + console.log(`☠️ killing process(es) on port ${port}: ${pids.join(', ')}`); + + if (isWindows) { + await Promise.all( + pids.map((pid) => execa('taskkill', ['/PID', pid, '/F']).catch(() => {})) + ); + } else { + await Promise.all(pids.map((pid) => execa('kill', ['-9', pid]).catch(() => {}))); + } + + // Give the OS a moment to release the port + await new Promise((resolve) => setTimeout(resolve, 500)); + } + } catch { + // No process found on port or command failed, which is fine + } +}; diff --git a/scripts/utils/yarn.ts b/scripts/utils/yarn.ts index 97a7693b289b..a69237c40d21 100644 --- a/scripts/utils/yarn.ts +++ b/scripts/utils/yarn.ts @@ -111,7 +111,6 @@ export const addWorkaroundResolutions = async ({ '@testing-library/dom': '^9.3.4', '@testing-library/jest-dom': '^6.6.3', '@testing-library/user-event': '^14.5.2', - typescript: '~5.7.3', rollup: '4.44.2', }; diff --git a/test-storybooks/yarn-pnp/.storybook/main.ts b/test-storybooks/yarn-pnp/.storybook/main.ts index d0d77ba98234..88cd184ea953 100644 --- a/test-storybooks/yarn-pnp/.storybook/main.ts +++ b/test-storybooks/yarn-pnp/.storybook/main.ts @@ -1,25 +1,16 @@ -import { fileURLToPath } from "node:url"; -import { dirname } from "node:path"; -import type { StorybookConfig } from '@storybook/react-vite'; - -const config: StorybookConfig = { - "stories": [ - "../src/**/*.mdx", - "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)" - ], - "addons": [ - getAbsolutePath("@chromatic-com/storybook"), - getAbsolutePath("@storybook/addon-docs"), - getAbsolutePath("@storybook/addon-a11y"), - getAbsolutePath("@storybook/addon-vitest") - ], - "framework": { - "name": getAbsolutePath("@storybook/react-vite"), - "options": {} - } -}; -export default config; - -function getAbsolutePath(value: string): any { - return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`))); -} \ No newline at end of file +import type { StorybookConfig } from "@storybook/vue3-vite"; + +const config: StorybookConfig = { + stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], + addons: [ + "@chromatic-com/storybook", + "@storybook/addon-docs", + "@storybook/addon-a11y", + "@storybook/addon-vitest", + ], + framework: { + name: "@storybook/vue3-vite", + options: {}, + }, +}; +export default config; diff --git a/test-storybooks/yarn-pnp/.storybook/vitest.setup.ts b/test-storybooks/yarn-pnp/.storybook/vitest.setup.ts index 44922d55e49d..d3876789a13a 100644 --- a/test-storybooks/yarn-pnp/.storybook/vitest.setup.ts +++ b/test-storybooks/yarn-pnp/.storybook/vitest.setup.ts @@ -1,7 +1,7 @@ import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview"; -import { setProjectAnnotations } from '@storybook/react-vite'; -import * as projectAnnotations from './preview'; +import { setProjectAnnotations } from "@storybook/vue3-vite"; +import * as projectAnnotations from "./preview"; // This is an important step to apply the right configuration when testing your stories. // More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations -setProjectAnnotations([a11yAddonAnnotations, projectAnnotations]); \ No newline at end of file +setProjectAnnotations([a11yAddonAnnotations, projectAnnotations]); diff --git a/test-storybooks/yarn-pnp/README.md b/test-storybooks/yarn-pnp/README.md deleted file mode 100644 index 7959ce426934..000000000000 --- a/test-storybooks/yarn-pnp/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# React + TypeScript + Vite - -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. - -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh - -## Expanding the ESLint configuration - -If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: - -```js -export default tseslint.config([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - - // Remove tseslint.configs.recommended and replace with this - ...tseslint.configs.recommendedTypeChecked, - // Alternatively, use this for stricter rules - ...tseslint.configs.strictTypeChecked, - // Optionally, add this for stylistic rules - ...tseslint.configs.stylisticTypeChecked, - - // Other configs... - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` - -You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: - -```js -// eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' - -export default tseslint.config([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - // Enable lint rules for React - reactX.configs['recommended-typescript'], - // Enable lint rules for React DOM - reactDom.configs.recommended, - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` diff --git a/test-storybooks/yarn-pnp/eslint.config.js b/test-storybooks/yarn-pnp/eslint.config.js index bc656236fe0c..279fc495572d 100644 --- a/test-storybooks/yarn-pnp/eslint.config.js +++ b/test-storybooks/yarn-pnp/eslint.config.js @@ -3,8 +3,6 @@ import storybook from "eslint-plugin-storybook"; import js from '@eslint/js' import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' import tseslint from 'typescript-eslint' import { globalIgnores } from 'eslint/config' @@ -15,8 +13,6 @@ export default tseslint.config([ extends: [ js.configs.recommended, tseslint.configs.recommended, - reactHooks.configs['recommended-latest'], - reactRefresh.configs.vite, ], languageOptions: { ecmaVersion: 2020, diff --git a/test-storybooks/yarn-pnp/index.html b/test-storybooks/yarn-pnp/index.html index e4b78eae1230..fc7120dd11e1 100644 --- a/test-storybooks/yarn-pnp/index.html +++ b/test-storybooks/yarn-pnp/index.html @@ -1,13 +1,16 @@ - - - - - Vite + React + TS - - -
- - - + + + + + + vue3-vite + + + +
+ + + + \ No newline at end of file diff --git a/test-storybooks/yarn-pnp/package.json b/test-storybooks/yarn-pnp/package.json index 63e2d3e7eca3..8e30706caaa6 100644 --- a/test-storybooks/yarn-pnp/package.json +++ b/test-storybooks/yarn-pnp/package.json @@ -4,12 +4,11 @@ "private": true, "type": "module", "scripts": { - "build": "tsc -b && vite build", - "build-storybook": "storybook build", "dev": "vite", - "lint": "eslint .", + "build": "vue-tsc -b && vite build", "preview": "vite preview", - "storybook": "storybook dev -p 6006" + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" }, "resolutions": { "@playwright/test": "1.52.0", @@ -50,32 +49,28 @@ "storybook": "file:../../code/core" }, "dependencies": { - "react": "^19.1.0", - "react-dom": "^19.1.0" + "vue": "^3.5.22" }, "devDependencies": { "@chromatic-com/storybook": "^4.1.2", - "@eslint/js": "^9.29.0", - "@playwright/test": "1.52.0", - "@storybook/addon-a11y": "9.1.0-alpha.6", - "@storybook/addon-docs": "9.1.0-alpha.6", - "@storybook/addon-vitest": "9.1.0-alpha.6", - "@storybook/react-vite": "9.1.0-alpha.6", - "@types/react": "^19.1.8", - "@types/react-dom": "^19.1.6", - "@vitejs/plugin-react": "^4.5.2", - "@vitest/browser": "^3.2.4", - "@vitest/coverage-v8": "^3.2.4", + "@storybook/addon-a11y": "^10.1.0-alpha.6", + "@storybook/addon-docs": "^10.1.0-alpha.6", + "@storybook/addon-onboarding": "^10.1.0-alpha.6", + "@storybook/addon-vitest": "^10.1.0-alpha.6", + "@storybook/vue3-vite": "^10.1.0-alpha.6", + "@types/node": "^24.6.0", + "@vitejs/plugin-vue": "^6.0.1", + "@vitest/browser-playwright": "^4.0.7", + "@vitest/coverage-v8": "^4.0.7", + "@vue/tsconfig": "^0.8.1", "eslint": "^9.29.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-storybook": "9.1.0-alpha.6", - "globals": "^16.2.0", - "playwright": "1.52.0", - "storybook": "file:../../code/core", - "typescript": "~5.8.3", + "playwright": "^1.56.1", + "storybook": "^10.1.0-alpha.6", + "typescript": "~5.9.3", "typescript-eslint": "^8.34.1", - "vite": "^7.0.0", - "vitest": "^3.2.4" + "vite": "^7.1.7", + "vitest": "^4.0.7", + "vue-tsc": "^3.1.0" } } diff --git a/test-storybooks/yarn-pnp/src/App.css b/test-storybooks/yarn-pnp/src/App.css deleted file mode 100644 index b9d355df2a59..000000000000 --- a/test-storybooks/yarn-pnp/src/App.css +++ /dev/null @@ -1,42 +0,0 @@ -#root { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; -} -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } -} - -.card { - padding: 2em; -} - -.read-the-docs { - color: #888; -} diff --git a/test-storybooks/yarn-pnp/src/App.tsx b/test-storybooks/yarn-pnp/src/App.tsx deleted file mode 100644 index 3d7ded3ff624..000000000000 --- a/test-storybooks/yarn-pnp/src/App.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { useState } from 'react' -import reactLogo from './assets/react.svg' -import viteLogo from '/vite.svg' -import './App.css' - -function App() { - const [count, setCount] = useState(0) - - return ( - <> -
-

Vite + React

-
- -

- Edit src/App.tsx and save to test HMR -

-
-

- Click on the Vite and React logos to learn more -

- - ) -} - -export default App diff --git a/test-storybooks/yarn-pnp/src/App.vue b/test-storybooks/yarn-pnp/src/App.vue new file mode 100644 index 000000000000..58b0f21b1647 --- /dev/null +++ b/test-storybooks/yarn-pnp/src/App.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/test-storybooks/yarn-pnp/src/assets/react.svg b/test-storybooks/yarn-pnp/src/assets/react.svg deleted file mode 100644 index 6c87de9bb335..000000000000 --- a/test-storybooks/yarn-pnp/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/test-storybooks/yarn-pnp/src/assets/vue.svg b/test-storybooks/yarn-pnp/src/assets/vue.svg new file mode 100644 index 000000000000..770e9d333ee7 --- /dev/null +++ b/test-storybooks/yarn-pnp/src/assets/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test-storybooks/yarn-pnp/src/components/HelloWorld.vue b/test-storybooks/yarn-pnp/src/components/HelloWorld.vue new file mode 100644 index 000000000000..b58e52b965f6 --- /dev/null +++ b/test-storybooks/yarn-pnp/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/test-storybooks/yarn-pnp/src/main.ts b/test-storybooks/yarn-pnp/src/main.ts new file mode 100644 index 000000000000..2425c0f745be --- /dev/null +++ b/test-storybooks/yarn-pnp/src/main.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue' +import './style.css' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/test-storybooks/yarn-pnp/src/main.tsx b/test-storybooks/yarn-pnp/src/main.tsx deleted file mode 100644 index bef5202a32cb..000000000000 --- a/test-storybooks/yarn-pnp/src/main.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import './index.css' -import App from './App.tsx' - -createRoot(document.getElementById('root')!).render( - - - , -) diff --git a/test-storybooks/yarn-pnp/src/stories/Button.stories.ts b/test-storybooks/yarn-pnp/src/stories/Button.stories.ts index 0c3151f3089c..fafb4c8ff006 100644 --- a/test-storybooks/yarn-pnp/src/stories/Button.stories.ts +++ b/test-storybooks/yarn-pnp/src/stories/Button.stories.ts @@ -1,31 +1,33 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { fn } from 'storybook/test'; -import { Button } from './Button'; +import Button from './Button.vue'; -// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories const meta = { title: 'Example/Button', component: Button, - parameters: { - // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout - layout: 'centered', - }, - // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs tags: ['autodocs'], - // More on argTypes: https://storybook.js.org/docs/api/argtypes argTypes: { + size: { control: 'select', options: ['small', 'medium', 'large'] }, backgroundColor: { control: 'color' }, }, - // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args - args: { onClick: fn() }, + args: { + primary: false, + // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#story-args + onClick: fn(), + }, } satisfies Meta; export default meta; type Story = StoryObj; - -// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args +/* + *👇 Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/api/csf + * to learn how to use render functions. + */ export const Primary: Story = { args: { primary: true, @@ -35,20 +37,21 @@ export const Primary: Story = { export const Secondary: Story = { args: { + primary: false, label: 'Button', }, }; export const Large: Story = { args: { - size: 'large', label: 'Button', + size: 'large', }, }; export const Small: Story = { args: { - size: 'small', label: 'Button', + size: 'small', }, }; diff --git a/test-storybooks/yarn-pnp/src/stories/Button.tsx b/test-storybooks/yarn-pnp/src/stories/Button.tsx deleted file mode 100644 index f35dafdcb427..000000000000 --- a/test-storybooks/yarn-pnp/src/stories/Button.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react'; - -import './button.css'; - -export interface ButtonProps { - /** Is this the principal call to action on the page? */ - primary?: boolean; - /** What background color to use */ - backgroundColor?: string; - /** How large should the button be? */ - size?: 'small' | 'medium' | 'large'; - /** Button contents */ - label: string; - /** Optional click handler */ - onClick?: () => void; -} - -/** Primary UI component for user interaction */ -export const Button = ({ - primary = false, - size = 'medium', - backgroundColor, - label, - ...props -}: ButtonProps) => { - const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; - return ( - - ); -}; diff --git a/test-storybooks/yarn-pnp/src/stories/Button.vue b/test-storybooks/yarn-pnp/src/stories/Button.vue new file mode 100644 index 000000000000..338b97c658d4 --- /dev/null +++ b/test-storybooks/yarn-pnp/src/stories/Button.vue @@ -0,0 +1,50 @@ + + + diff --git a/test-storybooks/yarn-pnp/src/stories/Configure.mdx b/test-storybooks/yarn-pnp/src/stories/Configure.mdx index dca091c16b1a..34a34ea9e3e0 100644 --- a/test-storybooks/yarn-pnp/src/stories/Configure.mdx +++ b/test-storybooks/yarn-pnp/src/stories/Configure.mdx @@ -48,7 +48,7 @@ export const RightArrow = () => Add styling and CSS

Like with web applications, there are many ways to include CSS within Storybook. Learn more about setting up styling within Storybook.

Learn more @@ -60,7 +60,7 @@ export const RightArrow = () => Provide context and mocking

Often when a story doesn't render, it's because your component is expecting a specific environment or context (like a theme provider) to be available.

Learn more @@ -72,7 +72,7 @@ export const RightArrow = () => Learn more @@ -94,7 +94,7 @@ export const RightArrow = () => Auto-generate living, interactive reference documentation from your components and stories.

Learn more @@ -103,7 +103,7 @@ export const RightArrow = () => Publish to Chromatic

Publish your Storybook to review and collaborate with your entire team.

Learn more @@ -113,7 +113,7 @@ export const RightArrow = () => Embed your stories into Figma to cross-reference the design and live implementation in one place.

Learn more @@ -123,7 +123,7 @@ export const RightArrow = () => Use stories to test a component in all its variations, no matter how complex.

Learn more @@ -132,7 +132,7 @@ export const RightArrow = () => Accessibility

Automatically test your components for a11y issues as you develop.

Learn more @@ -141,7 +141,7 @@ export const RightArrow = () => Theming

Theme Storybook's UI to personalize it to your project.

Learn more diff --git a/test-storybooks/yarn-pnp/src/stories/Header.stories.ts b/test-storybooks/yarn-pnp/src/stories/Header.stories.ts index 36a3b8f9f2b1..47caa29a09e3 100644 --- a/test-storybooks/yarn-pnp/src/stories/Header.stories.ts +++ b/test-storybooks/yarn-pnp/src/stories/Header.stories.ts @@ -1,14 +1,23 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { fn } from 'storybook/test'; -import { Header } from './Header'; +import MyHeader from './Header.vue'; const meta = { + /* 👇 The title prop is optional. + * See https://storybook.js.org/docs/configure/#configure-story-loading + * to learn how to generate automatic titles + */ title: 'Example/Header', - component: Header, - // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs - tags: ['autodocs'], + component: MyHeader, + render: (args: any) => ({ + components: { MyHeader }, + setup() { + return { args }; + }, + template: '', + }), parameters: { // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout layout: 'fullscreen', @@ -18,7 +27,9 @@ const meta = { onLogout: fn(), onCreateAccount: fn(), }, -} satisfies Meta; + // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], +} satisfies Meta; export default meta; type Story = StoryObj; @@ -31,4 +42,8 @@ export const LoggedIn: Story = { }, }; -export const LoggedOut: Story = {}; +export const LoggedOut: Story = { + args: { + user: null, + }, +}; diff --git a/test-storybooks/yarn-pnp/src/stories/Header.tsx b/test-storybooks/yarn-pnp/src/stories/Header.tsx deleted file mode 100644 index 1bf981a4251f..000000000000 --- a/test-storybooks/yarn-pnp/src/stories/Header.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import React from 'react'; - -import { Button } from './Button'; -import './header.css'; - -type User = { - name: string; -}; - -export interface HeaderProps { - user?: User; - onLogin?: () => void; - onLogout?: () => void; - onCreateAccount?: () => void; -} - -export const Header = ({ user, onLogin, onLogout, onCreateAccount }: HeaderProps) => ( -
-
-
- - - - - - - -

Acme

-
-
- {user ? ( - <> - - Welcome, {user.name}! - -
-
-
-); diff --git a/test-storybooks/yarn-pnp/src/stories/Header.vue b/test-storybooks/yarn-pnp/src/stories/Header.vue new file mode 100644 index 000000000000..bade22d0979f --- /dev/null +++ b/test-storybooks/yarn-pnp/src/stories/Header.vue @@ -0,0 +1,53 @@ + + + diff --git a/test-storybooks/yarn-pnp/src/stories/Page.stories.ts b/test-storybooks/yarn-pnp/src/stories/Page.stories.ts index 7bbda250dec4..ec3d2488dd06 100644 --- a/test-storybooks/yarn-pnp/src/stories/Page.stories.ts +++ b/test-storybooks/yarn-pnp/src/stories/Page.stories.ts @@ -1,26 +1,30 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import type { Meta, StoryObj } from '@storybook/vue3-vite'; import { expect, userEvent, within } from 'storybook/test'; -import { Page } from './Page'; +import MyPage from './Page.vue'; const meta = { title: 'Example/Page', - component: Page, + component: MyPage, + render: () => ({ + components: { MyPage }, + template: '', + }), parameters: { // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout layout: 'fullscreen', }, -} satisfies Meta; + // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], +} satisfies Meta; export default meta; type Story = StoryObj; -export const LoggedOut: Story = {}; - // More on component testing: https://storybook.js.org/docs/writing-tests/interaction-testing export const LoggedIn: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement }: any) => { const canvas = within(canvasElement); const loginButton = canvas.getByRole('button', { name: /Log in/i }); await expect(loginButton).toBeInTheDocument(); @@ -31,3 +35,5 @@ export const LoggedIn: Story = { await expect(logoutButton).toBeInTheDocument(); }, }; + +export const LoggedOut: Story = {}; diff --git a/test-storybooks/yarn-pnp/src/stories/Page.tsx b/test-storybooks/yarn-pnp/src/stories/Page.tsx deleted file mode 100644 index e11748301390..000000000000 --- a/test-storybooks/yarn-pnp/src/stories/Page.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import React from 'react'; - -import { Header } from './Header'; -import './page.css'; - -type User = { - name: string; -}; - -export const Page: React.FC = () => { - const [user, setUser] = React.useState(); - - return ( -
-
setUser({ name: 'Jane Doe' })} - onLogout={() => setUser(undefined)} - onCreateAccount={() => setUser({ name: 'Jane Doe' })} - /> - -
-

Pages in Storybook

-

- We recommend building UIs with a{' '} - - component-driven - {' '} - process starting with atomic components and ending with pages. -

-

- Render pages with mock data. This makes it easy to build and review page states without - needing to navigate to them in your app. Here are some handy patterns for managing page - data in Storybook: -

-
    -
  • - Use a higher-level connected component. Storybook helps you compose such data from the - "args" of child component stories -
  • -
  • - Assemble data in the page component from your services. You can mock these services out - using Storybook. -
  • -
-

- Get a guided tutorial on component-driven development at{' '} - - Storybook tutorials - - . Read more in the{' '} - - docs - - . -

-
- Tip Adjust the width of the canvas with the{' '} - - - - - - Viewports addon in the toolbar -
-
-
- ); -}; diff --git a/test-storybooks/yarn-pnp/src/stories/Page.vue b/test-storybooks/yarn-pnp/src/stories/Page.vue new file mode 100644 index 000000000000..85701a3bdf00 --- /dev/null +++ b/test-storybooks/yarn-pnp/src/stories/Page.vue @@ -0,0 +1,73 @@ + + + diff --git a/test-storybooks/yarn-pnp/src/index.css b/test-storybooks/yarn-pnp/src/style.css similarity index 90% rename from test-storybooks/yarn-pnp/src/index.css rename to test-storybooks/yarn-pnp/src/style.css index 08a3ac9e1e5c..f6913154345d 100644 --- a/test-storybooks/yarn-pnp/src/index.css +++ b/test-storybooks/yarn-pnp/src/style.css @@ -54,6 +54,17 @@ button:focus-visible { outline: 4px auto -webkit-focus-ring-color; } +.card { + padding: 2em; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + @media (prefers-color-scheme: light) { :root { color: #213547; diff --git a/test-storybooks/yarn-pnp/src/vite-env.d.ts b/test-storybooks/yarn-pnp/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a006..000000000000 --- a/test-storybooks/yarn-pnp/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/test-storybooks/yarn-pnp/tsconfig.app.json b/test-storybooks/yarn-pnp/tsconfig.app.json index 227a6c6723b6..a2d3056b819b 100644 --- a/test-storybooks/yarn-pnp/tsconfig.app.json +++ b/test-storybooks/yarn-pnp/tsconfig.app.json @@ -6,6 +6,7 @@ "lib": ["ES2022", "DOM", "DOM.Iterable"], "module": "ESNext", "skipLibCheck": true, + "types": ["vite/client"], /* Bundler mode */ "moduleResolution": "bundler", @@ -13,7 +14,6 @@ "verbatimModuleSyntax": true, "moduleDetection": "force", "noEmit": true, - "jsx": "react-jsx", /* Linting */ "strict": true, @@ -23,5 +23,5 @@ "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true }, - "include": ["src"] + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] } diff --git a/test-storybooks/yarn-pnp/tsconfig.node.json b/test-storybooks/yarn-pnp/tsconfig.node.json index f85a39906e55..8a67f62f4cee 100644 --- a/test-storybooks/yarn-pnp/tsconfig.node.json +++ b/test-storybooks/yarn-pnp/tsconfig.node.json @@ -4,6 +4,7 @@ "target": "ES2023", "lib": ["ES2023"], "module": "ESNext", + "types": ["node"], "skipLibCheck": true, /* Bundler mode */ diff --git a/test-storybooks/yarn-pnp/vite.config.ts b/test-storybooks/yarn-pnp/vite.config.ts index 8b0f57b91aeb..28cb993f3fde 100644 --- a/test-storybooks/yarn-pnp/vite.config.ts +++ b/test-storybooks/yarn-pnp/vite.config.ts @@ -1,7 +1,46 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +/// +import { defineConfig } from "vite"; +import vue from "@vitejs/plugin-vue"; // https://vite.dev/config/ +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { storybookTest } from "@storybook/addon-vitest/vitest-plugin"; +import { playwright } from "@vitest/browser-playwright"; +const dirname = + typeof __dirname !== "undefined" + ? __dirname + : path.dirname(fileURLToPath(import.meta.url)); + +// More info at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon export default defineConfig({ - plugins: [react()], -}) + plugins: [vue()], + test: { + projects: [ + { + extends: true, + plugins: [ + // The plugin will run tests for the stories defined in your Storybook config + // See options at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon#storybooktest + storybookTest({ + configDir: path.join(dirname, ".storybook"), + }), + ], + test: { + name: "storybook", + browser: { + enabled: true, + headless: true, + provider: playwright({}), + instances: [ + { + browser: "chromium", + }, + ], + }, + setupFiles: [".storybook/vitest.setup.ts"], + }, + }, + ], + }, +}); diff --git a/test-storybooks/yarn-pnp/vitest.shims.d.ts b/test-storybooks/yarn-pnp/vitest.shims.d.ts index f923d47d483f..03b1801a60cb 100644 --- a/test-storybooks/yarn-pnp/vitest.shims.d.ts +++ b/test-storybooks/yarn-pnp/vitest.shims.d.ts @@ -1 +1 @@ -/// \ No newline at end of file +/// diff --git a/test-storybooks/yarn-pnp/vitest.workspace.ts b/test-storybooks/yarn-pnp/vitest.workspace.ts deleted file mode 100644 index 4b1fcc8dc232..000000000000 --- a/test-storybooks/yarn-pnp/vitest.workspace.ts +++ /dev/null @@ -1,32 +0,0 @@ -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; - -import { defineWorkspace } from 'vitest/config'; - -import { storybookTest } from '@storybook/addon-vitest/vitest-plugin'; - -const dirname = - typeof __dirname !== 'undefined' ? __dirname : path.dirname(fileURLToPath(import.meta.url)); - -// More info at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon -export default defineWorkspace([ - 'vite.config.ts', - { - extends: 'vite.config.ts', - plugins: [ - // The plugin will run tests for the stories defined in your Storybook config - // See options at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon#storybooktest - storybookTest({ configDir: path.join(dirname, '.storybook') }), - ], - test: { - name: 'storybook', - browser: { - enabled: true, - headless: true, - provider: 'playwright', - instances: [{ browser: 'chromium' }] - }, - setupFiles: ['.storybook/vitest.setup.ts'], - }, - }, -]); diff --git a/test-storybooks/yarn-pnp/yarn.lock b/test-storybooks/yarn-pnp/yarn.lock index e69de29bb2d1..8b137891791f 100644 --- a/test-storybooks/yarn-pnp/yarn.lock +++ b/test-storybooks/yarn-pnp/yarn.lock @@ -0,0 +1 @@ +