diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx
index aefc27f54cfd..abd21cab7079 100644
--- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx
+++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/nextjs';
import { getImageProps } from 'next/image';
diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx
index f5e83ef867f6..5478d835d89c 100644
--- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx
+++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx
@@ -1,6 +1,7 @@
+import type { Meta, StoryObj } from '@storybook/nextjs';
import { cookies, headers } from '@storybook/nextjs/headers.mock';
-import type { Meta, StoryObj } from '@storybook/react';
-import { expect, userEvent, within } from '@storybook/test';
+
+import { expect, userEvent, within } from 'storybook/test';
import NextHeader from './NextHeader';
diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Redirect.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/Redirect.stories.tsx
index 3c5980b79757..6cf56ede2f13 100644
--- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Redirect.stories.tsx
+++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/Redirect.stories.tsx
@@ -1,9 +1,9 @@
import React from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
-import { userEvent, within } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/nextjs';
import { redirect } from 'next/navigation';
+import { userEvent, within } from 'storybook/test';
let state = 'Bug! Not invalidated';
diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx
index f1a9ad762eed..4da326d7d98f 100644
--- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx
+++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx
@@ -1,10 +1,11 @@
import React from 'react';
+import type { Meta, StoryObj } from '@storybook/nextjs';
import { revalidatePath } from '@storybook/nextjs/cache.mock';
import { cookies } from '@storybook/nextjs/headers.mock';
import { getRouter, redirect } from '@storybook/nextjs/navigation.mock';
-import type { Meta, StoryObj } from '@storybook/react';
-import { expect, userEvent, waitFor, within } from '@storybook/test';
+
+import { expect, userEvent, waitFor, within } from 'storybook/test';
import { accessRoute, login, logout } from './server-actions';
diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx
index aefc27f54cfd..abd21cab7079 100644
--- a/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx
+++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/nextjs';
import { getImageProps } from 'next/image';
diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx
index f5e83ef867f6..5478d835d89c 100644
--- a/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx
+++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx
@@ -1,6 +1,7 @@
+import type { Meta, StoryObj } from '@storybook/nextjs';
import { cookies, headers } from '@storybook/nextjs/headers.mock';
-import type { Meta, StoryObj } from '@storybook/react';
-import { expect, userEvent, within } from '@storybook/test';
+
+import { expect, userEvent, within } from 'storybook/test';
import NextHeader from './NextHeader';
diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx
index 3c5980b79757..6cf56ede2f13 100644
--- a/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx
+++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx
@@ -1,9 +1,9 @@
import React from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
-import { userEvent, within } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/nextjs';
import { redirect } from 'next/navigation';
+import { userEvent, within } from 'storybook/test';
let state = 'Bug! Not invalidated';
diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/ServerActions.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/ServerActions.stories.tsx
index f1a9ad762eed..4da326d7d98f 100644
--- a/code/frameworks/nextjs/template/stories_nextjs-prerelease/ServerActions.stories.tsx
+++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/ServerActions.stories.tsx
@@ -1,10 +1,11 @@
import React from 'react';
+import type { Meta, StoryObj } from '@storybook/nextjs';
import { revalidatePath } from '@storybook/nextjs/cache.mock';
import { cookies } from '@storybook/nextjs/headers.mock';
import { getRouter, redirect } from '@storybook/nextjs/navigation.mock';
-import type { Meta, StoryObj } from '@storybook/react';
-import { expect, userEvent, waitFor, within } from '@storybook/test';
+
+import { expect, userEvent, waitFor, within } from 'storybook/test';
import { accessRoute, login, logout } from './server-actions';
diff --git a/code/frameworks/preact-vite/src/index.ts b/code/frameworks/preact-vite/src/index.ts
index fcb073fefcd6..6a07f64e6833 100644
--- a/code/frameworks/preact-vite/src/index.ts
+++ b/code/frameworks/preact-vite/src/index.ts
@@ -1 +1,2 @@
+export * from '@storybook/preact';
export * from './types';
diff --git a/code/frameworks/preact-webpack5/src/index.ts b/code/frameworks/preact-webpack5/src/index.ts
index fcb073fefcd6..6a07f64e6833 100644
--- a/code/frameworks/preact-webpack5/src/index.ts
+++ b/code/frameworks/preact-webpack5/src/index.ts
@@ -1 +1,2 @@
+export * from '@storybook/preact';
export * from './types';
diff --git a/code/frameworks/react-native-web-vite/src/index.ts b/code/frameworks/react-native-web-vite/src/index.ts
index baac63e5f100..274fe088be34 100644
--- a/code/frameworks/react-native-web-vite/src/index.ts
+++ b/code/frameworks/react-native-web-vite/src/index.ts
@@ -1,3 +1,4 @@
export type { FrameworkOptions, StorybookConfig } from './types';
export { __definePreview as definePreview } from '@storybook/react';
+export * from '@storybook/react';
diff --git a/code/frameworks/react-native-web-vite/template/cli/js/Button.stories.jsx b/code/frameworks/react-native-web-vite/template/cli/js/Button.stories.jsx
index b7136fd8ae67..3ea891e65ce3 100644
--- a/code/frameworks/react-native-web-vite/template/cli/js/Button.stories.jsx
+++ b/code/frameworks/react-native-web-vite/template/cli/js/Button.stories.jsx
@@ -1,6 +1,5 @@
-import { fn } from '@storybook/test';
-
import { View } from 'react-native';
+import { fn } from 'storybook/test';
import { Button } from './Button';
diff --git a/code/frameworks/react-native-web-vite/template/cli/js/Page.stories.jsx b/code/frameworks/react-native-web-vite/template/cli/js/Page.stories.jsx
index 249647fce862..bbf8729b8a31 100644
--- a/code/frameworks/react-native-web-vite/template/cli/js/Page.stories.jsx
+++ b/code/frameworks/react-native-web-vite/template/cli/js/Page.stories.jsx
@@ -1,4 +1,4 @@
-import { expect, userEvent, within } from '@storybook/test';
+import { expect, userEvent, within } from 'storybook/test';
import { Page } from './Page';
diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.stories.tsx
index 8e655fbfe266..3d532efa99b7 100644
--- a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.stories.tsx
+++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.stories.tsx
@@ -1,7 +1,7 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-native-web-vite';
import { View } from 'react-native';
+import { fn } from 'storybook/test';
import { Button } from './Button';
diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.stories.tsx
index 029f040b0396..b5a633e2e987 100644
--- a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.stories.tsx
+++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-native-web-vite';
import { Header } from './Header';
diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.stories.tsx
index 5a5db7ff2685..bb9b828da45e 100644
--- a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.stories.tsx
+++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.stories.tsx
@@ -1,5 +1,6 @@
-import type { Meta } from '@storybook/react';
-import { expect, userEvent, within } from '@storybook/test';
+import type { Meta } from '@storybook/react-native-web-vite';
+
+import { expect, userEvent, within } from 'storybook/test';
import { Page } from './Page';
diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json
index 5d3501d75dcc..c9ff913ecf15 100644
--- a/code/frameworks/react-vite/package.json
+++ b/code/frameworks/react-vite/package.json
@@ -56,6 +56,7 @@
},
"files": [
"dist/**/*",
+ "template/**/*",
"README.md",
"*.js",
"*.d.ts",
@@ -82,17 +83,11 @@
"vite": "^4.0.0"
},
"peerDependencies": {
- "@storybook/test": "workspace:*",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
"storybook": "workspace:^",
"vite": "^4.0.0 || ^5.0.0 || ^6.0.0"
},
- "peerDependenciesMeta": {
- "@storybook/test": {
- "optional": true
- }
- },
"engines": {
"node": ">=18.0.0"
},
diff --git a/code/frameworks/react-vite/src/index.ts b/code/frameworks/react-vite/src/index.ts
index f71bd648bf9c..cb9de933e712 100644
--- a/code/frameworks/react-vite/src/index.ts
+++ b/code/frameworks/react-vite/src/index.ts
@@ -1,3 +1,4 @@
+export * from '@storybook/react';
export { __definePreview as definePreview } from '@storybook/react';
export * from './types';
diff --git a/code/frameworks/react-vite/template/cli/.eslintrc.json b/code/frameworks/react-vite/template/cli/.eslintrc.json
new file mode 100644
index 000000000000..40ece4a0aa18
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/.eslintrc.json
@@ -0,0 +1,5 @@
+{
+ "rules": {
+ "import/extensions": "off"
+ }
+}
diff --git a/code/frameworks/react-vite/template/cli/js/Button.jsx b/code/frameworks/react-vite/template/cli/js/Button.jsx
new file mode 100644
index 000000000000..dabe38e0e82a
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/js/Button.jsx
@@ -0,0 +1,39 @@
+import React from 'react';
+
+import PropTypes from 'prop-types';
+
+import './button.css';
+
+/** Primary UI component for user interaction */
+export const Button = ({
+ primary = false,
+ backgroundColor = null,
+ size = 'medium',
+ label,
+ ...props
+}) => {
+ const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
+ return (
+
+ {label}
+
+ );
+};
+
+Button.propTypes = {
+ /** Is this the principal call to action on the page? */
+ primary: PropTypes.bool,
+ /** What background color to use */
+ backgroundColor: PropTypes.string,
+ /** How large should the button be? */
+ size: PropTypes.oneOf(['small', 'medium', 'large']),
+ /** Button contents */
+ label: PropTypes.string.isRequired,
+ /** Optional click handler */
+ onClick: PropTypes.func,
+};
diff --git a/code/frameworks/react-vite/template/cli/js/Button.stories.js b/code/frameworks/react-vite/template/cli/js/Button.stories.js
new file mode 100644
index 000000000000..1b56021e71d9
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/js/Button.stories.js
@@ -0,0 +1,49 @@
+import { fn } from 'storybook/test';
+
+import { Button } from './Button';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
+export default {
+ 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
+ tags: ['autodocs'],
+ // More on argTypes: https://storybook.js.org/docs/api/argtypes
+ argTypes: {
+ 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() },
+};
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Primary = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/react-vite/template/cli/js/Header.jsx b/code/frameworks/react-vite/template/cli/js/Header.jsx
new file mode 100644
index 000000000000..94a691e1dd76
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/js/Header.jsx
@@ -0,0 +1,56 @@
+import React from 'react';
+
+import PropTypes from 'prop-types';
+
+import { Button } from './Button';
+import './header.css';
+
+export const Header = ({ user = null, onLogin, onLogout, onCreateAccount }) => (
+
+);
+
+Header.propTypes = {
+ user: PropTypes.shape({
+ name: PropTypes.string.isRequired,
+ }),
+ onLogin: PropTypes.func.isRequired,
+ onLogout: PropTypes.func.isRequired,
+ onCreateAccount: PropTypes.func.isRequired,
+};
diff --git a/code/frameworks/react-vite/template/cli/js/Header.stories.js b/code/frameworks/react-vite/template/cli/js/Header.stories.js
new file mode 100644
index 000000000000..6d88e1007498
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/js/Header.stories.js
@@ -0,0 +1,29 @@
+import { fn } from 'storybook/test';
+
+import { Header } from './Header';
+
+export default {
+ title: 'Example/Header',
+ component: Header,
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+ args: {
+ onLogin: fn(),
+ onLogout: fn(),
+ onCreateAccount: fn(),
+ },
+};
+
+export const LoggedIn = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut = {};
diff --git a/code/frameworks/react-vite/template/cli/js/Page.jsx b/code/frameworks/react-vite/template/cli/js/Page.jsx
new file mode 100644
index 000000000000..c421401138ed
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/js/Page.jsx
@@ -0,0 +1,69 @@
+import React from 'react';
+
+import { Header } from './Header';
+import './page.css';
+
+export const Page = () => {
+ 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/code/frameworks/react-vite/template/cli/js/Page.stories.js b/code/frameworks/react-vite/template/cli/js/Page.stories.js
new file mode 100644
index 000000000000..7b9906a73514
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/js/Page.stories.js
@@ -0,0 +1,28 @@
+import { expect, userEvent, within } from '@storybook/test';
+
+import { Page } from './Page';
+
+export default {
+ title: 'Example/Page',
+ component: Page,
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+};
+
+export const LoggedOut = {};
+
+// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing
+export const LoggedIn = {
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await expect(loginButton).not.toBeInTheDocument();
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ },
+};
diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/react-vite/template/cli/ts-4-9/Button.stories.ts
new file mode 100644
index 000000000000..0c3151f3089c
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/ts-4-9/Button.stories.ts
@@ -0,0 +1,54 @@
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
+
+import { Button } from './Button';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
+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
+ tags: ['autodocs'],
+ // More on argTypes: https://storybook.js.org/docs/api/argtypes
+ argTypes: {
+ 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() },
+} satisfies Meta
;
+
+export default meta;
+type Story = StoryObj;
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Primary: Story = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary: Story = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large: Story = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small: Story = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Button.tsx b/code/frameworks/react-vite/template/cli/ts-4-9/Button.tsx
new file mode 100644
index 000000000000..f35dafdcb427
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/ts-4-9/Button.tsx
@@ -0,0 +1,37 @@
+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 (
+
+ {label}
+
+ );
+};
diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/react-vite/template/cli/ts-4-9/Header.stories.ts
new file mode 100644
index 000000000000..36a3b8f9f2b1
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/ts-4-9/Header.stories.ts
@@ -0,0 +1,34 @@
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
+
+import { Header } from './Header';
+
+const meta = {
+ title: 'Example/Header',
+ component: Header,
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+ args: {
+ onLogin: fn(),
+ onLogout: fn(),
+ onCreateAccount: fn(),
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LoggedIn: Story = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut: Story = {};
diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Header.tsx b/code/frameworks/react-vite/template/cli/ts-4-9/Header.tsx
new file mode 100644
index 000000000000..1bf981a4251f
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/ts-4-9/Header.tsx
@@ -0,0 +1,56 @@
+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) => (
+
+);
diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/react-vite/template/cli/ts-4-9/Page.stories.ts
new file mode 100644
index 000000000000..9ca0d882bce3
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/ts-4-9/Page.stories.ts
@@ -0,0 +1,33 @@
+import { expect, userEvent, within } from '@storybook/test';
+
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { Page } from './Page';
+
+const meta = {
+ title: 'Example/Page',
+ component: Page,
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LoggedOut: Story = {};
+
+// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing
+export const LoggedIn: Story = {
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await expect(loginButton).not.toBeInTheDocument();
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ },
+};
diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Page.tsx b/code/frameworks/react-vite/template/cli/ts-4-9/Page.tsx
new file mode 100644
index 000000000000..e11748301390
--- /dev/null
+++ b/code/frameworks/react-vite/template/cli/ts-4-9/Page.tsx
@@ -0,0 +1,73 @@
+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/code/frameworks/react-webpack5/src/index.ts b/code/frameworks/react-webpack5/src/index.ts
index 9dce8313193a..cf6d4c05ce5a 100644
--- a/code/frameworks/react-webpack5/src/index.ts
+++ b/code/frameworks/react-webpack5/src/index.ts
@@ -1,2 +1,3 @@
+export * from '@storybook/react';
export * from './types';
export { __definePreview as definePreview } from '@storybook/react';
diff --git a/code/frameworks/server-webpack5/src/index.ts b/code/frameworks/server-webpack5/src/index.ts
index fcb073fefcd6..098058fdbc0e 100644
--- a/code/frameworks/server-webpack5/src/index.ts
+++ b/code/frameworks/server-webpack5/src/index.ts
@@ -1 +1,2 @@
+export * from '@storybook/server';
export * from './types';
diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json
index d3e292d40514..a29ea282b3a9 100644
--- a/code/frameworks/svelte-vite/package.json
+++ b/code/frameworks/svelte-vite/package.json
@@ -43,6 +43,7 @@
"types": "dist/index.d.ts",
"files": [
"dist/**/*",
+ "template/**/*",
"README.md",
"*.js",
"*.d.ts",
@@ -57,7 +58,7 @@
"@storybook/svelte": "workspace:*",
"magic-string": "^0.30.0",
"svelte-preprocess": "^5.1.1",
- "svelte2tsx": "^0.7.13",
+ "svelte2tsx": "^0.7.35",
"sveltedoc-parser": "^4.2.1",
"ts-dedent": "^2.2.0",
"typescript": "^4.9.4 || ^5.0.0"
diff --git a/code/frameworks/svelte-vite/src/index.ts b/code/frameworks/svelte-vite/src/index.ts
index fcb073fefcd6..07de4359ae11 100644
--- a/code/frameworks/svelte-vite/src/index.ts
+++ b/code/frameworks/svelte-vite/src/index.ts
@@ -1 +1,2 @@
+export * from '@storybook/svelte';
export * from './types';
diff --git a/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts b/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts
index eff343fbfe0b..01905776d96e 100644
--- a/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts
+++ b/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts
@@ -1,6 +1,6 @@
import path from 'node:path';
-import svelte2tsx from 'svelte2tsx';
+import svelte2tsx, { internalHelpers } from 'svelte2tsx';
import { VERSION } from 'svelte/compiler';
import ts from 'typescript';
@@ -411,7 +411,9 @@ export function generateDocgen(targetFileName: string, cache: DocgenCache): Docg
// Get render function generated by svelte2tsx
const renderFunction = sourceFile.statements.find((statement) => {
- return ts.isFunctionDeclaration(statement) && statement.name?.text === 'render';
+ return (
+ ts.isFunctionDeclaration(statement) && statement.name?.text === internalHelpers.renderName
+ );
}) as ts.FunctionDeclaration | undefined;
if (renderFunction === undefined) {
return {
diff --git a/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts b/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts
index c1647653933f..062e7f683277 100644
--- a/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts
+++ b/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts
@@ -146,7 +146,7 @@ export async function svelteDocgen(svelteOptions: Record = {}): Pro
return {
name: 'storybook:svelte-docgen-plugin',
async transform(src: string, id: string) {
- if (!filter(id)) {
+ if (id.startsWith('\0') || !filter(id)) {
return undefined;
}
@@ -189,7 +189,13 @@ export async function svelteDocgen(svelteOptions: Record = {}): Pro
let docOptions;
if (docPreprocessOptions) {
- const rawSource = readFileSync(resource).toString();
+ let rawSource;
+ try {
+ rawSource = readFileSync(resource).toString();
+ } catch (_) {
+ // ignore/skip modules that can't be loaded, possibly virtual module
+ return undefined;
+ }
const { code: fileContent } = await preprocess(rawSource, docPreprocessOptions, {
filename: resource,
});
diff --git a/code/frameworks/svelte-vite/template/cli/js/Button.stories.js b/code/frameworks/svelte-vite/template/cli/js/Button.stories.js
new file mode 100644
index 000000000000..c5c88776d6b5
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/js/Button.stories.js
@@ -0,0 +1,43 @@
+import Button from './Button.svelte';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+export default {
+ title: 'Example/Button',
+ component: Button,
+ tags: ['autodocs'],
+ argTypes: {
+ backgroundColor: { control: 'color' },
+ size: {
+ control: { type: 'select' },
+ options: ['small', 'medium', 'large'],
+ },
+ },
+};
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Primary = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/svelte-vite/template/cli/js/Button.svelte b/code/frameworks/svelte-vite/template/cli/js/Button.svelte
new file mode 100644
index 000000000000..a2a78d9d0d6f
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/js/Button.svelte
@@ -0,0 +1,36 @@
+
+
+
+ {label}
+
diff --git a/code/frameworks/svelte-vite/template/cli/js/Header.stories.js b/code/frameworks/svelte-vite/template/cli/js/Header.stories.js
new file mode 100644
index 000000000000..e2856c0e035c
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/js/Header.stories.js
@@ -0,0 +1,22 @@
+import Header from './Header.svelte';
+
+export default {
+ title: 'Example/Header',
+ component: Header,
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+};
+
+export const LoggedIn = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut = {};
diff --git a/code/frameworks/svelte-vite/template/cli/js/Header.svelte b/code/frameworks/svelte-vite/template/cli/js/Header.svelte
new file mode 100644
index 000000000000..a9c08f75db7d
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/js/Header.svelte
@@ -0,0 +1,52 @@
+
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/js/Page.stories.js b/code/frameworks/svelte-vite/template/cli/js/Page.stories.js
new file mode 100644
index 000000000000..5ce7b3dac56f
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/js/Page.stories.js
@@ -0,0 +1,28 @@
+import { expect, userEvent, waitFor, within } from '@storybook/test';
+
+import Page from './Page.svelte';
+
+export default {
+ title: 'Example/Page',
+ component: Page,
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+};
+
+export const LoggedOut = {};
+
+// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing
+export const LoggedIn = {
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await waitFor(() => expect(loginButton).not.toBeInTheDocument());
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ },
+};
diff --git a/code/frameworks/svelte-vite/template/cli/js/Page.svelte b/code/frameworks/svelte-vite/template/cli/js/Page.svelte
new file mode 100644
index 000000000000..acc473c2518f
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/js/Page.svelte
@@ -0,0 +1,70 @@
+
+
+
+ (user = { name: 'Jane Doe' })}
+ on:logout={() => (user = null)}
+ on:createAccount={() => (user = { 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/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.stories.svelte
new file mode 100644
index 000000000000..e6fb72dac174
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.stories.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.svelte
new file mode 100644
index 000000000000..b2b820ea4971
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.svelte
@@ -0,0 +1,26 @@
+
+
+
+ {label}
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.stories.svelte
new file mode 100644
index 000000000000..23175a8203e5
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.stories.svelte
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.svelte
new file mode 100644
index 000000000000..dba3b7880f49
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.svelte
@@ -0,0 +1,47 @@
+
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.stories.svelte
new file mode 100644
index 000000000000..2f4fd9e890a5
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.stories.svelte
@@ -0,0 +1,30 @@
+
+
+ {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await waitFor(() => expect(loginButton).not.toBeInTheDocument());
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ }}
+ />
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.svelte
new file mode 100644
index 000000000000..92a95c00c5c5
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.svelte
@@ -0,0 +1,70 @@
+
+
+
+ (user = { name: 'Jane Doe' })}
+ onLogout={() => (user = null)}
+ onCreateAccount={() => (user = { 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/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.stories.svelte
new file mode 100644
index 000000000000..e6fb72dac174
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.stories.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.svelte
new file mode 100644
index 000000000000..b31f5bffe4a5
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.svelte
@@ -0,0 +1,29 @@
+
+
+
+ {label}
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.stories.svelte
new file mode 100644
index 000000000000..23175a8203e5
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.stories.svelte
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.svelte
new file mode 100644
index 000000000000..14e890c79e98
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.svelte
@@ -0,0 +1,45 @@
+
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.stories.svelte
new file mode 100644
index 000000000000..f782871a1158
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.stories.svelte
@@ -0,0 +1,30 @@
+
+
+ {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await waitFor(() => expect(loginButton).not.toBeInTheDocument());
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ }}
+/>
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.svelte
new file mode 100644
index 000000000000..c4c069a5a50b
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.svelte
@@ -0,0 +1,70 @@
+
+
+
+ (user = { name: 'Jane Doe' })}
+ onLogout={() => (user = undefined)}
+ onCreateAccount={() => (user = { 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/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.stories.svelte
new file mode 100644
index 000000000000..e6fb72dac174
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.stories.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.svelte
new file mode 100644
index 000000000000..b31f5bffe4a5
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.svelte
@@ -0,0 +1,29 @@
+
+
+
+ {label}
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.stories.svelte
new file mode 100644
index 000000000000..23175a8203e5
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.stories.svelte
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.svelte
new file mode 100644
index 000000000000..14e890c79e98
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.svelte
@@ -0,0 +1,45 @@
+
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.stories.svelte
new file mode 100644
index 000000000000..f782871a1158
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.stories.svelte
@@ -0,0 +1,30 @@
+
+
+ {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await waitFor(() => expect(loginButton).not.toBeInTheDocument());
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ }}
+/>
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.svelte
new file mode 100644
index 000000000000..c4c069a5a50b
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.svelte
@@ -0,0 +1,70 @@
+
+
+
+ (user = { name: 'Jane Doe' })}
+ onLogout={() => (user = undefined)}
+ onCreateAccount={() => (user = { 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/code/frameworks/svelte-vite/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/svelte-vite/template/cli/ts-4-9/Button.stories.ts
new file mode 100644
index 000000000000..bcc54cde4d55
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/ts-4-9/Button.stories.ts
@@ -0,0 +1,48 @@
+import type { Meta, StoryObj } from '@storybook/svelte-vite';
+
+import Button from './Button.svelte';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+const meta = {
+ title: 'Example/Button',
+ component: Button,
+ tags: ['autodocs'],
+ argTypes: {
+ backgroundColor: { control: 'color' },
+ size: {
+ control: { type: 'select' },
+ options: ['small', 'medium', 'large'],
+ },
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Primary: Story = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary: Story = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large: Story = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small: Story = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/svelte-vite/template/cli/ts-4-9/Button.svelte b/code/frameworks/svelte-vite/template/cli/ts-4-9/Button.svelte
new file mode 100644
index 000000000000..f590a0aff55e
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/ts-4-9/Button.svelte
@@ -0,0 +1,34 @@
+
+
+
+ {label}
+
diff --git a/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.stories.ts
new file mode 100644
index 000000000000..22e301266dbf
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/svelte-vite';
+
+import Header from './Header.svelte';
+
+const meta = {
+ title: 'Example/Header',
+ component: Header,
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LoggedIn: Story = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut: Story = {};
diff --git a/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.svelte b/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.svelte
new file mode 100644
index 000000000000..cb6f82d5e666
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.svelte
@@ -0,0 +1,52 @@
+
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.stories.ts
new file mode 100644
index 000000000000..d6b261fb5864
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.stories.ts
@@ -0,0 +1,33 @@
+import { expect, userEvent, waitFor, within } from '@storybook/test';
+
+import type { Meta, StoryObj } from '@storybook/svelte-vite';
+
+import Page from './Page.svelte';
+
+const meta = {
+ title: 'Example/Page',
+ component: Page,
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LoggedOut: Story = {};
+
+// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing
+export const LoggedIn: Story = {
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await waitFor(() => expect(loginButton).not.toBeInTheDocument());
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ },
+};
diff --git a/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.svelte b/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.svelte
new file mode 100644
index 000000000000..94cdb07ecd39
--- /dev/null
+++ b/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.svelte
@@ -0,0 +1,70 @@
+
+
+
+ (user = { name: 'Jane Doe' })}
+ on:logout={() => (user = null)}
+ on:createAccount={() => (user = { 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/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json
index 7ac7af6decf2..55f2f14aa283 100644
--- a/code/frameworks/svelte-webpack5/package.json
+++ b/code/frameworks/svelte-webpack5/package.json
@@ -43,6 +43,7 @@
"types": "dist/index.d.ts",
"files": [
"dist/**/*",
+ "templates/**/*",
"README.md",
"*.js",
"*.d.ts",
diff --git a/code/frameworks/svelte-webpack5/src/index.ts b/code/frameworks/svelte-webpack5/src/index.ts
index fcb073fefcd6..07de4359ae11 100644
--- a/code/frameworks/svelte-webpack5/src/index.ts
+++ b/code/frameworks/svelte-webpack5/src/index.ts
@@ -1 +1,2 @@
+export * from '@storybook/svelte';
export * from './types';
diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json
index d3c602c9a1a5..8b972dc17a0c 100644
--- a/code/frameworks/sveltekit/package.json
+++ b/code/frameworks/sveltekit/package.json
@@ -54,6 +54,7 @@
"types": "dist/index.d.ts",
"files": [
"dist/**/*",
+ "template/**/*",
"README.md",
"*.js",
"*.d.ts",
diff --git a/code/frameworks/sveltekit/src/index.ts b/code/frameworks/sveltekit/src/index.ts
index a904f93ec89d..ee64168c3b83 100644
--- a/code/frameworks/sveltekit/src/index.ts
+++ b/code/frameworks/sveltekit/src/index.ts
@@ -1,2 +1,4 @@
+export * from '@storybook/svelte';
export * from './types';
+// @ts-expect-error (double exports)
export * from './portable-stories';
diff --git a/code/frameworks/sveltekit/template/cli/js/Button.stories.js b/code/frameworks/sveltekit/template/cli/js/Button.stories.js
new file mode 100644
index 000000000000..c5c88776d6b5
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/js/Button.stories.js
@@ -0,0 +1,43 @@
+import Button from './Button.svelte';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+export default {
+ title: 'Example/Button',
+ component: Button,
+ tags: ['autodocs'],
+ argTypes: {
+ backgroundColor: { control: 'color' },
+ size: {
+ control: { type: 'select' },
+ options: ['small', 'medium', 'large'],
+ },
+ },
+};
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Primary = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/sveltekit/template/cli/js/Button.svelte b/code/frameworks/sveltekit/template/cli/js/Button.svelte
new file mode 100644
index 000000000000..a2a78d9d0d6f
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/js/Button.svelte
@@ -0,0 +1,36 @@
+
+
+
+ {label}
+
diff --git a/code/frameworks/sveltekit/template/cli/js/Header.stories.js b/code/frameworks/sveltekit/template/cli/js/Header.stories.js
new file mode 100644
index 000000000000..e2856c0e035c
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/js/Header.stories.js
@@ -0,0 +1,22 @@
+import Header from './Header.svelte';
+
+export default {
+ title: 'Example/Header',
+ component: Header,
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+};
+
+export const LoggedIn = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut = {};
diff --git a/code/frameworks/sveltekit/template/cli/js/Header.svelte b/code/frameworks/sveltekit/template/cli/js/Header.svelte
new file mode 100644
index 000000000000..a9c08f75db7d
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/js/Header.svelte
@@ -0,0 +1,52 @@
+
+
+
diff --git a/code/frameworks/sveltekit/template/cli/js/Page.stories.js b/code/frameworks/sveltekit/template/cli/js/Page.stories.js
new file mode 100644
index 000000000000..5ce7b3dac56f
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/js/Page.stories.js
@@ -0,0 +1,28 @@
+import { expect, userEvent, waitFor, within } from '@storybook/test';
+
+import Page from './Page.svelte';
+
+export default {
+ title: 'Example/Page',
+ component: Page,
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+};
+
+export const LoggedOut = {};
+
+// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing
+export const LoggedIn = {
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await waitFor(() => expect(loginButton).not.toBeInTheDocument());
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ },
+};
diff --git a/code/frameworks/sveltekit/template/cli/js/Page.svelte b/code/frameworks/sveltekit/template/cli/js/Page.svelte
new file mode 100644
index 000000000000..acc473c2518f
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/js/Page.svelte
@@ -0,0 +1,70 @@
+
+
+
+ (user = { name: 'Jane Doe' })}
+ on:logout={() => (user = null)}
+ on:createAccount={() => (user = { 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/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.stories.svelte
new file mode 100644
index 000000000000..e6fb72dac174
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.stories.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.svelte
new file mode 100644
index 000000000000..b2b820ea4971
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.svelte
@@ -0,0 +1,26 @@
+
+
+
+ {label}
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.stories.svelte
new file mode 100644
index 000000000000..23175a8203e5
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.stories.svelte
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.svelte
new file mode 100644
index 000000000000..dba3b7880f49
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.svelte
@@ -0,0 +1,47 @@
+
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.stories.svelte
new file mode 100644
index 000000000000..2f4fd9e890a5
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.stories.svelte
@@ -0,0 +1,30 @@
+
+
+ {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await waitFor(() => expect(loginButton).not.toBeInTheDocument());
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ }}
+ />
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.svelte
new file mode 100644
index 000000000000..92a95c00c5c5
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.svelte
@@ -0,0 +1,70 @@
+
+
+
+ (user = { name: 'Jane Doe' })}
+ onLogout={() => (user = null)}
+ onCreateAccount={() => (user = { 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/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.stories.svelte
new file mode 100644
index 000000000000..e6fb72dac174
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.stories.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.svelte
new file mode 100644
index 000000000000..b31f5bffe4a5
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.svelte
@@ -0,0 +1,29 @@
+
+
+
+ {label}
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.stories.svelte
new file mode 100644
index 000000000000..23175a8203e5
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.stories.svelte
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.svelte
new file mode 100644
index 000000000000..14e890c79e98
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.svelte
@@ -0,0 +1,45 @@
+
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.stories.svelte
new file mode 100644
index 000000000000..f782871a1158
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.stories.svelte
@@ -0,0 +1,30 @@
+
+
+ {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await waitFor(() => expect(loginButton).not.toBeInTheDocument());
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ }}
+/>
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.svelte
new file mode 100644
index 000000000000..c4c069a5a50b
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.svelte
@@ -0,0 +1,70 @@
+
+
+
+ (user = { name: 'Jane Doe' })}
+ onLogout={() => (user = undefined)}
+ onCreateAccount={() => (user = { 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/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.stories.svelte
new file mode 100644
index 000000000000..e6fb72dac174
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.stories.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.svelte
new file mode 100644
index 000000000000..b31f5bffe4a5
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.svelte
@@ -0,0 +1,29 @@
+
+
+
+ {label}
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.stories.svelte
new file mode 100644
index 000000000000..23175a8203e5
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.stories.svelte
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.svelte
new file mode 100644
index 000000000000..14e890c79e98
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.svelte
@@ -0,0 +1,45 @@
+
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.stories.svelte
new file mode 100644
index 000000000000..f782871a1158
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.stories.svelte
@@ -0,0 +1,30 @@
+
+
+ {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await waitFor(() => expect(loginButton).not.toBeInTheDocument());
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ }}
+/>
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.svelte
new file mode 100644
index 000000000000..c4c069a5a50b
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.svelte
@@ -0,0 +1,70 @@
+
+
+
+ (user = { name: 'Jane Doe' })}
+ onLogout={() => (user = undefined)}
+ onCreateAccount={() => (user = { 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/code/frameworks/sveltekit/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/sveltekit/template/cli/ts-4-9/Button.stories.ts
new file mode 100644
index 000000000000..1b8ab10d8b7a
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/ts-4-9/Button.stories.ts
@@ -0,0 +1,48 @@
+import type { Meta, StoryObj } from '@storybook/sveltekit';
+
+import Button from './Button.svelte';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+const meta = {
+ title: 'Example/Button',
+ component: Button,
+ tags: ['autodocs'],
+ argTypes: {
+ backgroundColor: { control: 'color' },
+ size: {
+ control: { type: 'select' },
+ options: ['small', 'medium', 'large'],
+ },
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Primary: Story = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary: Story = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large: Story = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small: Story = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/sveltekit/template/cli/ts-4-9/Button.svelte b/code/frameworks/sveltekit/template/cli/ts-4-9/Button.svelte
new file mode 100644
index 000000000000..f590a0aff55e
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/ts-4-9/Button.svelte
@@ -0,0 +1,34 @@
+
+
+
+ {label}
+
diff --git a/code/frameworks/sveltekit/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/sveltekit/template/cli/ts-4-9/Header.stories.ts
new file mode 100644
index 000000000000..8f3588a55c1e
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/ts-4-9/Header.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/sveltekit';
+
+import Header from './Header.svelte';
+
+const meta = {
+ title: 'Example/Header',
+ component: Header,
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LoggedIn: Story = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut: Story = {};
diff --git a/code/frameworks/sveltekit/template/cli/ts-4-9/Header.svelte b/code/frameworks/sveltekit/template/cli/ts-4-9/Header.svelte
new file mode 100644
index 000000000000..cb6f82d5e666
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/ts-4-9/Header.svelte
@@ -0,0 +1,52 @@
+
+
+
diff --git a/code/frameworks/sveltekit/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/sveltekit/template/cli/ts-4-9/Page.stories.ts
new file mode 100644
index 000000000000..0465cf531223
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/ts-4-9/Page.stories.ts
@@ -0,0 +1,32 @@
+import type { Meta, StoryObj } from '@storybook/sveltekit';
+import { expect, userEvent, waitFor, within } from '@storybook/test';
+
+import Page from './Page.svelte';
+
+const meta = {
+ title: 'Example/Page',
+ component: Page,
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LoggedOut: Story = {};
+
+// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing
+export const LoggedIn: Story = {
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await waitFor(() => expect(loginButton).not.toBeInTheDocument());
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ },
+};
diff --git a/code/frameworks/sveltekit/template/cli/ts-4-9/Page.svelte b/code/frameworks/sveltekit/template/cli/ts-4-9/Page.svelte
new file mode 100644
index 000000000000..94cdb07ecd39
--- /dev/null
+++ b/code/frameworks/sveltekit/template/cli/ts-4-9/Page.svelte
@@ -0,0 +1,70 @@
+
+
+
+ (user = { name: 'Jane Doe' })}
+ on:logout={() => (user = null)}
+ on:createAccount={() => (user = { 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/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js
index baff059fa212..a60865e1d172 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Forms from './Forms.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js
index 9f7033e36a3f..e5517ce62f88 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Hrefs from './Hrefs.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js
index e102fce96438..cde66fd4f5a0 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Navigation from './Navigation.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/environment.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/environment.stories.js
index fb4c85d99264..47f2f3a4424d 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/environment.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/environment.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Environment from './Environment.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/forms.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/forms.stories.js
index 7659291df4f8..6a020c8e124c 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/forms.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/forms.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, userEvent, within } from '@storybook/test';
+import { expect, fn, userEvent, within } from 'storybook/test';
import Forms from './Forms.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/hrefs.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/hrefs.stories.js
index 9f7033e36a3f..e5517ce62f88 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/hrefs.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/hrefs.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Hrefs from './Hrefs.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/navigation.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/navigation.stories.js
index e102fce96438..cde66fd4f5a0 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/navigation.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/navigation.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Navigation from './Navigation.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/paths.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/paths.stories.js
index 4ef5ddbcb54b..1c6d5f362c59 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/paths.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/paths.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Paths from './Paths.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/environment.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/environment.stories.js
index fb4c85d99264..47f2f3a4424d 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/environment.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/environment.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Environment from './Environment.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/forms.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/forms.stories.js
index baff059fa212..a60865e1d172 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/forms.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/forms.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Forms from './Forms.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/hrefs.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/hrefs.stories.js
index 9f7033e36a3f..e5517ce62f88 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/hrefs.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/hrefs.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Hrefs from './Hrefs.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/navigation.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/navigation.stories.js
index e102fce96438..cde66fd4f5a0 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/navigation.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/navigation.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Navigation from './Navigation.svelte';
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/paths.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/paths.stories.js
index 4ef5ddbcb54b..1c6d5f362c59 100644
--- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/paths.stories.js
+++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/paths.stories.js
@@ -1,4 +1,4 @@
-import { expect, fn, within } from '@storybook/test';
+import { expect, fn, within } from 'storybook/test';
import Paths from './Paths.svelte';
diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json
index 49e0cc2aa711..dbdb637ea2d2 100644
--- a/code/frameworks/vue3-vite/package.json
+++ b/code/frameworks/vue3-vite/package.json
@@ -48,6 +48,7 @@
"types": "dist/index.d.ts",
"files": [
"dist/**/*",
+ "template/**/*",
"README.md",
"*.js",
"*.d.ts",
diff --git a/code/frameworks/vue3-vite/src/index.ts b/code/frameworks/vue3-vite/src/index.ts
index fcb073fefcd6..034adb8b02a6 100644
--- a/code/frameworks/vue3-vite/src/index.ts
+++ b/code/frameworks/vue3-vite/src/index.ts
@@ -1 +1,2 @@
+export * from '@storybook/vue3';
export * from './types';
diff --git a/code/frameworks/vue3-vite/template/cli/js/Button.stories.js b/code/frameworks/vue3-vite/template/cli/js/Button.stories.js
new file mode 100644
index 000000000000..2bd009f38165
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/js/Button.stories.js
@@ -0,0 +1,44 @@
+import { fn } from 'storybook/test';
+
+import MyButton from './Button.vue';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+export default {
+ title: 'Example/Button',
+ component: MyButton,
+ tags: ['autodocs'],
+ argTypes: {
+ size: { control: { type: '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() },
+};
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Primary = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/vue3-vite/template/cli/js/Button.vue b/code/frameworks/vue3-vite/template/cli/js/Button.vue
new file mode 100644
index 000000000000..a831ddf4991b
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/js/Button.vue
@@ -0,0 +1,52 @@
+
+ {{ label }}
+
+
+
diff --git a/code/frameworks/vue3-vite/template/cli/js/Header.stories.js b/code/frameworks/vue3-vite/template/cli/js/Header.stories.js
new file mode 100644
index 000000000000..ca1b5e65bf00
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/js/Header.stories.js
@@ -0,0 +1,48 @@
+import { fn } from 'storybook/test';
+
+import MyHeader from './Header.vue';
+
+export default {
+ title: 'Example/Header',
+ component: MyHeader,
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ render: (args) => ({
+ // Components used in your story `template` are defined in the `components` object
+ components: {
+ MyHeader,
+ },
+ // The story's `args` need to be mapped into the template through the `setup()` method
+ setup() {
+ // Story args can be spread into the returned object
+ return {
+ ...args,
+ };
+ },
+ // Then, the spread values can be accessed directly in the template
+ template: ' ',
+ }),
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+ args: {
+ onLogin: fn(),
+ onLogout: fn(),
+ onCreateAccount: fn(),
+ },
+};
+
+export const LoggedIn = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut = {
+ args: {
+ user: null,
+ },
+};
diff --git a/code/frameworks/vue3-vite/template/cli/js/Header.vue b/code/frameworks/vue3-vite/template/cli/js/Header.vue
new file mode 100644
index 000000000000..16d7740d96c4
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/js/Header.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
diff --git a/code/frameworks/vue3-vite/template/cli/js/Page.stories.js b/code/frameworks/vue3-vite/template/cli/js/Page.stories.js
new file mode 100644
index 000000000000..f03db3c7f07f
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/js/Page.stories.js
@@ -0,0 +1,34 @@
+import { expect, userEvent, within } from '@storybook/test';
+
+import MyPage from './Page.vue';
+
+export default {
+ title: 'Example/Page',
+ component: MyPage,
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+};
+
+export const LoggedOut = {};
+
+// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing
+export const LoggedIn = {
+ render: () => ({
+ components: {
+ MyPage,
+ },
+ template: ' ',
+ }),
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await expect(loginButton).not.toBeInTheDocument();
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ },
+};
diff --git a/code/frameworks/vue3-vite/template/cli/js/Page.vue b/code/frameworks/vue3-vite/template/cli/js/Page.vue
new file mode 100644
index 000000000000..245401b72c4d
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/js/Page.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+ 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/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.stories.ts
new file mode 100644
index 000000000000..c9cf6edbe7de
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.stories.ts
@@ -0,0 +1,57 @@
+import type { Meta, StoryObj } from '@storybook/vue3-vite';
+
+import { fn } from 'storybook/test';
+
+import Button from './Button.vue';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+const meta = {
+ title: 'Example/Button',
+ component: Button,
+ // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ argTypes: {
+ size: { control: 'select', options: ['small', 'medium', 'large'] },
+ backgroundColor: { control: 'color' },
+ },
+ 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#action-args
+ onClick: fn(),
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+/*
+ *👇 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,
+ label: 'Button',
+ },
+};
+
+export const Secondary: Story = {
+ args: {
+ primary: false,
+ label: 'Button',
+ },
+};
+
+export const Large: Story = {
+ args: {
+ label: 'Button',
+ size: 'large',
+ },
+};
+
+export const Small: Story = {
+ args: {
+ label: 'Button',
+ size: 'small',
+ },
+};
diff --git a/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.vue b/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.vue
new file mode 100644
index 000000000000..2e1ee0ee22f3
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.vue
@@ -0,0 +1,48 @@
+
+ {{ label }}
+
+
+
\ No newline at end of file
diff --git a/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.stories.ts
new file mode 100644
index 000000000000..47caa29a09e3
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.stories.ts
@@ -0,0 +1,49 @@
+import type { Meta, StoryObj } from '@storybook/vue3-vite';
+
+import { fn } from 'storybook/test';
+
+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: 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',
+ },
+ args: {
+ onLogin: fn(),
+ onLogout: fn(),
+ onCreateAccount: fn(),
+ },
+ // 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 LoggedIn: Story = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut: Story = {
+ args: {
+ user: null,
+ },
+};
diff --git a/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.vue b/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.vue
new file mode 100644
index 000000000000..b716db02b3f5
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
diff --git a/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.stories.ts
new file mode 100644
index 000000000000..906f674fa3a0
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.stories.ts
@@ -0,0 +1,39 @@
+import { expect, userEvent, within } from '@storybook/test';
+
+import type { Meta, StoryObj } from '@storybook/vue3-vite';
+
+import MyPage from './Page.vue';
+
+const meta = {
+ title: 'Example/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',
+ },
+ // 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;
+
+// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing
+export const LoggedIn: Story = {
+ play: async ({ canvasElement }: any) => {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await expect(loginButton).not.toBeInTheDocument();
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ },
+};
+
+export const LoggedOut: Story = {};
diff --git a/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.vue b/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.vue
new file mode 100644
index 000000000000..6a6e5eb1a4af
--- /dev/null
+++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.vue
@@ -0,0 +1,73 @@
+
+
+
+
+
+ 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/code/frameworks/vue3-webpack5/package.json b/code/frameworks/vue3-webpack5/package.json
index 438e09442f17..c46b6f713875 100644
--- a/code/frameworks/vue3-webpack5/package.json
+++ b/code/frameworks/vue3-webpack5/package.json
@@ -43,6 +43,7 @@
"types": "dist/index.d.ts",
"files": [
"dist/**/*",
+ "template/**/*",
"README.md",
"*.js",
"*.d.ts",
diff --git a/code/frameworks/vue3-webpack5/src/index.ts b/code/frameworks/vue3-webpack5/src/index.ts
index fcb073fefcd6..034adb8b02a6 100644
--- a/code/frameworks/vue3-webpack5/src/index.ts
+++ b/code/frameworks/vue3-webpack5/src/index.ts
@@ -1 +1,2 @@
+export * from '@storybook/vue3';
export * from './types';
diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Button.stories.js b/code/frameworks/vue3-webpack5/template/cli/js/Button.stories.js
new file mode 100644
index 000000000000..2bd009f38165
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/js/Button.stories.js
@@ -0,0 +1,44 @@
+import { fn } from 'storybook/test';
+
+import MyButton from './Button.vue';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+export default {
+ title: 'Example/Button',
+ component: MyButton,
+ tags: ['autodocs'],
+ argTypes: {
+ size: { control: { type: '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() },
+};
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Primary = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Button.vue b/code/frameworks/vue3-webpack5/template/cli/js/Button.vue
new file mode 100644
index 000000000000..a831ddf4991b
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/js/Button.vue
@@ -0,0 +1,52 @@
+
+ {{ label }}
+
+
+
diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Header.stories.js b/code/frameworks/vue3-webpack5/template/cli/js/Header.stories.js
new file mode 100644
index 000000000000..ca1b5e65bf00
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/js/Header.stories.js
@@ -0,0 +1,48 @@
+import { fn } from 'storybook/test';
+
+import MyHeader from './Header.vue';
+
+export default {
+ title: 'Example/Header',
+ component: MyHeader,
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ render: (args) => ({
+ // Components used in your story `template` are defined in the `components` object
+ components: {
+ MyHeader,
+ },
+ // The story's `args` need to be mapped into the template through the `setup()` method
+ setup() {
+ // Story args can be spread into the returned object
+ return {
+ ...args,
+ };
+ },
+ // Then, the spread values can be accessed directly in the template
+ template: ' ',
+ }),
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+ args: {
+ onLogin: fn(),
+ onLogout: fn(),
+ onCreateAccount: fn(),
+ },
+};
+
+export const LoggedIn = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut = {
+ args: {
+ user: null,
+ },
+};
diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Header.vue b/code/frameworks/vue3-webpack5/template/cli/js/Header.vue
new file mode 100644
index 000000000000..16d7740d96c4
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/js/Header.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Page.stories.js b/code/frameworks/vue3-webpack5/template/cli/js/Page.stories.js
new file mode 100644
index 000000000000..f03db3c7f07f
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/js/Page.stories.js
@@ -0,0 +1,34 @@
+import { expect, userEvent, within } from '@storybook/test';
+
+import MyPage from './Page.vue';
+
+export default {
+ title: 'Example/Page',
+ component: MyPage,
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ layout: 'fullscreen',
+ },
+};
+
+export const LoggedOut = {};
+
+// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing
+export const LoggedIn = {
+ render: () => ({
+ components: {
+ MyPage,
+ },
+ template: ' ',
+ }),
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await expect(loginButton).not.toBeInTheDocument();
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ },
+};
diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Page.vue b/code/frameworks/vue3-webpack5/template/cli/js/Page.vue
new file mode 100644
index 000000000000..245401b72c4d
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/js/Page.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+ 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/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.stories.ts
new file mode 100644
index 000000000000..73deaf7ecc03
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.stories.ts
@@ -0,0 +1,57 @@
+import type { Meta, StoryObj } from '@storybook/vue3-webpack5';
+
+import { fn } from 'storybook/test';
+
+import Button from './Button.vue';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+const meta = {
+ title: 'Example/Button',
+ component: Button,
+ // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ argTypes: {
+ size: { control: 'select', options: ['small', 'medium', 'large'] },
+ backgroundColor: { control: 'color' },
+ },
+ 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#action-args
+ onClick: fn(),
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+/*
+ *👇 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,
+ label: 'Button',
+ },
+};
+
+export const Secondary: Story = {
+ args: {
+ primary: false,
+ label: 'Button',
+ },
+};
+
+export const Large: Story = {
+ args: {
+ label: 'Button',
+ size: 'large',
+ },
+};
+
+export const Small: Story = {
+ args: {
+ label: 'Button',
+ size: 'small',
+ },
+};
diff --git a/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.vue b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.vue
new file mode 100644
index 000000000000..2e1ee0ee22f3
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.vue
@@ -0,0 +1,48 @@
+
+ {{ label }}
+
+
+
\ No newline at end of file
diff --git a/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.stories.ts
new file mode 100644
index 000000000000..5826d501c98b
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.stories.ts
@@ -0,0 +1,49 @@
+import type { Meta, StoryObj } from '@storybook/vue3-webpack5';
+
+import { fn } from 'storybook/test';
+
+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: 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',
+ },
+ args: {
+ onLogin: fn(),
+ onLogout: fn(),
+ onCreateAccount: fn(),
+ },
+ // 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 LoggedIn: Story = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut: Story = {
+ args: {
+ user: null,
+ },
+};
diff --git a/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.vue b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.vue
new file mode 100644
index 000000000000..b716db02b3f5
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
diff --git a/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.stories.ts
new file mode 100644
index 000000000000..dfc690f896c5
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.stories.ts
@@ -0,0 +1,39 @@
+import { expect, userEvent, within } from '@storybook/test';
+
+import type { Meta, StoryObj } from '@storybook/vue3-webpack5';
+
+import MyPage from './Page.vue';
+
+const meta = {
+ title: 'Example/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',
+ },
+ // 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;
+
+// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing
+export const LoggedIn: Story = {
+ play: async ({ canvasElement }: any) => {
+ const canvas = within(canvasElement);
+ const loginButton = canvas.getByRole('button', { name: /Log in/i });
+ await expect(loginButton).toBeInTheDocument();
+ await userEvent.click(loginButton);
+ await expect(loginButton).not.toBeInTheDocument();
+
+ const logoutButton = canvas.getByRole('button', { name: /Log out/i });
+ await expect(logoutButton).toBeInTheDocument();
+ },
+};
+
+export const LoggedOut: Story = {};
diff --git a/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.vue b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.vue
new file mode 100644
index 000000000000..6a6e5eb1a4af
--- /dev/null
+++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.vue
@@ -0,0 +1,73 @@
+
+
+
+
+
+ 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/code/frameworks/web-components-vite/package.json b/code/frameworks/web-components-vite/package.json
index 06537c129744..549bb897aac3 100644
--- a/code/frameworks/web-components-vite/package.json
+++ b/code/frameworks/web-components-vite/package.json
@@ -43,6 +43,7 @@
"types": "dist/index.d.ts",
"files": [
"dist/**/*",
+ "template/**/*",
"README.md",
"*.js",
"*.d.ts",
diff --git a/code/frameworks/web-components-vite/src/index.ts b/code/frameworks/web-components-vite/src/index.ts
index fcb073fefcd6..538d3b3a6d67 100644
--- a/code/frameworks/web-components-vite/src/index.ts
+++ b/code/frameworks/web-components-vite/src/index.ts
@@ -1 +1,2 @@
+export * from '@storybook/web-components';
export * from './types';
diff --git a/code/frameworks/web-components-vite/template/cli/.eslintrc.json b/code/frameworks/web-components-vite/template/cli/.eslintrc.json
new file mode 100644
index 000000000000..40ece4a0aa18
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/.eslintrc.json
@@ -0,0 +1,5 @@
+{
+ "rules": {
+ "import/extensions": "off"
+ }
+}
diff --git a/code/frameworks/web-components-vite/template/cli/js/Button.js b/code/frameworks/web-components-vite/template/cli/js/Button.js
new file mode 100644
index 000000000000..6cbe804eb1b7
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/js/Button.js
@@ -0,0 +1,20 @@
+import { html } from 'lit';
+import { styleMap } from 'lit/directives/style-map.js';
+
+import './button.css';
+
+/** Primary UI component for user interaction */
+export const Button = ({ primary, backgroundColor = null, size, label, onClick }) => {
+ const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
+
+ return html`
+
+ ${label}
+
+ `;
+};
diff --git a/code/frameworks/web-components-vite/template/cli/js/Button.stories.js b/code/frameworks/web-components-vite/template/cli/js/Button.stories.js
new file mode 100644
index 000000000000..9efdf07ece3d
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/js/Button.stories.js
@@ -0,0 +1,46 @@
+import { fn } from 'storybook/test';
+
+import { Button } from './Button';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+export default {
+ title: 'Example/Button',
+ tags: ['autodocs'],
+ render: (args) => Button(args),
+ argTypes: {
+ backgroundColor: { control: 'color' },
+ size: {
+ control: { type: 'select' },
+ options: ['small', 'medium', 'large'],
+ },
+ },
+ args: { onClick: fn() },
+};
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Primary = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/web-components-vite/template/cli/js/Header.js b/code/frameworks/web-components-vite/template/cli/js/Header.js
new file mode 100644
index 000000000000..19fea63604a8
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/js/Header.js
@@ -0,0 +1,45 @@
+import { html } from 'lit';
+
+import { Button } from './Button';
+import './header.css';
+
+export const Header = ({ user, onLogin, onLogout, onCreateAccount }) => html`
+
+`;
diff --git a/code/frameworks/web-components-vite/template/cli/js/Header.stories.js b/code/frameworks/web-components-vite/template/cli/js/Header.stories.js
new file mode 100644
index 000000000000..b45ba68c5a87
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/js/Header.stories.js
@@ -0,0 +1,24 @@
+import { fn } from 'storybook/test';
+
+import { Header } from './Header';
+
+export default {
+ title: 'Example/Header',
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/web-components/vue/writing-docs/autodocs
+ tags: ['autodocs'],
+ render: (args) => Header(args),
+ args: {
+ onLogin: fn(),
+ onLogout: fn(),
+ onCreateAccount: fn(),
+ },
+};
+export const LoggedIn = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut = {};
diff --git a/code/frameworks/web-components-vite/template/cli/js/Page.js b/code/frameworks/web-components-vite/template/cli/js/Page.js
new file mode 100644
index 000000000000..54919dabd48b
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/js/Page.js
@@ -0,0 +1,62 @@
+import { html } from 'lit';
+
+import { Header } from './Header';
+import './page.css';
+
+export const Page = ({ user, onLogin, onLogout, onCreateAccount }) => html`
+
+ ${Header({
+ user,
+ onLogin,
+ onLogout,
+ onCreateAccount,
+ })}
+
+
+ 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/code/frameworks/web-components-vite/template/cli/js/Page.stories.js b/code/frameworks/web-components-vite/template/cli/js/Page.stories.js
new file mode 100644
index 000000000000..7c28c5ad14b3
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/js/Page.stories.js
@@ -0,0 +1,20 @@
+import * as HeaderStories from './Header.stories';
+import { Page } from './Page';
+
+export default {
+ title: 'Example/Page',
+ render: (args) => Page(args),
+};
+
+export const LoggedIn = {
+ args: {
+ // More on composing args: https://storybook.js.org/docs/writing-stories/args#args-composition
+ ...HeaderStories.LoggedIn.args,
+ },
+};
+
+export const LoggedOut = {
+ args: {
+ ...HeaderStories.LoggedOut.args,
+ },
+};
diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.stories.ts
new file mode 100644
index 000000000000..8b595baddc2c
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.stories.ts
@@ -0,0 +1,52 @@
+import type { Meta, StoryObj } from '@storybook/web-components-vite';
+
+import { fn } from 'storybook/test';
+
+import type { ButtonProps } from './Button';
+import { Button } from './Button';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+const meta = {
+ title: 'Example/Button',
+ tags: ['autodocs'],
+ render: (args) => Button(args),
+ argTypes: {
+ backgroundColor: { control: 'color' },
+ size: {
+ control: { type: 'select' },
+ options: ['small', 'medium', 'large'],
+ },
+ },
+ 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
+export const Primary: Story = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary: Story = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large: Story = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small: Story = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.ts
new file mode 100644
index 000000000000..4ca7fe4a7232
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.ts
@@ -0,0 +1,32 @@
+import { html } from 'lit';
+import { styleMap } from 'lit/directives/style-map.js';
+
+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, backgroundColor, size, label, onClick }: ButtonProps) => {
+ const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
+
+ return html`
+
+ ${label}
+
+ `;
+};
diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.stories.ts
new file mode 100644
index 000000000000..b2f7d90ce371
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.stories.ts
@@ -0,0 +1,31 @@
+import type { Meta, StoryObj } from '@storybook/web-components-vite';
+
+import { fn } from 'storybook/test';
+
+import type { HeaderProps } from './Header';
+import { Header } from './Header';
+
+const meta = {
+ title: 'Example/Header',
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ render: (args: HeaderProps) => Header(args),
+ args: {
+ onLogin: fn(),
+ onLogout: fn(),
+ onCreateAccount: fn(),
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LoggedIn: Story = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut: Story = {};
diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.ts
new file mode 100644
index 000000000000..7c3c8b89375a
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.ts
@@ -0,0 +1,56 @@
+import { html } from 'lit';
+
+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) => html`
+
+`;
diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.stories.ts
new file mode 100644
index 000000000000..57505c5f694d
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.stories.ts
@@ -0,0 +1,26 @@
+import type { Meta, StoryObj } from '@storybook/web-components-vite';
+
+import * as HeaderStories from './Header.stories';
+import type { PageProps } from './Page';
+import { Page } from './Page';
+
+const meta = {
+ title: 'Example/Page',
+ render: (args: PageProps) => Page(args),
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LoggedIn: Story = {
+ args: {
+ // More on composing args: https://storybook.js.org/docs/writing-stories/args#args-composition
+ ...HeaderStories.LoggedIn.args,
+ },
+};
+
+export const LoggedOut: Story = {
+ args: {
+ ...HeaderStories.LoggedOut.args,
+ },
+};
diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.ts
new file mode 100644
index 000000000000..079c4f04cfbc
--- /dev/null
+++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.ts
@@ -0,0 +1,73 @@
+import { html } from 'lit';
+
+import { Header } from './Header';
+import './page.css';
+
+type User = {
+ name: string;
+};
+
+export interface PageProps {
+ user?: User;
+ onLogin?: () => void;
+ onLogout?: () => void;
+ onCreateAccount?: () => void;
+}
+
+export const Page = ({ user, onLogin, onLogout, onCreateAccount }: PageProps) => html`
+
+ ${Header({
+ user,
+ onLogin,
+ onLogout,
+ onCreateAccount,
+ })}
+
+
+ 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/code/frameworks/web-components-webpack5/package.json b/code/frameworks/web-components-webpack5/package.json
index f7a59969d419..e13ae030089a 100644
--- a/code/frameworks/web-components-webpack5/package.json
+++ b/code/frameworks/web-components-webpack5/package.json
@@ -46,6 +46,7 @@
"types": "dist/index.d.ts",
"files": [
"dist/**/*",
+ "template/**/*",
"README.md",
"*.js",
"*.d.ts",
diff --git a/code/frameworks/web-components-webpack5/src/index.ts b/code/frameworks/web-components-webpack5/src/index.ts
index fcb073fefcd6..538d3b3a6d67 100644
--- a/code/frameworks/web-components-webpack5/src/index.ts
+++ b/code/frameworks/web-components-webpack5/src/index.ts
@@ -1 +1,2 @@
+export * from '@storybook/web-components';
export * from './types';
diff --git a/code/frameworks/web-components-webpack5/template/cli/.eslintrc.json b/code/frameworks/web-components-webpack5/template/cli/.eslintrc.json
new file mode 100644
index 000000000000..40ece4a0aa18
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/.eslintrc.json
@@ -0,0 +1,5 @@
+{
+ "rules": {
+ "import/extensions": "off"
+ }
+}
diff --git a/code/frameworks/web-components-webpack5/template/cli/js/Button.js b/code/frameworks/web-components-webpack5/template/cli/js/Button.js
new file mode 100644
index 000000000000..6cbe804eb1b7
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/js/Button.js
@@ -0,0 +1,20 @@
+import { html } from 'lit';
+import { styleMap } from 'lit/directives/style-map.js';
+
+import './button.css';
+
+/** Primary UI component for user interaction */
+export const Button = ({ primary, backgroundColor = null, size, label, onClick }) => {
+ const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
+
+ return html`
+
+ ${label}
+
+ `;
+};
diff --git a/code/frameworks/web-components-webpack5/template/cli/js/Button.stories.js b/code/frameworks/web-components-webpack5/template/cli/js/Button.stories.js
new file mode 100644
index 000000000000..9efdf07ece3d
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/js/Button.stories.js
@@ -0,0 +1,46 @@
+import { fn } from 'storybook/test';
+
+import { Button } from './Button';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+export default {
+ title: 'Example/Button',
+ tags: ['autodocs'],
+ render: (args) => Button(args),
+ argTypes: {
+ backgroundColor: { control: 'color' },
+ size: {
+ control: { type: 'select' },
+ options: ['small', 'medium', 'large'],
+ },
+ },
+ args: { onClick: fn() },
+};
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Primary = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/web-components-webpack5/template/cli/js/Header.js b/code/frameworks/web-components-webpack5/template/cli/js/Header.js
new file mode 100644
index 000000000000..19fea63604a8
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/js/Header.js
@@ -0,0 +1,45 @@
+import { html } from 'lit';
+
+import { Button } from './Button';
+import './header.css';
+
+export const Header = ({ user, onLogin, onLogout, onCreateAccount }) => html`
+
+`;
diff --git a/code/frameworks/web-components-webpack5/template/cli/js/Header.stories.js b/code/frameworks/web-components-webpack5/template/cli/js/Header.stories.js
new file mode 100644
index 000000000000..b45ba68c5a87
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/js/Header.stories.js
@@ -0,0 +1,24 @@
+import { fn } from 'storybook/test';
+
+import { Header } from './Header';
+
+export default {
+ title: 'Example/Header',
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/web-components/vue/writing-docs/autodocs
+ tags: ['autodocs'],
+ render: (args) => Header(args),
+ args: {
+ onLogin: fn(),
+ onLogout: fn(),
+ onCreateAccount: fn(),
+ },
+};
+export const LoggedIn = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut = {};
diff --git a/code/frameworks/web-components-webpack5/template/cli/js/Page.js b/code/frameworks/web-components-webpack5/template/cli/js/Page.js
new file mode 100644
index 000000000000..54919dabd48b
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/js/Page.js
@@ -0,0 +1,62 @@
+import { html } from 'lit';
+
+import { Header } from './Header';
+import './page.css';
+
+export const Page = ({ user, onLogin, onLogout, onCreateAccount }) => html`
+
+ ${Header({
+ user,
+ onLogin,
+ onLogout,
+ onCreateAccount,
+ })}
+
+
+ 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/code/frameworks/web-components-webpack5/template/cli/js/Page.stories.js b/code/frameworks/web-components-webpack5/template/cli/js/Page.stories.js
new file mode 100644
index 000000000000..7c28c5ad14b3
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/js/Page.stories.js
@@ -0,0 +1,20 @@
+import * as HeaderStories from './Header.stories';
+import { Page } from './Page';
+
+export default {
+ title: 'Example/Page',
+ render: (args) => Page(args),
+};
+
+export const LoggedIn = {
+ args: {
+ // More on composing args: https://storybook.js.org/docs/writing-stories/args#args-composition
+ ...HeaderStories.LoggedIn.args,
+ },
+};
+
+export const LoggedOut = {
+ args: {
+ ...HeaderStories.LoggedOut.args,
+ },
+};
diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.stories.ts
new file mode 100644
index 000000000000..e3085252e4bb
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.stories.ts
@@ -0,0 +1,52 @@
+import type { Meta, StoryObj } from '@storybook/web-components-webpack5';
+
+import { fn } from 'storybook/test';
+
+import type { ButtonProps } from './Button';
+import { Button } from './Button';
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
+const meta = {
+ title: 'Example/Button',
+ tags: ['autodocs'],
+ render: (args) => Button(args),
+ argTypes: {
+ backgroundColor: { control: 'color' },
+ size: {
+ control: { type: 'select' },
+ options: ['small', 'medium', 'large'],
+ },
+ },
+ 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
+export const Primary: Story = {
+ args: {
+ primary: true,
+ label: 'Button',
+ },
+};
+
+export const Secondary: Story = {
+ args: {
+ label: 'Button',
+ },
+};
+
+export const Large: Story = {
+ args: {
+ size: 'large',
+ label: 'Button',
+ },
+};
+
+export const Small: Story = {
+ args: {
+ size: 'small',
+ label: 'Button',
+ },
+};
diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.ts
new file mode 100644
index 000000000000..4ca7fe4a7232
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.ts
@@ -0,0 +1,32 @@
+import { html } from 'lit';
+import { styleMap } from 'lit/directives/style-map.js';
+
+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, backgroundColor, size, label, onClick }: ButtonProps) => {
+ const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
+
+ return html`
+
+ ${label}
+
+ `;
+};
diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.stories.ts
new file mode 100644
index 000000000000..9564aa90e730
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.stories.ts
@@ -0,0 +1,31 @@
+import type { Meta, StoryObj } from '@storybook/web-components-webpack5';
+
+import { fn } from 'storybook/test';
+
+import type { HeaderProps } from './Header';
+import { Header } from './Header';
+
+const meta = {
+ title: 'Example/Header',
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+ render: (args: HeaderProps) => Header(args),
+ args: {
+ onLogin: fn(),
+ onLogout: fn(),
+ onCreateAccount: fn(),
+ },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LoggedIn: Story = {
+ args: {
+ user: {
+ name: 'Jane Doe',
+ },
+ },
+};
+
+export const LoggedOut: Story = {};
diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.ts
new file mode 100644
index 000000000000..7c3c8b89375a
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.ts
@@ -0,0 +1,56 @@
+import { html } from 'lit';
+
+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) => html`
+
+`;
diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.stories.ts
new file mode 100644
index 000000000000..51ba30dfaaea
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.stories.ts
@@ -0,0 +1,26 @@
+import type { Meta, StoryObj } from '@storybook/web-components-webpack5';
+
+import * as HeaderStories from './Header.stories';
+import type { PageProps } from './Page';
+import { Page } from './Page';
+
+const meta = {
+ title: 'Example/Page',
+ render: (args: PageProps) => Page(args),
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LoggedIn: Story = {
+ args: {
+ // More on composing args: https://storybook.js.org/docs/writing-stories/args#args-composition
+ ...HeaderStories.LoggedIn.args,
+ },
+};
+
+export const LoggedOut: Story = {
+ args: {
+ ...HeaderStories.LoggedOut.args,
+ },
+};
diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.ts
new file mode 100644
index 000000000000..079c4f04cfbc
--- /dev/null
+++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.ts
@@ -0,0 +1,73 @@
+import { html } from 'lit';
+
+import { Header } from './Header';
+import './page.css';
+
+type User = {
+ name: string;
+};
+
+export interface PageProps {
+ user?: User;
+ onLogin?: () => void;
+ onLogout?: () => void;
+ onCreateAccount?: () => void;
+}
+
+export const Page = ({ user, onLogin, onLogout, onCreateAccount }: PageProps) => html`
+
+ ${Header({
+ user,
+ onLogin,
+ onLogout,
+ onCreateAccount,
+ })}
+
+
+ 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/code/lib/blocks/package.json b/code/lib/blocks/package.json
index a124f721788b..c8bd492d8868 100644
--- a/code/lib/blocks/package.json
+++ b/code/lib/blocks/package.json
@@ -49,7 +49,6 @@
"devDependencies": {
"@storybook/addon-actions": "workspace:*",
"@storybook/react": "workspace:*",
- "@storybook/test": "workspace:*",
"@types/color-convert": "^2.0.0",
"color-convert": "^2.0.1",
"es-toolkit": "^1.22.0",
diff --git a/code/lib/blocks/src/blocks/Anchor.stories.tsx b/code/lib/blocks/src/blocks/Anchor.stories.tsx
index 276c5aa2219e..262af3d77039 100644
--- a/code/lib/blocks/src/blocks/Anchor.stories.tsx
+++ b/code/lib/blocks/src/blocks/Anchor.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Anchor } from './Anchor';
diff --git a/code/lib/blocks/src/blocks/ArgTypes.stories.tsx b/code/lib/blocks/src/blocks/ArgTypes.stories.tsx
index 7738bde257eb..4a17e355d874 100644
--- a/code/lib/blocks/src/blocks/ArgTypes.stories.tsx
+++ b/code/lib/blocks/src/blocks/ArgTypes.stories.tsx
@@ -2,8 +2,9 @@ import React from 'react';
import type { PlayFunctionContext } from 'storybook/internal/csf';
-import type { Meta, StoryObj } from '@storybook/react';
-import { within } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { within } from 'storybook/test';
import * as ExampleStories from '../examples/ArgTypesParameters.stories';
import * as SubcomponentsExampleStories from '../examples/ArgTypesWithSubcomponentsParameters.stories';
diff --git a/code/lib/blocks/src/blocks/Canvas.stories.tsx b/code/lib/blocks/src/blocks/Canvas.stories.tsx
index 987e28678a71..befddeebd0ad 100644
--- a/code/lib/blocks/src/blocks/Canvas.stories.tsx
+++ b/code/lib/blocks/src/blocks/Canvas.stories.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { dedent } from 'ts-dedent';
diff --git a/code/lib/blocks/src/blocks/Controls.stories.tsx b/code/lib/blocks/src/blocks/Controls.stories.tsx
index 624f03452b8b..09e424484c55 100644
--- a/code/lib/blocks/src/blocks/Controls.stories.tsx
+++ b/code/lib/blocks/src/blocks/Controls.stories.tsx
@@ -2,8 +2,9 @@ import React from 'react';
import type { PlayFunctionContext } from 'storybook/internal/csf';
-import type { Meta, StoryObj } from '@storybook/react';
-import { within } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { within } from 'storybook/test';
import * as ExampleStories from '../examples/ControlsParameters.stories';
import * as SubcomponentsExampleStories from '../examples/ControlsWithSubcomponentsParameters.stories';
diff --git a/code/lib/blocks/src/blocks/Description.stories.tsx b/code/lib/blocks/src/blocks/Description.stories.tsx
index 9285fd9095ff..31bbea234588 100644
--- a/code/lib/blocks/src/blocks/Description.stories.tsx
+++ b/code/lib/blocks/src/blocks/Description.stories.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button as ButtonComponent } from '../examples/Button';
import * as DefaultButtonStories from '../examples/Button.stories';
diff --git a/code/lib/blocks/src/blocks/DocsPage.stories.tsx b/code/lib/blocks/src/blocks/DocsPage.stories.tsx
index 1ed85bfa3ac9..31b433f68867 100644
--- a/code/lib/blocks/src/blocks/DocsPage.stories.tsx
+++ b/code/lib/blocks/src/blocks/DocsPage.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { DocsPage } from './DocsPage';
diff --git a/code/lib/blocks/src/blocks/Primary.stories.tsx b/code/lib/blocks/src/blocks/Primary.stories.tsx
index 6ea9025eac9c..39b9123ea726 100644
--- a/code/lib/blocks/src/blocks/Primary.stories.tsx
+++ b/code/lib/blocks/src/blocks/Primary.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import * as DefaultButtonStories from '../examples/Button.stories';
import * as StoriesParametersStories from '../examples/StoriesParameters.stories';
diff --git a/code/lib/blocks/src/blocks/Source.stories.tsx b/code/lib/blocks/src/blocks/Source.stories.tsx
index 8981289a1491..30915ce18af9 100644
--- a/code/lib/blocks/src/blocks/Source.stories.tsx
+++ b/code/lib/blocks/src/blocks/Source.stories.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { SourceType } from 'storybook/internal/docs-tools';
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { dedent } from 'ts-dedent';
diff --git a/code/lib/blocks/src/blocks/Stories.stories.tsx b/code/lib/blocks/src/blocks/Stories.stories.tsx
index 017da21c799e..98576f0892b6 100644
--- a/code/lib/blocks/src/blocks/Stories.stories.tsx
+++ b/code/lib/blocks/src/blocks/Stories.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Stories } from './Stories';
diff --git a/code/lib/blocks/src/blocks/Story.stories.tsx b/code/lib/blocks/src/blocks/Story.stories.tsx
index 370262bf0f2f..6616b489934e 100644
--- a/code/lib/blocks/src/blocks/Story.stories.tsx
+++ b/code/lib/blocks/src/blocks/Story.stories.tsx
@@ -1,7 +1,8 @@
import React from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
-import { expect, waitFor } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { expect, waitFor } from 'storybook/test';
import * as StoryComponentStories from '../components/Story.stories';
import * as ButtonStories from '../examples/Button.stories';
diff --git a/code/lib/blocks/src/blocks/Subtitle.stories.tsx b/code/lib/blocks/src/blocks/Subtitle.stories.tsx
index df1b8ff2fd70..e0e847cd9182 100644
--- a/code/lib/blocks/src/blocks/Subtitle.stories.tsx
+++ b/code/lib/blocks/src/blocks/Subtitle.stories.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import * as DefaultButtonStories from '../examples/Button.stories';
import * as ButtonStoriesWithMetaSubtitleAsBoth from '../examples/ButtonWithMetaSubtitleAsBoth.stories';
diff --git a/code/lib/blocks/src/blocks/Title.stories.tsx b/code/lib/blocks/src/blocks/Title.stories.tsx
index 00ec452971be..7eed0521a0a2 100644
--- a/code/lib/blocks/src/blocks/Title.stories.tsx
+++ b/code/lib/blocks/src/blocks/Title.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import * as DefaultButtonStories from '../examples/Button.stories';
import { Title } from './Title';
diff --git a/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx b/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx
index ce83ae7e67ed..3cbad6a0e329 100644
--- a/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx
+++ b/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { styled } from 'storybook/internal/theming';
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { action } from '@storybook/addon-actions';
diff --git a/code/lib/blocks/src/components/Source.stories.tsx b/code/lib/blocks/src/components/Source.stories.tsx
index d7028b920e05..cd2d7ae38bb9 100644
--- a/code/lib/blocks/src/components/Source.stories.tsx
+++ b/code/lib/blocks/src/components/Source.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Source, SourceError } from './Source';
diff --git a/code/lib/blocks/src/components/Story.stories.tsx b/code/lib/blocks/src/components/Story.stories.tsx
index 09e64a2dd1dd..9d3ad8c7591b 100644
--- a/code/lib/blocks/src/components/Story.stories.tsx
+++ b/code/lib/blocks/src/components/Story.stories.tsx
@@ -10,8 +10,9 @@ import type { PlayFunctionContext } from 'storybook/internal/csf';
import type { PreviewWeb } from 'storybook/internal/preview-api';
import type { ModuleExport, WebRenderer } from 'storybook/internal/types';
-import type { Meta, ReactRenderer, StoryObj } from '@storybook/react';
-import { within } from '@storybook/test';
+import type { Meta, ReactRenderer, StoryObj } from '@storybook/react-vite';
+
+import { within } from 'storybook/test';
import type { DocsContextProps } from '../blocks';
import * as ButtonStories from '../examples/Button.stories';
diff --git a/code/lib/blocks/src/controls/Boolean.stories.tsx b/code/lib/blocks/src/controls/Boolean.stories.tsx
index ad7365c03838..5276f71edb6e 100644
--- a/code/lib/blocks/src/controls/Boolean.stories.tsx
+++ b/code/lib/blocks/src/controls/Boolean.stories.tsx
@@ -1,8 +1,9 @@
import { RESET_STORY_ARGS, STORY_ARGS_UPDATED } from 'storybook/internal/core-events';
import { addons } from 'storybook/internal/preview-api';
-import type { Meta, StoryObj } from '@storybook/react';
-import { expect, fireEvent, fn, waitFor, within } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { expect, fireEvent, fn, waitFor, within } from 'storybook/test';
import { BooleanControl } from './Boolean';
diff --git a/code/lib/blocks/src/controls/Color.stories.tsx b/code/lib/blocks/src/controls/Color.stories.tsx
index 8b77cff62f0c..867e0d0c5cb7 100644
--- a/code/lib/blocks/src/controls/Color.stories.tsx
+++ b/code/lib/blocks/src/controls/Color.stories.tsx
@@ -1,5 +1,6 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
import { ColorControl } from './Color';
diff --git a/code/lib/blocks/src/controls/Date.stories.tsx b/code/lib/blocks/src/controls/Date.stories.tsx
index c2fcb33e39bb..f8f3200f3129 100644
--- a/code/lib/blocks/src/controls/Date.stories.tsx
+++ b/code/lib/blocks/src/controls/Date.stories.tsx
@@ -1,5 +1,6 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
import { DateControl } from './Date';
diff --git a/code/lib/blocks/src/controls/Files.stories.tsx b/code/lib/blocks/src/controls/Files.stories.tsx
index 640f954260c1..82c8f61eed1e 100644
--- a/code/lib/blocks/src/controls/Files.stories.tsx
+++ b/code/lib/blocks/src/controls/Files.stories.tsx
@@ -1,5 +1,6 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
import { FilesControl } from './Files';
diff --git a/code/lib/blocks/src/controls/Number.stories.tsx b/code/lib/blocks/src/controls/Number.stories.tsx
index 80bde03aeeff..ae5daf07be0d 100644
--- a/code/lib/blocks/src/controls/Number.stories.tsx
+++ b/code/lib/blocks/src/controls/Number.stories.tsx
@@ -1,5 +1,6 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
import { NumberControl } from './Number';
diff --git a/code/lib/blocks/src/controls/Object.stories.tsx b/code/lib/blocks/src/controls/Object.stories.tsx
index 0929234e3ad2..de883570198b 100644
--- a/code/lib/blocks/src/controls/Object.stories.tsx
+++ b/code/lib/blocks/src/controls/Object.stories.tsx
@@ -1,5 +1,6 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
import { ObjectControl } from './Object';
diff --git a/code/lib/blocks/src/controls/Range.stories.tsx b/code/lib/blocks/src/controls/Range.stories.tsx
index cd8ca20c5220..b8464d923c17 100644
--- a/code/lib/blocks/src/controls/Range.stories.tsx
+++ b/code/lib/blocks/src/controls/Range.stories.tsx
@@ -1,5 +1,6 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
import { RangeControl } from './Range';
diff --git a/code/lib/blocks/src/controls/Text.stories.tsx b/code/lib/blocks/src/controls/Text.stories.tsx
index 71dee59dc19a..e1ce009699f2 100644
--- a/code/lib/blocks/src/controls/Text.stories.tsx
+++ b/code/lib/blocks/src/controls/Text.stories.tsx
@@ -1,5 +1,6 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
import { TextControl } from './Text';
diff --git a/code/lib/blocks/src/controls/options/CheckOptions.stories.tsx b/code/lib/blocks/src/controls/options/CheckOptions.stories.tsx
index 8e98d88c080f..e98ac3cc049e 100644
--- a/code/lib/blocks/src/controls/options/CheckOptions.stories.tsx
+++ b/code/lib/blocks/src/controls/options/CheckOptions.stories.tsx
@@ -1,5 +1,6 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
import { OptionsControl } from './Options';
diff --git a/code/lib/blocks/src/controls/options/RadioOptions.stories.tsx b/code/lib/blocks/src/controls/options/RadioOptions.stories.tsx
index e96f52b781cf..e0a5bb706a4e 100644
--- a/code/lib/blocks/src/controls/options/RadioOptions.stories.tsx
+++ b/code/lib/blocks/src/controls/options/RadioOptions.stories.tsx
@@ -1,5 +1,6 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
import { OptionsControl } from './Options';
diff --git a/code/lib/blocks/src/controls/options/SelectOptions.stories.tsx b/code/lib/blocks/src/controls/options/SelectOptions.stories.tsx
index 81efc451c7f5..71e28da394d4 100644
--- a/code/lib/blocks/src/controls/options/SelectOptions.stories.tsx
+++ b/code/lib/blocks/src/controls/options/SelectOptions.stories.tsx
@@ -1,5 +1,6 @@
-import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { fn } from 'storybook/test';
import { OptionsControl } from './Options';
diff --git a/code/lib/blocks/src/examples/ArgTypesParameters.stories.tsx b/code/lib/blocks/src/examples/ArgTypesParameters.stories.tsx
index 95fef9f585fc..a5660dbfd967 100644
--- a/code/lib/blocks/src/examples/ArgTypesParameters.stories.tsx
+++ b/code/lib/blocks/src/examples/ArgTypesParameters.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { ArgTypesParameters } from './ArgTypesParameters';
diff --git a/code/lib/blocks/src/examples/ArgTypesWithSubcomponentsParameters.stories.tsx b/code/lib/blocks/src/examples/ArgTypesWithSubcomponentsParameters.stories.tsx
index b6c66a4ae53a..24b00efc25d2 100644
--- a/code/lib/blocks/src/examples/ArgTypesWithSubcomponentsParameters.stories.tsx
+++ b/code/lib/blocks/src/examples/ArgTypesWithSubcomponentsParameters.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { ArgTypesParameters, SubcomponentA, SubcomponentB } from './ArgTypesParameters';
diff --git a/code/lib/blocks/src/examples/Button.stories.tsx b/code/lib/blocks/src/examples/Button.stories.tsx
index c22d141f541c..8aa24f8a8ed9 100644
--- a/code/lib/blocks/src/examples/Button.stories.tsx
+++ b/code/lib/blocks/src/examples/Button.stories.tsx
@@ -1,8 +1,9 @@
/* eslint-disable local-rules/no-uncategorized-errors */
import React from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
-import { expect, fireEvent, within } from '@storybook/test';
+import type { Meta, StoryObj } from '@storybook/react-vite';
+
+import { expect, fireEvent, within } from 'storybook/test';
import { Button } from './Button';
diff --git a/code/lib/blocks/src/examples/ButtonNoAutodocs.stories.tsx b/code/lib/blocks/src/examples/ButtonNoAutodocs.stories.tsx
index 727ba4598ba2..ac771a2c43d3 100644
--- a/code/lib/blocks/src/examples/ButtonNoAutodocs.stories.tsx
+++ b/code/lib/blocks/src/examples/ButtonNoAutodocs.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from './Button';
diff --git a/code/lib/blocks/src/examples/ButtonReadonly.stories.tsx b/code/lib/blocks/src/examples/ButtonReadonly.stories.tsx
index 442f945490b2..7fc7bffe26b5 100644
--- a/code/lib/blocks/src/examples/ButtonReadonly.stories.tsx
+++ b/code/lib/blocks/src/examples/ButtonReadonly.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from './Button';
diff --git a/code/lib/blocks/src/examples/ButtonSomeAutodocs.stories.tsx b/code/lib/blocks/src/examples/ButtonSomeAutodocs.stories.tsx
index fbc06945b979..62e7c8c37210 100644
--- a/code/lib/blocks/src/examples/ButtonSomeAutodocs.stories.tsx
+++ b/code/lib/blocks/src/examples/ButtonSomeAutodocs.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from './Button';
diff --git a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsBoth.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsBoth.stories.tsx
index a5515b3ee335..40543373c6ef 100644
--- a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsBoth.stories.tsx
+++ b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsBoth.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from './Button';
diff --git a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsComment.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsComment.stories.tsx
index 95464610b4aa..31862be623d2 100644
--- a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsComment.stories.tsx
+++ b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsComment.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from './Button';
diff --git a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsParameter.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsParameter.stories.tsx
index fff71f67e626..bf044d45bac6 100644
--- a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsParameter.stories.tsx
+++ b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsParameter.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from './Button';
diff --git a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsBoth.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsBoth.stories.tsx
index 6ee3c6c12930..78f6218743ba 100644
--- a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsBoth.stories.tsx
+++ b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsBoth.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from './Button';
diff --git a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsComponentSubtitle.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsComponentSubtitle.stories.tsx
index 9a430f39e81f..f67f7c5aeaef 100644
--- a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsComponentSubtitle.stories.tsx
+++ b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsComponentSubtitle.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from './Button';
diff --git a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsDocsSubtitle.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsDocsSubtitle.stories.tsx
index 0ec5ff64c6fe..47794cda9006 100644
--- a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsDocsSubtitle.stories.tsx
+++ b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsDocsSubtitle.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from './Button';
diff --git a/code/lib/blocks/src/examples/CanvasParameters.stories.tsx b/code/lib/blocks/src/examples/CanvasParameters.stories.tsx
index 4d4433747494..c286e07e7bbc 100644
--- a/code/lib/blocks/src/examples/CanvasParameters.stories.tsx
+++ b/code/lib/blocks/src/examples/CanvasParameters.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { EmptyExample } from './EmptyExample';
diff --git a/code/lib/blocks/src/examples/ControlsParameters.stories.tsx b/code/lib/blocks/src/examples/ControlsParameters.stories.tsx
index 7684d4f0e02f..497c543d728c 100644
--- a/code/lib/blocks/src/examples/ControlsParameters.stories.tsx
+++ b/code/lib/blocks/src/examples/ControlsParameters.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { ControlsParameters } from './ControlsParameters';
diff --git a/code/lib/blocks/src/examples/ControlsWithSubcomponentsParameters.stories.tsx b/code/lib/blocks/src/examples/ControlsWithSubcomponentsParameters.stories.tsx
index bf2e1e77d37a..543c55be5546 100644
--- a/code/lib/blocks/src/examples/ControlsWithSubcomponentsParameters.stories.tsx
+++ b/code/lib/blocks/src/examples/ControlsWithSubcomponentsParameters.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { ControlsParameters, SubcomponentA, SubcomponentB } from './ControlsParameters';
diff --git a/code/lib/blocks/src/examples/DocsPageParameters.stories.tsx b/code/lib/blocks/src/examples/DocsPageParameters.stories.tsx
index 91d5b3f3cadd..2f52462c6e7c 100644
--- a/code/lib/blocks/src/examples/DocsPageParameters.stories.tsx
+++ b/code/lib/blocks/src/examples/DocsPageParameters.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { EmptyExample } from './EmptyExample';
diff --git a/code/lib/blocks/src/examples/EmptyArgTypes.stories.tsx b/code/lib/blocks/src/examples/EmptyArgTypes.stories.tsx
index 9c596e5def69..ebe717ad91d9 100644
--- a/code/lib/blocks/src/examples/EmptyArgTypes.stories.tsx
+++ b/code/lib/blocks/src/examples/EmptyArgTypes.stories.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import type { ControlsParameters } from './ControlsParameters';
diff --git a/code/lib/blocks/src/examples/SourceParameters.stories.tsx b/code/lib/blocks/src/examples/SourceParameters.stories.tsx
index ee40704a051e..cc1043678228 100644
--- a/code/lib/blocks/src/examples/SourceParameters.stories.tsx
+++ b/code/lib/blocks/src/examples/SourceParameters.stories.tsx
@@ -1,7 +1,7 @@
import { SourceType } from 'storybook/internal/docs-tools';
import type { StoryContext } from 'storybook/internal/types';
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { dedent } from 'ts-dedent';
diff --git a/code/lib/blocks/src/examples/StoriesParameters.stories.tsx b/code/lib/blocks/src/examples/StoriesParameters.stories.tsx
index 731291ad75f7..74b397ee4b69 100644
--- a/code/lib/blocks/src/examples/StoriesParameters.stories.tsx
+++ b/code/lib/blocks/src/examples/StoriesParameters.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { EmptyExample } from './EmptyExample';
diff --git a/code/lib/blocks/src/examples/StoryParameters.stories.tsx b/code/lib/blocks/src/examples/StoryParameters.stories.tsx
index 79c8dcb7bdca..2280656b0b45 100644
--- a/code/lib/blocks/src/examples/StoryParameters.stories.tsx
+++ b/code/lib/blocks/src/examples/StoryParameters.stories.tsx
@@ -1,4 +1,4 @@
-import type { Meta, StoryObj } from '@storybook/react';
+import type { Meta, StoryObj } from '@storybook/react-vite';
import { SimpleSizeTest } from './SimpleSizeTest';
diff --git a/code/lib/cli-storybook/src/autoblock/block-storystorev6.ts b/code/lib/cli-storybook/src/autoblock/block-storystorev6.ts
index 9d28b8d15a08..83cff982ef96 100644
--- a/code/lib/cli-storybook/src/autoblock/block-storystorev6.ts
+++ b/code/lib/cli-storybook/src/autoblock/block-storystorev6.ts
@@ -28,7 +28,7 @@ export const blocker = createBlocker({
In your Storybook configuration we found storyStoreV7 feature defined. For instance:
- export default = {
+ export default {
features: {
${picocolors.cyan(`storyStoreV7: false`)}, <--- ${picocolors.bold('remove this line')}
},
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/addon-a11y-addon-test.ts b/code/lib/cli-storybook/src/automigrate/fixes/addon-a11y-addon-test.ts
index 41d58bc46a7c..d54bd76733ae 100644
--- a/code/lib/cli-storybook/src/automigrate/fixes/addon-a11y-addon-test.ts
+++ b/code/lib/cli-storybook/src/automigrate/fixes/addon-a11y-addon-test.ts
@@ -8,7 +8,7 @@ import path from 'path';
import picocolors from 'picocolors';
import { dedent } from 'ts-dedent';
-// Relative path import to avoid dependency to @storybook/test
+// Relative path import to avoid dependency to storybook/test
import {
SUPPORTED_FRAMEWORKS,
SUPPORTED_RENDERERS,
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.test.ts b/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.test.ts
new file mode 100644
index 000000000000..a7f0c5cbee47
--- /dev/null
+++ b/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.test.ts
@@ -0,0 +1,298 @@
+import { readFile, writeFile } from 'node:fs/promises';
+import { join } from 'node:path';
+
+import { describe, expect, it, vi } from 'vitest';
+
+import { dedent } from 'ts-dedent';
+
+import {
+ consolidatedImports,
+ transformImportFiles,
+ transformPackageJsonFiles,
+} from './consolidated-imports';
+
+vi.mock('node:fs/promises');
+vi.mock('globby', () => ({
+ globby: vi.fn(),
+}));
+
+const mockPackageJson = {
+ dependencies: {
+ '@storybook/react': '^7.0.0',
+ '@storybook/core-common': '^7.0.0',
+ react: '^18.0.0',
+ },
+ devDependencies: {
+ '@storybook/addon-essentials': '^7.0.0',
+ '@storybook/manager-api': '^7.0.0',
+ typescript: '^5.0.0',
+ },
+};
+
+const mockRunOptions = {
+ packageManager: {
+ retrievePackageJson: async () => mockPackageJson,
+ } as any,
+ mainConfig: {} as any,
+ mainConfigPath: 'main.ts',
+ packageJson: mockPackageJson,
+};
+
+const setupGlobby = async (files: string[]) => {
+ // eslint-disable-next-line depend/ban-dependencies
+ const { globby } = await import('globby');
+ vi.mocked(globby).mockResolvedValueOnce(files);
+};
+
+const setupCheck = async (packageJsonContents: string, packageJsonFiles: string[]) => {
+ vi.mocked(readFile).mockImplementation(async (path: any) => {
+ const filePath = path.toString();
+ if (filePath.endsWith('package.json')) {
+ return packageJsonContents;
+ }
+ return '';
+ });
+ await setupGlobby(packageJsonFiles);
+
+ return consolidatedImports.check({
+ ...mockRunOptions,
+ storybookVersion: '8.0.0',
+ });
+};
+
+describe('check', () => {
+ it('should call globby with correct patterns for package.json files', async () => {
+ const filePath = 'test/package.json';
+ const contents = JSON.stringify(mockPackageJson);
+
+ await setupCheck(contents, [filePath]);
+
+ // eslint-disable-next-line depend/ban-dependencies
+ const { globby } = await import('globby');
+ expect(globby).toHaveBeenCalledWith(
+ ['**/package.json'],
+ expect.objectContaining({
+ ignore: ['**/node_modules/**'],
+ })
+ );
+ });
+
+ it('should detect consolidated packages in package.json', async () => {
+ const contents = JSON.stringify(mockPackageJson);
+ const filePath = 'test/package.json';
+
+ const result = await setupCheck(contents, [filePath]);
+ expect(result).toMatchObject({
+ packageJsonFiles: [filePath],
+ });
+ });
+
+ it('should not detect non-consolidated packages in package.json', async () => {
+ const packageJsonWithoutConsolidated = {
+ dependencies: {
+ react: '^18.0.0',
+ },
+ devDependencies: {
+ typescript: '^5.0.0',
+ },
+ };
+ const contents = JSON.stringify(packageJsonWithoutConsolidated);
+ const filePath = 'test/package.json';
+
+ const result = await setupCheck(contents, [filePath]);
+ expect(result).toBeNull();
+ });
+});
+
+describe('transformPackageJsonFiles', () => {
+ it('should transform package.json files', async () => {
+ const contents = JSON.stringify(mockPackageJson);
+ const filePath = 'test/package.json';
+
+ vi.mocked(readFile).mockResolvedValueOnce(contents);
+
+ const errors = await transformPackageJsonFiles([filePath], false);
+
+ expect(errors).toHaveLength(0);
+ expect(writeFile).toHaveBeenCalledWith(
+ filePath,
+ expect.not.stringContaining('"@storybook/core-common": "^8.0.0"')
+ );
+ });
+
+ it('should not write files in dry run mode', async () => {
+ const contents = JSON.stringify(mockPackageJson);
+ const filePath = 'test/package.json';
+
+ vi.mocked(readFile).mockResolvedValueOnce(contents);
+
+ const errors = await transformPackageJsonFiles([filePath], true);
+
+ expect(errors).toHaveLength(0);
+ expect(writeFile).not.toHaveBeenCalled();
+ });
+
+ it('should handle file read errors', async () => {
+ const filePath = 'test/package.json';
+ vi.mocked(readFile).mockRejectedValueOnce(new Error('Failed to read file'));
+
+ const errors = await transformPackageJsonFiles([filePath], false);
+
+ expect(errors).toHaveLength(1);
+ expect(errors[0]).toMatchObject({
+ file: filePath,
+ error: expect.any(Error),
+ });
+ });
+
+ it('should handle file write errors', async () => {
+ const contents = JSON.stringify(mockPackageJson);
+ const filePath = 'test/package.json';
+ vi.mocked(readFile).mockResolvedValueOnce(contents);
+ vi.mocked(writeFile).mockRejectedValueOnce(new Error('Failed to write file'));
+
+ const errors = await transformPackageJsonFiles([filePath], false);
+
+ expect(errors).toHaveLength(1);
+ expect(errors[0]).toMatchObject({
+ file: filePath,
+ error: expect.any(Error),
+ });
+ });
+});
+
+describe('transformImportFiles', () => {
+ it('should transform import declarations', async () => {
+ const sourceContents = dedent`
+ import { something } from '@storybook/components';
+ import { other } from '@storybook/core-common';
+ `;
+ const sourceFiles = [join('src', 'test.ts')];
+
+ vi.mocked(readFile).mockResolvedValueOnce(sourceContents);
+
+ const errors = await transformImportFiles(sourceFiles, false);
+
+ expect(errors).toHaveLength(0);
+ expect(writeFile).toHaveBeenCalledWith(
+ sourceFiles[0],
+ expect.stringContaining(`from 'storybook/internal/components'`)
+ );
+ });
+
+ it('should transform import declarations with sub-paths', async () => {
+ const sourceContents = dedent`
+ import { other } from '@storybook/theming/create';
+ `;
+ const sourceFiles = [join('src', 'test.ts')];
+
+ vi.mocked(readFile).mockResolvedValueOnce(sourceContents);
+
+ const errors = await transformImportFiles(sourceFiles, false);
+
+ expect(errors).toHaveLength(0);
+ expect(writeFile).toHaveBeenCalledWith(
+ sourceFiles[0],
+ expect.stringContaining(`from 'storybook/internal/theming/create'`)
+ );
+ });
+
+ it('should transform require calls', async () => {
+ const sourceContents = dedent`
+ const something = require('@storybook/components');
+ const other = require('@storybook/core-common');
+ `;
+ const sourceFiles = [join('src', 'test.ts')];
+
+ vi.mocked(readFile).mockResolvedValueOnce(sourceContents);
+
+ const errors = await transformImportFiles(sourceFiles, false);
+
+ expect(errors).toHaveLength(0);
+ expect(writeFile).toHaveBeenCalledWith(
+ sourceFiles[0],
+ expect.stringContaining(`require('storybook/internal/components')`)
+ );
+ });
+
+ it('should handle mixed import styles', async () => {
+ const sourceContents = dedent`
+ import { something } from '@storybook/components';
+ const other = require('@storybook/core-common');
+ `;
+ const sourceFiles = [join('src', 'test.ts')];
+
+ vi.mocked(readFile).mockResolvedValueOnce(sourceContents);
+
+ const errors = await transformImportFiles(sourceFiles, false);
+
+ expect(errors).toHaveLength(0);
+ expect(writeFile).toHaveBeenCalledWith(
+ sourceFiles[0],
+ expect.stringContaining(`from 'storybook/internal/components'`)
+ );
+ expect(writeFile).toHaveBeenCalledWith(
+ sourceFiles[0],
+ expect.stringContaining(`require('storybook/internal/common')`)
+ );
+ });
+
+ it('should not transform non-consolidated package imports', async () => {
+ const sourceContents = `
+ import { something } from '@storybook/other-package';
+ const other = require('some-other-package');
+ `;
+ const sourceFiles = [join('src', 'test.ts')];
+
+ vi.mocked(readFile).mockResolvedValueOnce(sourceContents);
+
+ const errors = await transformImportFiles(sourceFiles, false);
+
+ expect(errors).toHaveLength(0);
+ expect(writeFile).not.toHaveBeenCalledWith(sourceFiles[0], expect.any(String));
+ });
+
+ it('should not write files in dry run mode', async () => {
+ const sourceContents = dedent`
+ import { something } from '@storybook/components';
+ `;
+ const sourceFiles = [join('src', 'test.ts')];
+
+ vi.mocked(readFile).mockResolvedValueOnce(sourceContents);
+
+ const errors = await transformImportFiles(sourceFiles, true);
+
+ expect(errors).toHaveLength(0);
+ expect(writeFile).not.toHaveBeenCalled();
+ });
+
+ it('should handle file read errors', async () => {
+ const sourceFiles = [join('src', 'test.ts')];
+ vi.mocked(readFile).mockRejectedValueOnce(new Error('Failed to read file'));
+
+ const errors = await transformImportFiles(sourceFiles, false);
+
+ expect(errors).toHaveLength(1);
+ expect(errors[0]).toMatchObject({
+ file: sourceFiles[0],
+ error: expect.any(Error),
+ });
+ });
+
+ it('should handle file write errors', async () => {
+ const sourceContents = dedent`
+ import { something } from '@storybook/components';
+ `;
+ const sourceFiles = [join('src', 'test.ts')];
+ vi.mocked(readFile).mockResolvedValueOnce(sourceContents);
+ vi.mocked(writeFile).mockRejectedValueOnce(new Error('Failed to write file'));
+
+ const errors = await transformImportFiles(sourceFiles, false);
+
+ expect(errors).toHaveLength(1);
+ expect(errors[0]).toMatchObject({
+ file: sourceFiles[0],
+ error: expect.any(Error),
+ });
+ });
+});
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.ts b/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.ts
new file mode 100644
index 000000000000..103911b39967
--- /dev/null
+++ b/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.ts
@@ -0,0 +1,203 @@
+import { readFile, writeFile } from 'node:fs/promises';
+
+import { commonGlobOptions, getProjectRoot } from 'storybook/internal/common';
+
+import prompts from 'prompts';
+import { dedent } from 'ts-dedent';
+
+import { consolidatedPackages } from '../helpers/consolidated-packages';
+import type { Fix, RunOptions } from '../types';
+
+export interface ConsolidatedOptions {
+ packageJsonFiles: string[];
+}
+
+function transformPackageJson(content: string): string | null {
+ const packageJson = JSON.parse(content);
+ let hasChanges = false;
+
+ // Check dependencies
+ if (packageJson.dependencies) {
+ for (const [dep, version] of Object.entries(packageJson.dependencies)) {
+ if (dep in consolidatedPackages) {
+ delete packageJson.dependencies[dep];
+ hasChanges = true;
+ }
+ }
+ }
+
+ // Check devDependencies
+ if (packageJson.devDependencies) {
+ for (const [dep, version] of Object.entries(packageJson.devDependencies)) {
+ if (dep in consolidatedPackages) {
+ delete packageJson.devDependencies[dep];
+ hasChanges = true;
+ }
+ }
+ }
+
+ return hasChanges ? JSON.stringify(packageJson, null, 2) : null;
+}
+
+function transformImports(source: string) {
+ let hasChanges = false;
+ let transformed = source;
+
+ for (const [from, to] of Object.entries(consolidatedPackages)) {
+ // Match the package name when it's inside either single or double quotes
+ const regex = new RegExp(`(['"])${from}(.*)\\1`, 'g');
+ if (regex.test(transformed)) {
+ transformed = transformed.replace(regex, `$1${to}$2$1`);
+ hasChanges = true;
+ }
+ }
+
+ return hasChanges ? transformed : null;
+}
+
+export const transformPackageJsonFiles = async (files: string[], dryRun: boolean) => {
+ const errors: Array<{ file: string; error: Error }> = [];
+
+ const { default: pLimit } = await import('p-limit');
+
+ const limit = pLimit(10);
+
+ await Promise.all(
+ files.map((file) =>
+ limit(async () => {
+ try {
+ const contents = await readFile(file, 'utf-8');
+ const transformed = transformPackageJson(contents);
+ if (!dryRun && transformed) {
+ await writeFile(file, transformed);
+ }
+ } catch (error) {
+ errors.push({ file, error: error as Error });
+ }
+ })
+ )
+ );
+
+ return errors;
+};
+
+export const transformImportFiles = async (files: string[], dryRun: boolean) => {
+ const errors: Array<{ file: string; error: Error }> = [];
+ const { default: pLimit } = await import('p-limit');
+ const limit = pLimit(10);
+
+ await Promise.all(
+ files.map((file) =>
+ limit(async () => {
+ try {
+ const contents = await readFile(file, 'utf-8');
+ const transformed = transformImports(contents);
+ if (!dryRun && transformed) {
+ await writeFile(file, transformed);
+ }
+ } catch (error) {
+ errors.push({ file, error: error as Error });
+ }
+ })
+ )
+ );
+
+ return errors;
+};
+
+export const consolidatedImports: Fix = {
+ id: 'consolidated-imports',
+ versionRange: ['^8.0.0', '^9.0.0-0'],
+ check: async () => {
+ const projectRoot = getProjectRoot();
+ // eslint-disable-next-line depend/ban-dependencies
+ const globby = (await import('globby')).globby;
+
+ const packageJsonFiles = await globby(['**/package.json'], {
+ ...commonGlobOptions(''),
+ ignore: ['**/node_modules/**'],
+ cwd: projectRoot,
+ gitignore: true,
+ });
+
+ // check if any of the package.json files have consolidated packages
+ const hasConsolidatedDependencies = await Promise.all(
+ packageJsonFiles.map(async (file) => {
+ const contents = await readFile(file, 'utf-8');
+ const packageJson = JSON.parse(contents);
+ return (
+ Object.keys(packageJson.dependencies || {}).some((dep) => dep in consolidatedPackages) ||
+ Object.keys(packageJson.devDependencies || {}).some((dep) => dep in consolidatedPackages)
+ );
+ })
+ ).then((results) => results.some(Boolean));
+
+ if (!hasConsolidatedDependencies) {
+ return null;
+ }
+ return {
+ packageJsonFiles,
+ };
+ },
+ prompt: (result: ConsolidatedOptions) => {
+ return dedent`
+ Found package.json files that contain consolidated Storybook packages that need to be updated:
+ ${result.packageJsonFiles.map((file) => `- ${file}`).join('\n')}
+
+ These packages have been consolidated into the main storybook package and should be removed.
+ The main storybook package will be added to devDependencies if not already present.
+
+ Would you like to:
+ 1. Update these package.json files
+ 2. Scan your codebase and update any imports from these consolidated packages
+
+ This will ensure your project is properly updated to use the new consolidated package structure.
+ `;
+ },
+ run: async (options: RunOptions) => {
+ const { result, dryRun = false } = options;
+ const { packageJsonFiles } = result;
+
+ const errors: Array<{ file: string; error: Error }> = [];
+
+ const packageJsonErrors = await transformPackageJsonFiles(packageJsonFiles, dryRun);
+ errors.push(...packageJsonErrors);
+
+ const projectRoot = getProjectRoot();
+
+ const defaultGlob = '**/*.{mjs,cjs,js,jsx,ts,tsx}';
+ // Find all files matching the glob pattern
+ const { glob } = await prompts({
+ type: 'text',
+ name: 'glob',
+ message: 'Enter a custom glob pattern to scan (or press enter to use default):',
+ initial: defaultGlob,
+ });
+
+ // eslint-disable-next-line depend/ban-dependencies
+ const globby = (await import('globby')).globby;
+
+ const sourceFiles = await globby([glob], {
+ ...commonGlobOptions(''),
+ ignore: ['**/node_modules/**'],
+ dot: true,
+ cwd: projectRoot,
+ });
+
+ const importErrors = await transformImportFiles(sourceFiles, dryRun);
+ errors.push(...importErrors);
+
+ if (errors.length > 0) {
+ // eslint-disable-next-line local-rules/no-uncategorized-errors
+ throw new Error(
+ `Failed to process ${errors.length} files:\n${errors
+ .map(({ file, error }) => `- ${file}: ${error.message}`)
+ .join('\n')}`
+ );
+ }
+
+ if (!dryRun && result.packageJsonFiles.length > 0) {
+ await options.packageManager.installDependencies();
+ }
+ },
+};
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/index.ts b/code/lib/cli-storybook/src/automigrate/fixes/index.ts
index 60f009ee14b4..87f11b336902 100644
--- a/code/lib/cli-storybook/src/automigrate/fixes/index.ts
+++ b/code/lib/cli-storybook/src/automigrate/fixes/index.ts
@@ -9,19 +9,18 @@ import { angularBuildersMultiproject } from './angular-builders-multiproject';
import { autodocsTags } from './autodocs-tags';
import { autodocsTrue } from './autodocs-true';
import { builderVite } from './builder-vite';
+import { consolidatedImports } from './consolidated-imports';
import { cra5 } from './cra5';
import { eslintPlugin } from './eslint-plugin';
import { initialGlobals } from './initial-globals';
import { mdx1to3 } from './mdx-1-to-3';
import { mdxgfm } from './mdx-gfm';
import { mdxToCSF } from './mdx-to-csf';
-import { missingStorybookDependencies } from './missing-storybook-dependencies';
import { newFrameworks } from './new-frameworks';
import { removeReactDependency } from './prompt-remove-react';
import { reactDocgen } from './react-docgen';
import { removeArgtypesRegex } from './remove-argtypes-regex';
import { removedGlobalClientAPIs } from './remove-global-client-apis';
-import { removeJestTestingLibrary } from './remove-jest-testing-library';
import { removeLegacyMDX1 } from './remove-legacymdx1';
import { sbBinary } from './sb-binary';
import { sbScripts } from './sb-scripts';
@@ -37,7 +36,6 @@ import { wrapRequire } from './wrap-require';
export * from '../types';
export const allFixes: Fix[] = [
- missingStorybookDependencies,
addonsAPI,
newFrameworks,
cra5,
@@ -49,7 +47,6 @@ export const allFixes: Fix[] = [
builderVite,
sbBinary,
sbScripts,
- removeJestTestingLibrary,
removeArgtypesRegex,
removedGlobalClientAPIs,
mdxgfm,
@@ -69,6 +66,7 @@ export const allFixes: Fix[] = [
autodocsTags,
initialGlobals,
addonA11yAddonTest,
+ consolidatedImports,
addonExperimentalTest,
];
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.test.ts b/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.test.ts
deleted file mode 100644
index 3663cf3f0bdc..000000000000
--- a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.test.ts
+++ /dev/null
@@ -1,130 +0,0 @@
-import { describe, expect, it, vi } from 'vitest';
-
-import type { JsPackageManager } from 'storybook/internal/common';
-
-import stripAnsi from 'strip-ansi';
-
-import { missingStorybookDependencies } from './missing-storybook-dependencies';
-
-vi.mock('globby', () => ({
- __esModule: true,
- globby: vi.fn().mockResolvedValue(['.storybook/manager.ts', 'path/to/file.stories.tsx']),
-}));
-
-vi.mock('node:fs/promises', async (importOriginal) => {
- const original = (await importOriginal()) as typeof import('node:fs/promises');
- return {
- ...original,
- readFile: vi.fn().mockResolvedValue(`
- // these are NOT installed, will be reported
- import { someFunction } from '@storybook/preview-api';
- import { anotherFunction } from '@storybook/manager-api';
- import { SomeError } from '@storybook/core-events/server-errors';
- // this IS installed, will not be reported
- import { yetAnotherFunction } from '@storybook/theming';
- `),
- };
-});
-
-vi.mock('../../helpers', () => ({
- getStorybookVersionSpecifier: vi.fn().mockReturnValue('^8.1.10'),
-}));
-
-const check = async ({
- packageManager,
- storybookVersion = '8.1.10',
-}: {
- packageManager: JsPackageManager;
- storybookVersion?: string;
-}) => {
- return missingStorybookDependencies.check({
- packageManager,
- mainConfig: {} as any,
- storybookVersion,
- });
-};
-
-describe('missingStorybookDependencies', () => {
- const mockPackageManager = {
- findInstallations: vi.fn().mockResolvedValue({
- dependencies: {
- '@storybook/react': '8.1.0',
- '@storybook/theming': '8.1.0',
- },
- }),
- retrievePackageJson: vi.fn().mockResolvedValue({
- dependencies: {
- storybook: '8.1.0',
- },
- }),
- addDependencies: vi.fn().mockResolvedValue(undefined),
- } as Partial;
-
- describe('check function', () => {
- it('should identify missing dependencies', async () => {
- const result = await check({
- packageManager: mockPackageManager as JsPackageManager,
- });
-
- expect(Object.keys(result!.packageUsage)).not.includes('@storybook/theming');
- expect(result).toEqual({
- packageUsage: {
- '@storybook/preview-api': ['.storybook/manager.ts', 'path/to/file.stories.tsx'],
- '@storybook/manager-api': ['.storybook/manager.ts', 'path/to/file.stories.tsx'],
- '@storybook/core-events': ['.storybook/manager.ts', 'path/to/file.stories.tsx'],
- },
- });
- });
- });
-
- describe('prompt function', () => {
- it('should provide a proper message with the missing dependencies', () => {
- const packageUsage = {
- '@storybook/preview-api': ['.storybook/manager.ts'],
- '@storybook/manager-api': ['path/to/file.stories.tsx'],
- };
-
- const message = missingStorybookDependencies.prompt({ packageUsage });
-
- expect(stripAnsi(message)).toMatchInlineSnapshot(`
- "Found the following Storybook packages used in your project, but they are missing from your project dependencies:
- - @storybook/manager-api: (1 file)
- - @storybook/preview-api: (1 file)
-
- Referencing missing packages can cause your project to crash. We can automatically add them to your dependencies.
-
- More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#failed-to-resolve-import-storybookx-error"
- `);
- });
- });
-
- describe('run function', () => {
- it('should add missing dependencies', async () => {
- const dryRun = false;
- const packageUsage = {
- '@storybook/preview-api': ['.storybook/manager.ts'],
- '@storybook/manager-api': ['path/to/file.stories.tsx'],
- };
-
- await missingStorybookDependencies.run!({
- result: { packageUsage },
- dryRun,
- packageJson: {},
- mainConfig: { stories: [] },
- packageManager: mockPackageManager as JsPackageManager,
- mainConfigPath: 'path/to/main-config.js',
- });
-
- expect(mockPackageManager.addDependencies).toHaveBeenNthCalledWith(
- 1,
- { installAsDevDependencies: true },
- ['@storybook/preview-api@8.1.0', '@storybook/manager-api@8.1.0']
- );
- expect(mockPackageManager.addDependencies).toHaveBeenNthCalledWith(
- 2,
- { installAsDevDependencies: true, skipInstall: true, packageJson: expect.anything() },
- ['@storybook/preview-api@8.1.0', '@storybook/manager-api@8.1.0']
- );
- });
- });
-});
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts b/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts
deleted file mode 100644
index 7e36f4750284..000000000000
--- a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-import { readFile } from 'node:fs/promises';
-
-import { getStorybookVersionSpecifier } from 'storybook/internal/cli';
-import type { InstallationMetadata, JsPackageManager } from 'storybook/internal/common';
-
-import picocolors from 'picocolors';
-import { dedent } from 'ts-dedent';
-
-import type { Fix } from '../types';
-
-const logger = console;
-
-type PackageUsage = Record;
-
-interface MissingStorybookDependenciesOptions {
- packageUsage: PackageUsage;
-}
-
-const consolidatedPackages = [
- '@storybook/channels',
- '@storybook/client-logger',
- '@storybook/core-common',
- '@storybook/core-events',
- '@storybook/csf-tools',
- '@storybook/docs-tools',
- '@storybook/node-logger',
- '@storybook/preview-api',
- '@storybook/router',
- '@storybook/telemetry',
- '@storybook/theming',
- '@storybook/types',
- '@storybook/manager-api',
- '@storybook/manager',
- '@storybook/preview',
- '@storybook/core-server',
- '@storybook/builder-manager',
- '@storybook/components',
-];
-
-async function checkInstallations(
- packageManager: JsPackageManager,
- packages: string[]
-): Promise {
- let result: Record = {};
-
- // go through each package and get installation info at depth 0 to make sure
- // the dependency is directly installed, else they could come from other dependencies
- const promises = packages.map((pkg) => packageManager.findInstallations([pkg], { depth: 0 }));
-
- const analyses = await Promise.all(promises);
-
- analyses.forEach((analysis) => {
- if (analysis?.dependencies) {
- result = {
- ...result,
- ...analysis.dependencies,
- };
- }
- });
-
- return result;
-}
-
-/** Find usage of Storybook packages in the project files which are not present in the dependencies. */
-export const missingStorybookDependencies: Fix = {
- id: 'missingStorybookDependencies',
- promptType: 'auto',
- versionRange: ['<8.2', '>=8.2'],
-
- async check({ packageManager }) {
- // Dynamically import globby because it is a pure ESM module
- // eslint-disable-next-line depend/ban-dependencies
- const { globby } = await import('globby');
-
- const result = await checkInstallations(packageManager, consolidatedPackages);
- if (!result) {
- return null;
- }
-
- const installedDependencies = Object.keys(result).sort();
- const dependenciesToCheck = consolidatedPackages.filter(
- (pkg) => !installedDependencies.includes(pkg)
- );
-
- const patterns = ['**/.storybook/*', '**/*.stories.*', '**/*.story.*'];
-
- const files = await globby(patterns, {
- ignore: ['**/node_modules/**'],
- });
- const packageUsage: PackageUsage = {};
-
- for (const file of files) {
- const content = await readFile(file, 'utf-8');
- dependenciesToCheck.forEach((pkg) => {
- // match imports like @storybook/theming or @storybook/theming/create
- const regex = new RegExp(`['"]${pkg}(/[^'"]*)?['"]`);
- if (regex.test(content)) {
- if (!packageUsage[pkg]) {
- packageUsage[pkg] = [];
- }
- packageUsage[pkg].push(file);
- }
- });
- }
-
- return Object.keys(packageUsage).length > 0 ? { packageUsage } : null;
- },
-
- prompt({ packageUsage }) {
- return dedent`
- Found the following Storybook packages used in your project, but they are missing from your project dependencies:
- ${Object.entries(packageUsage)
- .map(
- ([pkg, files]) =>
- `- ${picocolors.cyan(pkg)}: (${files.length} ${files.length === 1 ? 'file' : 'files'})`
- )
- .sort()
- .join('\n')}
-
- Referencing missing packages can cause your project to crash. We can automatically add them to your dependencies.
-
- More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#failed-to-resolve-import-storybookx-error
- `;
- },
-
- async run({ result: { packageUsage }, dryRun, packageManager }) {
- logger.info(
- `✅ Installing the following packages as devDependencies: ${Object.keys(packageUsage)}`
- );
- if (!dryRun) {
- console.log(packageManager.retrievePackageJson());
- const dependenciesToInstall = Object.keys(packageUsage);
- const versionToInstall = getStorybookVersionSpecifier(
- await packageManager.retrievePackageJson()
- );
-
- const versionToInstallWithoutModifiers = versionToInstall?.replace(/[\^~]/, '');
-
- /**
- * WORKAROUND: necessary for the following scenario: Storybook latest is currently at 8.2.2
- * User has all Storybook deps at ^8.2.1 We run e.g. npm install with the dependency@^8.2.1
- * The package.json will have ^8.2.1 but install 8.2.2 So we first install the exact version,
- * then run code again to write to package.json to add the caret back, but without running
- * install
- */
- await packageManager.addDependencies(
- { installAsDevDependencies: true },
- dependenciesToInstall.map((pkg) => `${pkg}@${versionToInstallWithoutModifiers}`)
- );
- const packageJson = await packageManager.retrievePackageJson();
- await packageManager.addDependencies(
- { installAsDevDependencies: true, skipInstall: true, packageJson },
- dependenciesToInstall.map((pkg) => `${pkg}@${versionToInstall}`)
- );
- }
- },
-};
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.test.ts b/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.test.ts
deleted file mode 100644
index 80e5e4989bad..000000000000
--- a/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.test.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { expect, it } from 'vitest';
-
-import type { JsPackageManager } from 'storybook/internal/common';
-import type { StorybookConfig } from 'storybook/internal/types';
-
-import ansiRegex from 'ansi-regex';
-
-import { removeJestTestingLibrary } from './remove-jest-testing-library';
-
-const check = async ({
- packageManager,
- main: mainConfig = {},
- storybookVersion = '8.0.0',
-}: {
- packageManager: Partial;
- main?: Partial & Record;
- storybookVersion?: string;
-}) => {
- return removeJestTestingLibrary.check({
- packageManager: packageManager as any,
- configDir: '',
- mainConfig: mainConfig as any,
- storybookVersion,
- });
-};
-
-it('should prompt to install the test package and run the codemod', async () => {
- const options = await check({
- packageManager: {
- getAllDependencies: async () => ({
- '@storybook/jest': '1.0.0',
- '@storybook/testing-library': '1.0.0',
- }),
- },
- main: { addons: ['@storybook/essentials', '@storybook/addon-info'] },
- });
-
- expect(options).toMatchInlineSnapshot(`
- {
- "incompatiblePackages": [
- "@storybook/jest",
- "@storybook/testing-library",
- ],
- }
- `);
-
- expect.addSnapshotSerializer({
- serialize: (value) => {
- const stringVal = typeof value === 'string' ? value : value.toString();
- return stringVal.replace(ansiRegex(), '');
- },
- test: () => true,
- });
-
- expect(await removeJestTestingLibrary.prompt(options!)).toMatchInlineSnapshot(`
- Attention: We've detected that you're using the following packages which are known to be incompatible since Storybook 8:
-
- - @storybook/jest
- - @storybook/testing-library
-
- We will uninstall them for you and install @storybook/test instead.
-
- Also, we can help you migrate your stories to use the new package.
- `);
-});
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.ts b/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.ts
deleted file mode 100644
index b7de9df0afc6..000000000000
--- a/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { getStorybookVersionSpecifier } from 'storybook/internal/cli';
-
-import { runCodemod } from '@storybook/codemod';
-
-import picocolors from 'picocolors';
-import prompts from 'prompts';
-import { dedent } from 'ts-dedent';
-
-import type { Fix } from '../types';
-
-const logger = console;
-
-export const removeJestTestingLibrary: Fix<{ incompatiblePackages: string[] }> = {
- id: 'remove-jest-testing-library',
- versionRange: ['<8.0.0-alpha.0', '>=8.0.0-alpha.0'],
- promptType: 'auto',
- async check({ packageManager }) {
- const deps = await packageManager.getAllDependencies();
-
- const incompatiblePackages = Object.keys(deps).filter(
- (it) => it === '@storybook/jest' || it === '@storybook/testing-library'
- );
- return incompatiblePackages.length ? { incompatiblePackages } : null;
- },
- prompt({ incompatiblePackages }) {
- return dedent`
- ${picocolors.bold(
- 'Attention'
- )}: We've detected that you're using the following packages which are known to be incompatible since Storybook 8:
-
- ${incompatiblePackages.map((name) => `- ${picocolors.cyan(`${name}`)}`).join('\n')}
-
- We will uninstall them for you and install ${picocolors.cyan('@storybook/test')} instead.
-
- Also, we can help you migrate your stories to use the new package.
- `;
- },
- async run({ packageManager, dryRun }) {
- if (!dryRun) {
- const packageJson = await packageManager.retrievePackageJson();
-
- await packageManager.removeDependencies({ skipInstall: true, packageJson }, [
- '@storybook/jest',
- '@storybook/testing-library',
- ]);
-
- const versionToInstall = getStorybookVersionSpecifier(packageJson);
-
- await packageManager.addDependencies({ installAsDevDependencies: true, packageJson }, [
- `@storybook/test@${versionToInstall}`,
- ]);
-
- const { glob: globString } = await prompts({
- type: 'text',
- name: 'glob',
- message: 'Please enter the glob for your stories to migrate to @storybook/test',
- initial: './src/**/*.stories.*',
- });
-
- if (globString) {
- await runCodemod('migrate-to-test-package', { glob: globString, dryRun, logger });
- }
- }
- },
-};
diff --git a/code/lib/cli-storybook/src/automigrate/helpers/consolidated-packages.ts b/code/lib/cli-storybook/src/automigrate/helpers/consolidated-packages.ts
new file mode 100644
index 000000000000..4880dad9498d
--- /dev/null
+++ b/code/lib/cli-storybook/src/automigrate/helpers/consolidated-packages.ts
@@ -0,0 +1,27 @@
+/**
+ * Consolidated packages are packages that have been merged into the main storybook package. This
+ * object maps the old package name to the new package name.
+ */
+export const consolidatedPackages = {
+ '@storybook/channels': 'storybook/internal/channels',
+ '@storybook/client-logger': 'storybook/internal/client-logger',
+ '@storybook/core-common': 'storybook/internal/common',
+ '@storybook/core-events': 'storybook/internal/core-events',
+ '@storybook/csf-tools': 'storybook/internal/csf-tools',
+ '@storybook/docs-tools': 'storybook/internal/docs-tools',
+ '@storybook/node-logger': 'storybook/internal/node-logger',
+ '@storybook/preview-api': 'storybook/internal/preview-api',
+ '@storybook/router': 'storybook/internal/router',
+ '@storybook/telemetry': 'storybook/internal/telemetry',
+ '@storybook/theming': 'storybook/internal/theming',
+ '@storybook/types': 'storybook/internal/types',
+ '@storybook/manager-api': 'storybook/internal/manager-api',
+ '@storybook/manager': 'storybook/internal/manager',
+ '@storybook/preview': 'storybook/internal/preview',
+ '@storybook/core-server': 'storybook/internal/core-server',
+ '@storybook/builder-manager': 'storybook/internal/builder-manager',
+ '@storybook/components': 'storybook/internal/components',
+ '@storybook/test': 'storybook/test',
+} as const;
+
+export type ConsolidatedPackage = keyof typeof consolidatedPackages;
diff --git a/code/lib/cli-storybook/src/sandbox-templates.ts b/code/lib/cli-storybook/src/sandbox-templates.ts
index d6000075ca04..3177a9820821 100644
--- a/code/lib/cli-storybook/src/sandbox-templates.ts
+++ b/code/lib/cli-storybook/src/sandbox-templates.ts
@@ -499,6 +499,9 @@ export const baseTemplates = {
renderer: '@storybook/angular',
builder: '@storybook/builder-webpack5',
},
+ modifications: {
+ extraDependencies: ['@angular-devkit/build-angular@next'],
+ },
skipTasks: ['e2e-tests-dev', 'bench', 'vitest-integration'],
},
'angular-cli/default-ts': {
diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json
index fe3b1f62ef45..917b3738f2cf 100644
--- a/code/lib/codemod/package.json
+++ b/code/lib/codemod/package.json
@@ -32,7 +32,6 @@
"./dist/transforms/find-implicit-spies.js": "./dist/transforms/find-implicit-spies.js",
"./dist/transforms/move-builtin-addons.js": "./dist/transforms/move-builtin-addons.js",
"./dist/transforms/mdx-to-csf.js": "./dist/transforms/mdx-to-csf.js",
- "./dist/transforms/migrate-to-test-package.js": "./dist/transforms/migrate-to-test-package.js",
"./dist/transforms/storiesof-to-csf.js": "./dist/transforms/storiesof-to-csf.js",
"./dist/transforms/update-addon-info.js": "./dist/transforms/update-addon-info.js",
"./dist/transforms/update-organisation-name.js": "./dist/transforms/update-organisation-name.js",
@@ -95,7 +94,6 @@
"./src/transforms/csf-hoist-story-annotations.js",
"./src/transforms/find-implicit-spies.ts",
"./src/transforms/add-component-parameters.js",
- "./src/transforms/migrate-to-test-package.ts",
"./src/transforms/move-builtin-addons.js",
"./src/transforms/update-addon-info.js",
"./src/transforms/update-organisation-name.js",
diff --git a/code/lib/codemod/src/transforms/__tests__/migrate-to-test-package.test.ts b/code/lib/codemod/src/transforms/__tests__/migrate-to-test-package.test.ts
deleted file mode 100644
index e3c2b2e517fa..000000000000
--- a/code/lib/codemod/src/transforms/__tests__/migrate-to-test-package.test.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { expect, test } from 'vitest';
-
-import { dedent } from 'ts-dedent';
-
-import transform from '../migrate-to-test-package';
-
-expect.addSnapshotSerializer({
- serialize: (val: any) => (typeof val === 'string' ? val : val.toString()),
- test: () => true,
-});
-
-const tsTransform = async (source: string) =>
- (await transform({ source, path: 'Component.stories.tsx' })).trim();
-
-test('replace jest and testing-library with the test package', async () => {
- const input = dedent`
- import { expect } from '@storybook/jest';
- import { within, userEvent } from '@storybook/testing-library';
- `;
-
- expect(await tsTransform(input)).toMatchInlineSnapshot(`
- import { expect } from '@storybook/test';
- import { userEvent, within } from '@storybook/test';
- `);
-});
-
-test('Make jest imports namespace imports', async () => {
- const input = dedent`
- import { expect, jest } from '@storybook/jest';
- import { within, userEvent } from '@storybook/testing-library';
-
- const onFocusMock = jest.fn();
- const onSearchMock = jest.fn();
-
- jest.spyOn(window, 'Something');
- `;
-
- expect(await tsTransform(input)).toMatchInlineSnapshot(`
- import { expect } from '@storybook/test';
- import * as test from '@storybook/test';
- import { userEvent, within } from '@storybook/test';
-
- const onFocusMock = test.fn();
- const onSearchMock = test.fn();
-
- test.spyOn(window, 'Something');
- `);
-});
diff --git a/code/lib/codemod/src/transforms/migrate-to-test-package.ts b/code/lib/codemod/src/transforms/migrate-to-test-package.ts
deleted file mode 100644
index 9fffa57f7ad6..000000000000
--- a/code/lib/codemod/src/transforms/migrate-to-test-package.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-/* eslint-disable no-underscore-dangle */
-import { type BabelFile, core as babel, types as t } from 'storybook/internal/babel';
-import { loadCsf, printCsf } from 'storybook/internal/csf-tools';
-
-import type { FileInfo } from 'jscodeshift';
-import prettier from 'prettier';
-
-export default async function transform(info: FileInfo) {
- const csf = loadCsf(info.source, { makeTitle: (title) => title });
- const fileNode = csf._ast;
- // @ts-expect-error File is not yet exposed, see https://github.com/babel/babel/issues/11350#issuecomment-644118606
- const file: BabelFile = new babel.File(
- { filename: info.path },
- { code: info.source, ast: fileNode }
- );
-
- file.path.traverse({
- ImportDeclaration: (path) => {
- if (
- path.node.source.value === '@storybook/jest' ||
- path.node.source.value === '@storybook/testing-library'
- ) {
- if (path.node.source.value === '@storybook/jest') {
- path.get('specifiers').forEach((specifier) => {
- if (specifier.isImportSpecifier()) {
- const imported = specifier.get('imported');
-
- if (!imported.isIdentifier()) {
- return;
- }
- if (imported.node.name === 'jest') {
- specifier.remove();
- path.insertAfter(
- t.importDeclaration(
- [t.importNamespaceSpecifier(t.identifier('test'))],
- t.stringLiteral('@storybook/test')
- )
- );
- }
- }
- });
- }
- path.get('source').replaceWith(t.stringLiteral('@storybook/test'));
- }
- },
- Identifier: (path) => {
- if (path.node.name === 'jest') {
- path.replaceWith(t.identifier('test'));
- }
- },
- });
-
- let output = printCsf(csf).code;
- try {
- output = await prettier.format(output, {
- ...(await prettier.resolveConfig(info.path)),
- filepath: info.path,
- });
- } catch (e) {
- console.warn(`Failed applying prettier to ${info.path}.`);
- }
- return output;
-}
-
-export const parser = 'tsx';
diff --git a/code/lib/create-storybook/src/generators/ANGULAR/index.ts b/code/lib/create-storybook/src/generators/ANGULAR/index.ts
index dfea1b03b318..1fa1bc2c53a1 100644
--- a/code/lib/create-storybook/src/generators/ANGULAR/index.ts
+++ b/code/lib/create-storybook/src/generators/ANGULAR/index.ts
@@ -73,7 +73,10 @@ const generator: Generator<{ projectName: string }> = async (
'angular',
{
extraAddons: [`@storybook/addon-onboarding`],
- ...(useCompodoc && { extraPackages: ['@compodoc/compodoc', '@storybook/addon-docs'] }),
+ extraPackages: [
+ '@angular-devkit/build-angular',
+ ...(useCompodoc ? ['@compodoc/compodoc', '@storybook/addon-docs'] : []),
+ ],
addScripts: false,
componentsDestinationPath: root ? `${root}/src/stories` : undefined,
storybookConfigFolder: storybookFolder,
diff --git a/code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts b/code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts
index 13d50bfb347e..bfe983ab5515 100644
--- a/code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts
+++ b/code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts
@@ -56,7 +56,7 @@ const generator: Generator = async (packageManager, npmOptions, options) => {
await copyTemplateFiles({
packageManager: packageManager as any,
- renderer: 'react-native',
+ templateLocation: 'react-native',
// this value for language is not used since we only ship the ts template. This means we just fallback to @storybook/react-native/template/cli.
language: SupportedLanguage.TYPESCRIPT_4_9,
destination: storybookConfigFolder,
diff --git a/code/lib/create-storybook/src/generators/baseGenerator.ts b/code/lib/create-storybook/src/generators/baseGenerator.ts
index 6f842d59e253..9d332674c68a 100644
--- a/code/lib/create-storybook/src/generators/baseGenerator.ts
+++ b/code/lib/create-storybook/src/generators/baseGenerator.ts
@@ -224,6 +224,7 @@ export async function baseGenerator(
ProjectType.SVELTE,
ProjectType.SVELTEKIT,
ProjectType.WEB_COMPONENTS,
+ ProjectType.REACT_NATIVE_WEB,
];
const supportsTestAddon =
projectType === ProjectType.NEXTJS ||
@@ -296,7 +297,6 @@ export async function baseGenerator(
const addonPackages = [
'@storybook/addon-essentials',
'@storybook/blocks',
- '@storybook/test',
...(compiler ? [`@storybook/addon-webpack5-compiler-${compiler}`] : []),
...extraAddonsToInstall,
].filter(Boolean);
@@ -448,7 +448,7 @@ export async function baseGenerator(
throw new Error(`Could not find template location for ${framework} or ${rendererId}`);
}
await copyTemplateFiles({
- renderer: templateLocation,
+ templateLocation,
packageManager: packageManager as any,
language,
destination: componentsDestinationPath,
diff --git a/code/lib/create-storybook/src/scaffold-new-project.ts b/code/lib/create-storybook/src/scaffold-new-project.ts
index cfbf63c41fe9..d86414b23aae 100644
--- a/code/lib/create-storybook/src/scaffold-new-project.ts
+++ b/code/lib/create-storybook/src/scaffold-new-project.ts
@@ -45,10 +45,10 @@ const SUPPORTED_PROJECTS: Record = {
language: 'TS',
},
createScript: {
- npm: 'npm create next-app@^14 . -- --typescript --use-npm --eslint --tailwind --no-app --import-alias="@/*" --src-dir',
+ npm: 'npm create next-app . -- --turbopack --typescript --use-npm --eslint --tailwind --no-app --import-alias="@/*" --src-dir',
// yarn doesn't support version ranges, so we have to use npx
- yarn: 'npx create-next-app@^14 . --typescript --use-yarn --eslint --tailwind --no-app --import-alias="@/*" --src-dir',
- pnpm: 'pnpm create next-app@^14 . --typescript --use-pnpm --eslint --tailwind --no-app --import-alias="@/*" --src-dir',
+ yarn: 'npx create-next-app . --turbopack --typescript --use-yarn --eslint --tailwind --no-app --import-alias="@/*" --src-dir',
+ pnpm: 'pnpm create next-app . --turbopack --typescript --use-pnpm --eslint --tailwind --no-app --import-alias="@/*" --src-dir',
},
},
'vue-vite-ts': {
diff --git a/code/lib/test/package.json b/code/lib/test/package.json
deleted file mode 100644
index 5082b1881b26..000000000000
--- a/code/lib/test/package.json
+++ /dev/null
@@ -1,84 +0,0 @@
-{
- "name": "@storybook/test",
- "version": "9.0.0-alpha.2",
- "description": "",
- "keywords": [
- "storybook"
- ],
- "homepage": "https://github.com/storybookjs/storybook/tree/next/code/lib/test",
- "bugs": {
- "url": "https://github.com/storybookjs/storybook/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/storybookjs/storybook.git",
- "directory": "code/lib/test"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "license": "MIT",
- "sideEffects": true,
- "exports": {
- ".": {
- "types": "./dist/index.d.ts",
- "node": "./dist/index.js",
- "import": "./dist/index.mjs",
- "require": "./dist/index.js"
- },
- "./package.json": "./package.json"
- },
- "main": "dist/index.js",
- "module": "dist/index.mjs",
- "types": "dist/index.d.ts",
- "files": [
- "dist/**/*",
- "README.md",
- "*.js",
- "*.d.ts"
- ],
- "scripts": {
- "check": "jiti ../../../scripts/prepare/check.ts",
- "prep": "jiti ../../../scripts/prepare/bundle.ts"
- },
- "dependencies": {
- "@storybook/global": "^5.0.0",
- "@testing-library/dom": "10.4.0",
- "@testing-library/jest-dom": "6.5.0",
- "@testing-library/user-event": "14.5.2",
- "@vitest/expect": "2.0.5",
- "@vitest/spy": "2.0.5"
- },
- "devDependencies": {
- "chai": "^5.1.1",
- "tinyspy": "^3.0.0",
- "ts-dedent": "^2.2.0",
- "type-fest": "~2.19",
- "typescript": "^5.7.3"
- },
- "peerDependencies": {
- "storybook": "workspace:^"
- },
- "publishConfig": {
- "access": "public"
- },
- "bundler": {
- "entries": [
- "./src/index.ts"
- ],
- "noExternal": [
- "@testing-library/dom",
- "@testing-library/jest-dom",
- "@testing-library/user-event",
- "chai",
- "@vitest/expect",
- "@vitest/spy",
- "@vitest/utils"
- ],
- "externals": [
- "util"
- ]
- },
- "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae16"
-}
diff --git a/code/lib/test/project.json b/code/lib/test/project.json
deleted file mode 100644
index 1302a230f1e1..000000000000
--- a/code/lib/test/project.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name": "test",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "projectType": "library",
- "targets": {
- "build": {}
- }
-}
diff --git a/code/lib/test/template/stories/utils.mock.ts b/code/lib/test/template/stories/utils.mock.ts
deleted file mode 100644
index 93a72d03a0e2..000000000000
--- a/code/lib/test/template/stories/utils.mock.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { fn } from '@storybook/test';
-
-import * as utils from './utils.ts';
-
-export const foo = fn(utils.foo).mockName('foo');
diff --git a/code/lib/test/template/stories/utils.ts b/code/lib/test/template/stories/utils.ts
deleted file mode 100644
index 5a80b1903c1f..000000000000
--- a/code/lib/test/template/stories/utils.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const foo = () => 'not mocked';
diff --git a/code/lib/test/tsconfig.json b/code/lib/test/tsconfig.json
deleted file mode 100644
index 73a65ef2ef6e..000000000000
--- a/code/lib/test/tsconfig.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "compilerOptions": {},
- "include": ["src/**/*"]
-}
diff --git a/code/lib/test/vitest.config.ts b/code/lib/test/vitest.config.ts
deleted file mode 100644
index 7420176b2e46..000000000000
--- a/code/lib/test/vitest.config.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { defineConfig, mergeConfig } from 'vitest/config';
-
-import { vitestCommonConfig } from '../../vitest.workspace';
-
-export default mergeConfig(
- vitestCommonConfig,
- defineConfig({
- // Add custom config here
- })
-);
diff --git a/code/package.json b/code/package.json
index 993a1ab476a6..e47578db9048 100644
--- a/code/package.json
+++ b/code/package.json
@@ -153,7 +153,6 @@
"@storybook/source-loader": "workspace:*",
"@storybook/svelte": "workspace:*",
"@storybook/svelte-webpack5": "workspace:*",
- "@storybook/test": "workspace:*",
"@storybook/testing-library": "next",
"@storybook/vue3": "workspace:*",
"@storybook/vue3-vite": "workspace:*",
@@ -162,8 +161,8 @@
"@storybook/web-components-vite": "workspace:*",
"@storybook/web-components-webpack5": "workspace:*",
"@testing-library/dom": "^10.4.0",
- "@testing-library/jest-dom": "^6.5.0",
- "@testing-library/react": "^16.0.0",
+ "@testing-library/jest-dom": "^6.6.3",
+ "@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.5.2",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/mock-require": "^2.0.3",
@@ -176,9 +175,9 @@
"@typescript-eslint/parser": "7.18.0",
"@vitejs/plugin-react": "^4.3.2",
"@vitejs/plugin-vue": "^4.4.0",
- "@vitest/browser": "^3.0.2",
- "@vitest/coverage-istanbul": "^3.0.2",
- "@vitest/coverage-v8": "^3.0.2",
+ "@vitest/browser": "^3.0.8",
+ "@vitest/coverage-istanbul": "^3.0.8",
+ "@vitest/coverage-v8": "^3.0.8",
"create-storybook": "workspace:*",
"cross-env": "^7.0.3",
"danger": "^12.3.3",
@@ -192,7 +191,7 @@
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-local-rules": "portal:../scripts/eslint-plugin-local-rules",
"eslint-plugin-playwright": "^1.6.2",
- "eslint-plugin-storybook": "0.11.3--canary.187.1af857a.0",
+ "eslint-plugin-storybook": "0.11.4",
"github-release-from-changelog": "^2.1.1",
"glob": "^10.0.0",
"happy-dom": "^14.12.0",
@@ -225,7 +224,7 @@
"util": "^0.12.4",
"vite": "^4.0.0",
"vite-plugin-inspect": "^0.8.5",
- "vitest": "^3.0.2",
+ "vitest": "^3.0.8",
"wait-on": "^7.0.1"
},
"dependenciesMeta": {
@@ -298,5 +297,6 @@
"Dependency Upgrades"
]
]
- }
+ },
+ "deferredNextVersion": "9.0.0-alpha.3"
}
diff --git a/code/renderers/html/template/cli/js/Button.stories.js b/code/renderers/html/template/cli/js/Button.stories.js
index 985eb1f26e1e..36ffffe5f270 100644
--- a/code/renderers/html/template/cli/js/Button.stories.js
+++ b/code/renderers/html/template/cli/js/Button.stories.js
@@ -1,4 +1,4 @@
-import { fn } from '@storybook/test';
+import { fn } from 'storybook/test';
import { createButton } from './Button';
diff --git a/code/renderers/html/template/cli/js/Header.stories.js b/code/renderers/html/template/cli/js/Header.stories.js
index 1168c39159ce..5c9949fe83f5 100644
--- a/code/renderers/html/template/cli/js/Header.stories.js
+++ b/code/renderers/html/template/cli/js/Header.stories.js
@@ -1,4 +1,4 @@
-import { fn } from '@storybook/test';
+import { fn } from 'storybook/test';
import { createHeader } from './Header';
diff --git a/code/renderers/html/template/cli/js/Page.stories.js b/code/renderers/html/template/cli/js/Page.stories.js
index 4e98ad615cd7..17002143e81f 100644
--- a/code/renderers/html/template/cli/js/Page.stories.js
+++ b/code/renderers/html/template/cli/js/Page.stories.js
@@ -1,4 +1,4 @@
-import { expect, userEvent, within } from '@storybook/test';
+import { expect, userEvent, within } from 'storybook/test';
import { createPage } from './Page';
diff --git a/code/renderers/html/template/cli/ts-4-9/Button.stories.ts b/code/renderers/html/template/cli/ts-4-9/Button.stories.ts
index e65f93d20f02..8e3e8fceb299 100644
--- a/code/renderers/html/template/cli/ts-4-9/Button.stories.ts
+++ b/code/renderers/html/template/cli/ts-4-9/Button.stories.ts
@@ -1,5 +1,6 @@
import type { Meta, StoryObj } from '@storybook/html';
-import { fn } from '@storybook/test';
+
+import { fn } from 'storybook/test';
import type { ButtonProps } from './Button';
import { createButton } from './Button';
diff --git a/code/renderers/html/template/cli/ts-4-9/Header.stories.ts b/code/renderers/html/template/cli/ts-4-9/Header.stories.ts
index 93bc0f66b4a8..5a119106099b 100644
--- a/code/renderers/html/template/cli/ts-4-9/Header.stories.ts
+++ b/code/renderers/html/template/cli/ts-4-9/Header.stories.ts
@@ -1,5 +1,6 @@
import type { Meta, StoryObj } from '@storybook/html';
-import { fn } from '@storybook/test';
+
+import { fn } from 'storybook/test';
import type { HeaderProps } from './Header';
import { createHeader } from './Header';
diff --git a/code/renderers/html/template/cli/ts-4-9/Page.stories.ts b/code/renderers/html/template/cli/ts-4-9/Page.stories.ts
index 5aa9e689913e..b5b06055caca 100644
--- a/code/renderers/html/template/cli/ts-4-9/Page.stories.ts
+++ b/code/renderers/html/template/cli/ts-4-9/Page.stories.ts
@@ -1,5 +1,6 @@
import type { Meta, StoryObj } from '@storybook/html';
-import { expect, userEvent, within } from '@storybook/test';
+
+import { expect, userEvent, within } from 'storybook/test';
import { createPage } from './Page';
diff --git a/code/renderers/preact/template/cli/Button.stories.jsx b/code/renderers/preact/template/cli/Button.stories.jsx
index 94fd8d336e48..0cc0adf6def4 100644
--- a/code/renderers/preact/template/cli/Button.stories.jsx
+++ b/code/renderers/preact/template/cli/Button.stories.jsx
@@ -1,4 +1,4 @@
-import { fn } from '@storybook/test';
+import { fn } from 'storybook/test';
import { Button } from './Button';
diff --git a/code/renderers/preact/template/cli/Header.stories.jsx b/code/renderers/preact/template/cli/Header.stories.jsx
index 7cb7da7cd8ca..6d88e1007498 100644
--- a/code/renderers/preact/template/cli/Header.stories.jsx
+++ b/code/renderers/preact/template/cli/Header.stories.jsx
@@ -1,4 +1,4 @@
-import { fn } from '@storybook/test';
+import { fn } from 'storybook/test';
import { Header } from './Header';
diff --git a/code/renderers/preact/template/cli/Page.stories.jsx b/code/renderers/preact/template/cli/Page.stories.jsx
index b7a417b634f0..478ae05a8705 100644
--- a/code/renderers/preact/template/cli/Page.stories.jsx
+++ b/code/renderers/preact/template/cli/Page.stories.jsx
@@ -1,4 +1,4 @@
-import { userEvent, within } from '@storybook/test';
+import { userEvent, within } from 'storybook/test';
import { Page } from './Page';
diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json
index 4ab865a78af3..9f4e0098a139 100644
--- a/code/renderers/react/package.json
+++ b/code/renderers/react/package.json
@@ -74,7 +74,6 @@
"@storybook/react-dom-shim": "workspace:*"
},
"devDependencies": {
- "@storybook/test": "workspace:*",
"@types/babel-plugin-react-docgen": "^4.2.3",
"@types/escodegen": "^0.0.6",
"@types/estree": "^0.0.51",
@@ -96,16 +95,12 @@
"type-fest": "~2.19"
},
"peerDependencies": {
- "@storybook/test": "workspace:*",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
"storybook": "workspace:^",
"typescript": ">= 4.9.x"
},
"peerDependenciesMeta": {
- "@storybook/test": {
- "optional": true
- },
"typescript": {
"optional": true
}
diff --git a/code/renderers/react/src/__test__/Button.csf4.stories.tsx b/code/renderers/react/src/__test__/Button.csf4.stories.tsx
index 71e8eafa02a8..19b9c20460e6 100644
--- a/code/renderers/react/src/__test__/Button.csf4.stories.tsx
+++ b/code/renderers/react/src/__test__/Button.csf4.stories.tsx
@@ -1,10 +1,10 @@
import React, { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
-import { expect, fn, mocked, userEvent, within } from '@storybook/test';
-
import { action } from '@storybook/addon-actions';
+import { expect, fn, mocked, userEvent, within } from 'storybook/test';
+
import { __definePreview } from '../preview';
import { Button } from './Button';
diff --git a/code/renderers/react/src/__test__/Button.stories.tsx b/code/renderers/react/src/__test__/Button.stories.tsx
index 0e6e0d6e8c67..134748e8b347 100644
--- a/code/renderers/react/src/__test__/Button.stories.tsx
+++ b/code/renderers/react/src/__test__/Button.stories.tsx
@@ -1,11 +1,11 @@
import React, { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
-import { expect, fn, mocked, userEvent, within } from '@storybook/test';
-
import type { HandlerFunction } from '@storybook/addon-actions';
import { action } from '@storybook/addon-actions';
+import { expect, fn, mocked, userEvent, within } from 'storybook/test';
+
import type { StoryFn as CSF2Story, StoryObj as CSF3Story, Meta } from '..';
import type { ButtonProps } from './Button';
import { Button } from './Button';
diff --git a/code/renderers/react/src/csf-factories.test.tsx b/code/renderers/react/src/csf-factories.test.tsx
index 3289e3394ec0..7a9aa5093d7b 100644
--- a/code/renderers/react/src/csf-factories.test.tsx
+++ b/code/renderers/react/src/csf-factories.test.tsx
@@ -9,10 +9,9 @@ import React from 'react';
import type { Canvas } from 'storybook/internal/csf';
import type { Args, StrictArgs } from 'storybook/internal/types';
-import type { Mock } from '@storybook/test';
-import { fn } from '@storybook/test';
-
import { expectTypeOf } from 'expect-type';
+import { fn } from 'storybook/test';
+import type { Mock } from 'storybook/test';
import { __definePreview } from './preview';
import type { Decorator } from './public-types';
diff --git a/code/renderers/react/src/entry-preview.tsx b/code/renderers/react/src/entry-preview.tsx
index b2e6c1de5b18..7c83cd3f45bc 100644
--- a/code/renderers/react/src/entry-preview.tsx
+++ b/code/renderers/react/src/entry-preview.tsx
@@ -30,7 +30,7 @@ export const beforeAll = async () => {
try {
// copied from
// https://github.com/testing-library/react-testing-library/blob/3dcd8a9649e25054c0e650d95fca2317b7008576/src/pure.js
- const { configure } = await import('@storybook/test');
+ const { configure } = await import('storybook/test');
configure({
unstable_advanceTimersWrapper: (cb) => {
@@ -73,7 +73,7 @@ export const beforeAll = async () => {
});
} catch (e) {
// no-op
- // @storybook/test might not be available
+ // storybook/test might not be available
}
};
diff --git a/code/renderers/react/src/public-types.test.tsx b/code/renderers/react/src/public-types.test.tsx
index 42544c6bb150..45a36ab1d015 100644
--- a/code/renderers/react/src/public-types.test.tsx
+++ b/code/renderers/react/src/public-types.test.tsx
@@ -9,10 +9,9 @@ import { satisfies } from 'storybook/internal/common';
import type { Canvas } from 'storybook/internal/csf';
import type { Args, StoryAnnotations, StrictArgs } from 'storybook/internal/types';
-import type { Mock } from '@storybook/test';
-import { fn } from '@storybook/test';
-
import { expectTypeOf } from 'expect-type';
+import { fn } from 'storybook/test';
+import type { Mock } from 'storybook/test';
import type { SetOptional } from 'type-fest';
import type { Decorator, Meta, StoryObj } from './public-types';
diff --git a/code/renderers/react/template/cli/js/Button.stories.js b/code/renderers/react/template/cli/js/Button.stories.js
index 045d9c477ab1..1b56021e71d9 100644
--- a/code/renderers/react/template/cli/js/Button.stories.js
+++ b/code/renderers/react/template/cli/js/Button.stories.js
@@ -1,4 +1,4 @@
-import { fn } from '@storybook/test';
+import { fn } from 'storybook/test';
import { Button } from './Button';
diff --git a/code/renderers/react/template/cli/js/Header.stories.js b/code/renderers/react/template/cli/js/Header.stories.js
index 7cb7da7cd8ca..6d88e1007498 100644
--- a/code/renderers/react/template/cli/js/Header.stories.js
+++ b/code/renderers/react/template/cli/js/Header.stories.js
@@ -1,4 +1,4 @@
-import { fn } from '@storybook/test';
+import { fn } from 'storybook/test';
import { Header } from './Header';
diff --git a/code/renderers/react/template/cli/js/Page.stories.js b/code/renderers/react/template/cli/js/Page.stories.js
index 7b9906a73514..1ffea36cf374 100644
--- a/code/renderers/react/template/cli/js/Page.stories.js
+++ b/code/renderers/react/template/cli/js/Page.stories.js
@@ -1,4 +1,4 @@
-import { expect, userEvent, within } from '@storybook/test';
+import { expect, userEvent, within } from 'storybook/test';
import { Page } from './Page';
diff --git a/code/renderers/react/template/cli/ts-4-9/Button.stories.ts b/code/renderers/react/template/cli/ts-4-9/Button.stories.ts
index 2a05e01b06fe..535e1b3fd965 100644
--- a/code/renderers/react/template/cli/ts-4-9/Button.stories.ts
+++ b/code/renderers/react/template/cli/ts-4-9/Button.stories.ts
@@ -1,5 +1,6 @@
import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+
+import { fn } from 'storybook/test';
import { Button } from './Button';
diff --git a/code/renderers/react/template/cli/ts-4-9/Header.stories.ts b/code/renderers/react/template/cli/ts-4-9/Header.stories.ts
index 80c71d0f520e..b233bcb4f4d0 100644
--- a/code/renderers/react/template/cli/ts-4-9/Header.stories.ts
+++ b/code/renderers/react/template/cli/ts-4-9/Header.stories.ts
@@ -1,5 +1,6 @@
import type { Meta, StoryObj } from '@storybook/react';
-import { fn } from '@storybook/test';
+
+import { fn } from 'storybook/test';
import { Header } from './Header';
diff --git a/code/renderers/react/template/cli/ts-4-9/Page.stories.ts b/code/renderers/react/template/cli/ts-4-9/Page.stories.ts
index 5d2c688a978f..6c39800e3e5c 100644
--- a/code/renderers/react/template/cli/ts-4-9/Page.stories.ts
+++ b/code/renderers/react/template/cli/ts-4-9/Page.stories.ts
@@ -1,5 +1,6 @@
import type { Meta, StoryObj } from '@storybook/react';
-import { expect, userEvent, within } from '@storybook/test';
+
+import { expect, userEvent, within } from 'storybook/test';
import { Page } from './Page';
diff --git a/code/renderers/svelte/src/__test__/composeStories/Button.stories.ts b/code/renderers/svelte/src/__test__/composeStories/Button.stories.ts
index 92ade46f29a8..9bc3ad429f8c 100644
--- a/code/renderers/svelte/src/__test__/composeStories/Button.stories.ts
+++ b/code/renderers/svelte/src/__test__/composeStories/Button.stories.ts
@@ -1,4 +1,4 @@
-import { expect, fn, userEvent, within } from '@storybook/test';
+import { expect, fn, userEvent, within } from 'storybook/test';
import type { StoryFn as CSF2Story, Meta, StoryObj } from '../..';
import AddWrapperDecorator from './AddWrapperDecorator.svelte';
diff --git a/code/renderers/svelte/template/cli/js/Page.stories.js b/code/renderers/svelte/template/cli/js/Page.stories.js
index 5ce7b3dac56f..7355660af638 100644
--- a/code/renderers/svelte/template/cli/js/Page.stories.js
+++ b/code/renderers/svelte/template/cli/js/Page.stories.js
@@ -1,4 +1,4 @@
-import { expect, userEvent, waitFor, within } from '@storybook/test';
+import { expect, userEvent, waitFor, within } from 'storybook/test';
import Page from './Page.svelte';
diff --git a/code/renderers/svelte/template/cli/svelte-5-js/Button.stories.svelte b/code/renderers/svelte/template/cli/svelte-5-js/Button.stories.svelte
index 4c8c7cce632a..e6fb72dac174 100644
--- a/code/renderers/svelte/template/cli/svelte-5-js/Button.stories.svelte
+++ b/code/renderers/svelte/template/cli/svelte-5-js/Button.stories.svelte
@@ -1,7 +1,7 @@