diff --git a/docs/contribute/new-snippets.md b/docs/contribute/new-snippets.md
index 1262f9f219b8..9b70c7e4250d 100644
--- a/docs/contribute/new-snippets.md
+++ b/docs/contribute/new-snippets.md
@@ -10,13 +10,9 @@ Storybook maintains code snippets for a [variety of frameworks](./../api/framewo
We welcome community contributions to the code snippets. Here's a matrix of the frameworks we have snippets for. Help us add snippets for your favorite framework.
-| React | Vue | Angular | Web Components | Svelte | Ember | HTML | Preact |
-| ---------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----- | ---- | ------ |
-| [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/react) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/vue) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/angular) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/web-components) (See below) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/svelte) | ❌ | ❌ | ❌ |
-
-
-💡 The Web Components
snippets are present but not fully documented. If you're willing to help, submit a pull request.
-
+| React | Vue | Angular | Web Components | Svelte | Ember | HTML | Preact |
+| ---------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----- | ---- | ------ |
+| [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/react) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/vue) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/angular) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/web-components) | [✅](https://github.com/storybookjs/storybook/tree/next/docs/snippets/svelte) | ❌ | ❌ | ❌ |
## Setup
diff --git a/docs/essentials/controls.md b/docs/essentials/controls.md
index 2d2035ad648e..73f0df99f184 100644
--- a/docs/essentials/controls.md
+++ b/docs/essentials/controls.md
@@ -123,6 +123,7 @@ Until now, we only used auto-generated controls based on the component we're wri
(AllInfoQuery);
+
+ return { loading, error, data };
+}
+
+export function DocumentScreen() {
+ const { loading, error, data } = useFetchInfo();
+
+ if (loading) {
+ return Loading...
;
+ }
+
+ if (error) {
+ return There was an error fetching the data!
;
+ }
+
+ return (
+
+
+
+
+ );
+}
+```
diff --git a/docs/snippets/react/documentscreen-story-msw-graphql-query.js.mdx b/docs/snippets/react/documentscreen-story-msw-graphql-query.js.mdx
index 3e9ea8d1e928..73ed384f351f 100644
--- a/docs/snippets/react/documentscreen-story-msw-graphql-query.js.mdx
+++ b/docs/snippets/react/documentscreen-story-msw-graphql-query.js.mdx
@@ -1,7 +1,5 @@
```js
-// YourPage.stories.js|jsx|ts|tsx
-
-import React from 'react';
+// YourPage.stories.js|jsx
import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client';
diff --git a/docs/snippets/react/documentscreen-story-msw-graphql-query.ts.mdx b/docs/snippets/react/documentscreen-story-msw-graphql-query.ts.mdx
new file mode 100644
index 000000000000..98a405243960
--- /dev/null
+++ b/docs/snippets/react/documentscreen-story-msw-graphql-query.ts.mdx
@@ -0,0 +1,126 @@
+```js
+// YourPage.stories.ts|tsx
+
+import type { Meta, StoryObj } from '@storybook/react';
+
+import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client';
+
+import { graphql } from 'msw';
+
+import { DocumentScreen } from './YourPage';
+
+const mockedClient = new ApolloClient({
+ uri: 'https://your-graphql-endpoint',
+ cache: new InMemoryCache(),
+ defaultOptions: {
+ watchQuery: {
+ fetchPolicy: 'no-cache',
+ errorPolicy: 'all',
+ },
+ query: {
+ fetchPolicy: 'no-cache',
+ errorPolicy: 'all',
+ },
+ },
+});
+
+//👇The mocked data that will be used in the story
+const TestData = {
+ user: {
+ userID: 1,
+ name: 'Someone',
+ },
+ document: {
+ id: 1,
+ userID: 1,
+ title: 'Something',
+ brief: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+ status: 'approved',
+ },
+ subdocuments: [
+ {
+ id: 1,
+ userID: 1,
+ title: 'Something',
+ content:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+ status: 'approved',
+ },
+ {
+ id: 2,
+ userID: 1,
+ title: 'Something else',
+ content:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+ status: 'awaiting review',
+ },
+ {
+ id: 3,
+ userID: 2,
+ title: 'Another document',
+ content:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+ status: 'approved',
+ },
+ {
+ id: 4,
+ userID: 2,
+ title: 'Something',
+ content:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+ status: 'approved',
+ },
+ ],
+};
+const meta: Meta = {
+ /* 👇 The title prop is optional.
+ * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading
+ * to learn how to generate automatic titles
+ */
+ title: 'DocumentScreen',
+ component: DocumentScreen,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const MockedSuccess: Story = {
+ parameters: {
+ msw: [
+ graphql.query('AllInfoQuery', (req, res, ctx) => {
+ return res(
+ ctx.data({
+ allFilms: {
+ films,
+ },
+ })
+ );
+ }),
+ ],
+ },
+};
+
+export const MockedError: Story = {
+ parameters: {
+ msw: [
+ graphql.query('AllInfoQuery', (req, res, ctx) => {
+ return res(
+ ctx.delay(800),
+ ctx.errors([
+ {
+ message: 'Access denied',
+ },
+ ])
+ );
+ }),
+ ],
+ },
+};
+```
diff --git a/docs/snippets/react/loader-story.js.mdx b/docs/snippets/react/loader-story.js.mdx
index 17a07ea76c5b..f54565fd68ab 100644
--- a/docs/snippets/react/loader-story.js.mdx
+++ b/docs/snippets/react/loader-story.js.mdx
@@ -1,5 +1,5 @@
```js
-// TodoItem.stories.js|jsx|ts|tsx
+// TodoItem.stories.js|jsx
import React from 'react';
diff --git a/docs/snippets/react/loader-story.ts.mdx b/docs/snippets/react/loader-story.ts.mdx
new file mode 100644
index 000000000000..51e25f9d98d0
--- /dev/null
+++ b/docs/snippets/react/loader-story.ts.mdx
@@ -0,0 +1,32 @@
+```tsx
+// MyComponent.stories.ts|tsx
+
+import type { Meta, StoryObj } from '@storybook/react';
+
+import fetch from 'node-fetch';
+
+import { TodoItem } from './TodoItem';
+
+const meta: Meta = {
+ /* 👇 The title prop is optional.
+ * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading
+ * to learn how to generate automatic titles
+ */
+ title: 'Examples/Loader'
+ component: TodoItem,
+ render: (args, { loaded: { todo } }) => ,
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Primary: Story = {
+ loaders: [
+ async () => ({
+ todo: await (
+ await fetch('https://jsonplaceholder.typicode.com/todos/1')
+ ).json(),
+ }),
+ ],
+};
+```
diff --git a/docs/snippets/react/table-story-fully-customize-controls.js.mdx b/docs/snippets/react/table-story-fully-customize-controls.js.mdx
index a2c2190a96ae..8189e7a1a59e 100644
--- a/docs/snippets/react/table-story-fully-customize-controls.js.mdx
+++ b/docs/snippets/react/table-story-fully-customize-controls.js.mdx
@@ -1,5 +1,5 @@
```js
-// Table.stories.js|jsx!ts!tsx
+// Table.stories.js|jsx
import React from 'react';
diff --git a/docs/snippets/react/table-story-fully-customize-controls.ts.mdx b/docs/snippets/react/table-story-fully-customize-controls.ts.mdx
new file mode 100644
index 000000000000..769112a69713
--- /dev/null
+++ b/docs/snippets/react/table-story-fully-customize-controls.ts.mdx
@@ -0,0 +1,44 @@
+```ts
+// Table.stories.ts|tsx
+
+import type { Meta, StoryObj } from '@storybook/react';
+
+import { Table } from './Table';
+import { TD } from './TableDataCell';
+import { TR } from './TableRow';
+
+const meta: Meta = {
+ /* 👇 The title prop is optional.
+ * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading
+ * to learn how to generate automatic titles
+ */
+ title: 'Custom Table',
+ component: Table,
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const TableStory: Story = {
+ render: ({ data, ...args }) => (
+
+ {data.map((row) => (
+
+ {row.map((item) => (
+ {item} |
+ ))}
+
+ ))}
+
+ ),
+ args: {
+ //👇 This arg is for the story component
+ data: [
+ [1, 2, 3],
+ [4, 5, 6],
+ ],
+ //👇 The remaining args get passed to the `Table` component
+ size: 'large',
+ },
+};
+```
diff --git a/docs/snippets/vue/button-component-with-proptypes.ts-2.ts.mdx b/docs/snippets/vue/button-component-with-proptypes.ts-2.ts.mdx
new file mode 100644
index 000000000000..c969a9195e41
--- /dev/null
+++ b/docs/snippets/vue/button-component-with-proptypes.ts-2.ts.mdx
@@ -0,0 +1,30 @@
+```html
+
+
+
+
+
+
+
+```
diff --git a/docs/snippets/vue/button-component-with-proptypes.ts-3.ts.mdx b/docs/snippets/vue/button-component-with-proptypes.ts-3.ts.mdx
new file mode 100644
index 000000000000..2621cd064736
--- /dev/null
+++ b/docs/snippets/vue/button-component-with-proptypes.ts-3.ts.mdx
@@ -0,0 +1,38 @@
+```html
+
+
+
+
+
+
+
+```
diff --git a/docs/snippets/vue/button-implementation.ts-2.ts.mdx b/docs/snippets/vue/button-implementation.ts-2.ts.mdx
new file mode 100644
index 000000000000..9dec664ccee5
--- /dev/null
+++ b/docs/snippets/vue/button-implementation.ts-2.ts.mdx
@@ -0,0 +1,54 @@
+```html
+
+
+
+
+
+
+
+```
diff --git a/docs/snippets/vue/button-implementation.ts-3.ts.mdx b/docs/snippets/vue/button-implementation.ts-3.ts.mdx
new file mode 100644
index 000000000000..b1aa84b94594
--- /dev/null
+++ b/docs/snippets/vue/button-implementation.ts-3.ts.mdx
@@ -0,0 +1,60 @@
+```html
+
+
+
+
+
+
+
+```
diff --git a/docs/snippets/vue/component-story-with-accessibility.ts-2.ts.mdx b/docs/snippets/vue/component-story-with-accessibility.ts-2.ts.mdx
new file mode 100644
index 000000000000..6df52baac8ee
--- /dev/null
+++ b/docs/snippets/vue/component-story-with-accessibility.ts-2.ts.mdx
@@ -0,0 +1,47 @@
+```ts
+// Button.stories.ts
+
+import Button from './Button.vue';
+
+import type { Meta, StoryObj } from '@storybook/vue';
+
+const meta: Meta = {
+ /* 👇 The title prop is optional.
+ * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading
+ * to learn how to generate automatic titles
+ */
+ title: 'Accessibility testing',
+ component: Button,
+ argTypes: {
+ backgroundColor: { control: 'color' },
+ },
+};
+
+export default meta;
+type Story = StoryObj;
+
+// This is an accessible story
+export const Accessible: Story = {
+ render: (args, { argTypes }) => ({
+ components: { Button },
+ props: Object.keys(argTypes),
+ template: '',
+ }),
+ args: {
+ primary: false,
+ label: 'Button',
+ },
+};
+// This is not
+export const Inaccessible: Story = {
+ render: (args, { argTypes }) => ({
+ components: { Button },
+ props: Object.keys(argTypes),
+ template: '',
+ }),
+ args: {
+ ...Accessible.args,
+ backgroundColor: 'red',
+ },
+};
+```
diff --git a/docs/snippets/vue/component-story-with-accessibility.ts-3.ts.mdx b/docs/snippets/vue/component-story-with-accessibility.ts-3.ts.mdx
new file mode 100644
index 000000000000..968002201fc9
--- /dev/null
+++ b/docs/snippets/vue/component-story-with-accessibility.ts-3.ts.mdx
@@ -0,0 +1,51 @@
+```ts
+// Button.stories.ts
+
+import Button from './Button.vue';
+
+import type { Meta, StoryObj } from '@storybook/vue3';
+
+const meta: Meta = {
+ /* 👇 The title prop is optional.
+ * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading
+ * to learn how to generate automatic titles
+ */
+ title: 'Accessibility testing',
+ component: Button,
+ argTypes: {
+ backgroundColor: { control: 'color' },
+ },
+};
+
+export default meta;
+type Story = StoryObj;
+
+// This is an accessible story
+export const Accessible: Story = {
+ render: (args) => ({
+ components: { Button },
+ setup() {
+ return { args };
+ },
+ template: '',
+ }),
+ args: {
+ primary: false,
+ label: 'Button',
+ },
+};
+// This is not
+export const Inaccessible: Story = {
+ render: (args) => ({
+ components: { Button },
+ setup() {
+ return { args };
+ },
+ template: '',
+ }),
+ args: {
+ ...Accessible.args,
+ backgroundColor: 'red',
+ },
+};
+```
diff --git a/docs/snippets/vue/document-screen-with-graphql.ts-3.ts.mdx b/docs/snippets/vue/document-screen-with-graphql.ts-3.ts.mdx
new file mode 100644
index 000000000000..819b65f74aa4
--- /dev/null
+++ b/docs/snippets/vue/document-screen-with-graphql.ts-3.ts.mdx
@@ -0,0 +1,60 @@
+```html
+
+
+
+ Loading...
+
+ There was an error fetching the data!
+
+
+
+
+
+```
diff --git a/docs/snippets/web-components/documentscreen-story-msw-rest-request.ts.mdx b/docs/snippets/web-components/documentscreen-story-msw-rest-request.ts.mdx
new file mode 100644
index 000000000000..05304ace97f4
--- /dev/null
+++ b/docs/snippets/web-components/documentscreen-story-msw-rest-request.ts.mdx
@@ -0,0 +1,84 @@
+```ts
+// YourPage.stories.ts
+
+import type { Meta, StoryObj } from '@storybook/web-components';
+
+import { rest } from 'msw';
+
+const meta: Meta = {
+ title: 'DocumentScreen',
+ component: 'demo-document-screen',
+};
+
+export default meta;
+type Story = StoryObj;
+
+// 👇 The mocked data that will be used in the story
+const TestData = {
+ user: {
+ userID: 1,
+ name: 'Someone',
+ },
+ document: {
+ id: 1,
+ userID: 1,
+ title: 'Something',
+ brief: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
+ status: 'approved',
+ },
+ subdocuments: [
+ {
+ id: 1,
+ userID: 1,
+ title: 'Something',
+ content:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+ status: 'approved',
+ },
+ {
+ id: 2,
+ userID: 1,
+ title: 'Something else',
+ content:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+ status: 'awaiting review',
+ },
+ {
+ id: 3,
+ userID: 2,
+ title: 'Another document',
+ content:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+ status: 'approved',
+ },
+ {
+ id: 4,
+ userID: 2,
+ title: 'Something',
+ content:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+ status: 'approved',
+ },
+ ],
+};
+
+export const MockedSuccess: Story = {
+ parameters: {
+ msw: [
+ rest.get('https://your-restful-endpoint/', (_req, res, ctx) => {
+ return res(ctx.json(TestData));
+ }),
+ ],
+ },
+};
+
+export const MockedError: Story = {
+ parameters: {
+ msw: [
+ rest.get('https://your-restful-endpoint', (_req, res, ctx) => {
+ return res(ctx.delay(800), ctx.status(403));
+ }),
+ ],
+ },
+};
+```
diff --git a/docs/snippets/web-components/histogram-story.js.mdx b/docs/snippets/web-components/histogram-story.js.mdx
index 5eff9c6d6908..38ccaa26c53b 100644
--- a/docs/snippets/web-components/histogram-story.js.mdx
+++ b/docs/snippets/web-components/histogram-story.js.mdx
@@ -1,33 +1,12 @@
```js
// Histogram.stories.js
-import { html } from 'lit-html';
-
-import './histogram-component';
-
export default {
- /* 👇 The title prop is optional.
- * See https://storybook.js.org/docs/7.0/web-components/configure/overview#configure-story-loading
- * to learn how to generate automatic titles
- */
title: 'Histogram',
+ component: 'histogram-component',
};
-/*
- *👇 Render functions are a framework specific feature to allow you control on how the component renders.
- * See https://storybook.js.org/docs/7.0/web-components/api/csf
- * to learn how to use render functions.
- */
-
export const Default = {
- render: ({ dataType, showHistogramLabels, histogramAccentColor, label }) => html`
-
- `,
args: {
dataType: 'latency',
showHistogramLabels: true,
diff --git a/docs/snippets/web-components/histogram-story.ts.mdx b/docs/snippets/web-components/histogram-story.ts.mdx
new file mode 100644
index 000000000000..93bed5e071a5
--- /dev/null
+++ b/docs/snippets/web-components/histogram-story.ts.mdx
@@ -0,0 +1,22 @@
+```ts
+// MyComponent.stories.ts
+
+import type { Meta, StoryObj } from '@storybook/web-components';
+
+const meta: Meta = {
+ title: 'Histogram',
+ component: 'histogram-component',
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ dataType: 'latency',
+ showHistogramLabels: true,
+ histogramAccentColor: '#1EA7FD',
+ label: 'Latency distribution',
+ },
+};
+```
diff --git a/docs/why-storybook.md b/docs/why-storybook.md
index 0c798e36876a..174698df577d 100644
--- a/docs/why-storybook.md
+++ b/docs/why-storybook.md
@@ -48,6 +48,7 @@ You write stories for granular UI component variation and then use those stories
'vue/histogram-story.ts-3.ts.mdx',
'svelte/histogram-story.js.mdx',
'web-components/histogram-story.js.mdx',
+ 'web-components/histogram-story.ts.mdx',
'preact/histogram-story.js.mdx',
'html/histogram-story.js.mdx',
'html/histogram-story.ts.mdx',
diff --git a/docs/writing-docs/doc-block-argstable.md b/docs/writing-docs/doc-block-argstable.md
index f541c781964b..b112256e6a6f 100644
--- a/docs/writing-docs/doc-block-argstable.md
+++ b/docs/writing-docs/doc-block-argstable.md
@@ -21,7 +21,9 @@ This is extremely useful, but it can be further expanded. Additional information
'react/button-component-with-proptypes.ts.mdx',
'angular/button-component-with-proptypes.ts.mdx',
'vue/button-component-with-proptypes.2.js.mdx',
+ 'vue/button-component-with-proptypes.ts-2.ts.mdx',
'vue/button-component-with-proptypes.3.js.mdx',
+ 'vue/button-component-with-proptypes.ts-3.ts.mdx',
'svelte/button-component-with-proptypes.js.mdx',
'web-components/button-component-with-proptypes.js.mdx',
'web-components/button-component-with-proptypes.ts.mdx',
@@ -126,7 +128,9 @@ You can also extend the ArgsTable's customization by grouping related `argTypes`
'react/button-implementation.ts.mdx',
'angular/button-implementation.ts.mdx',
'vue/button-implementation.2.js.mdx',
+ 'vue/button-implementation.ts-2.ts.mdx',
'vue/button-implementation.3.js.mdx',
+ 'vue/button-implementation.ts-3.ts.mdx',
'svelte/button-implementation.js.mdx',
'web-components/button-implementation.js.mdx',
'web-components/button-implementation.ts.mdx',
diff --git a/docs/writing-stories/build-pages-with-storybook.md b/docs/writing-stories/build-pages-with-storybook.md
index 121908aa65b9..320979b796a2 100644
--- a/docs/writing-stories/build-pages-with-storybook.md
+++ b/docs/writing-stories/build-pages-with-storybook.md
@@ -152,6 +152,7 @@ To test your screen with the mocked data, you could write a similar set of stori
paths={[
'common/documentscreen-story-msw-rest-request.js.mdx',
'web-components/documentscreen-story-msw-rest-request.js.mdx',
+ 'web-components/documentscreen-story-msw-rest-request.ts.mdx',
]}
usesCsf3
csf2Path="writing-stories/build-pages-with-storybook#snippet-documentscreen-story-msw-rest-request"
@@ -174,7 +175,9 @@ In addition to mocking RESTful requests, the other noteworthy feature of the [MS