Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions code/frameworks/react-vite/src/preset.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';

vi.mock(import('./plugins/react-docgen.ts'), { spy: true });

import * as reactDocgenModule from './plugins/react-docgen.ts';
import { viteFinal } from './preset.ts';

type ViteFinalOptions = Parameters<typeof viteFinal>[1];

const createTypescriptPresetOptions = (
reactDocgenOptions: Record<string, unknown>
): ViteFinalOptions =>
({
presets: {
apply: async (name: string) =>
name === 'typescript' ? { reactDocgen: 'react-docgen', reactDocgenOptions } : undefined,
},
}) as ViteFinalOptions;

describe('react-vite preset', () => {
beforeEach(() => {
vi.mocked(reactDocgenModule.reactDocgen)
.mockReset()
.mockResolvedValue({ name: 'storybook:react-docgen-plugin' });
});

it('passes reactDocgenOptions to the react-docgen plugin', async () => {
const existingPlugin = { name: 'existing-plugin' };
const reactDocgenOptions = {
exclude: [/node_modules\/.*/, /packages\/.*/],
};

const config = await viteFinal(
{ plugins: [existingPlugin] },
createTypescriptPresetOptions(reactDocgenOptions)
);

expect(reactDocgenModule.reactDocgen).toHaveBeenCalledWith({
include: /\.(mjs|tsx?|jsx?)$/,
...reactDocgenOptions,
});
expect(config.plugins).toEqual([{ name: 'storybook:react-docgen-plugin' }, existingPlugin]);
});

it('allows reactDocgenOptions to override the default include pattern', async () => {
const reactDocgenOptions = {
include: /\.jsx$/,
exclude: [/packages\/.*/],
};

await viteFinal({}, createTypescriptPresetOptions(reactDocgenOptions));

expect(reactDocgenModule.reactDocgen).toHaveBeenCalledWith(reactDocgenOptions);
});
});
15 changes: 11 additions & 4 deletions code/frameworks/react-vite/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,20 @@ export const core: PresetProperty<'core'> = {
renderer: import.meta.resolve('@storybook/react/preset'),
};

type TypescriptPresetOptions = Pick<
NonNullable<StorybookConfig['typescript']>,
'reactDocgen' | 'reactDocgenOptions' | 'reactDocgenTypescriptOptions'
>;

export const viteFinal: NonNullable<StorybookConfig['viteFinal']> = async (config, { presets }) => {
const plugins = [...(config?.plugins ?? [])];

// Add docgen plugin
const { reactDocgen: reactDocgenOption, reactDocgenTypescriptOptions } = await presets.apply<any>(
'typescript',
{}
);
const {
reactDocgen: reactDocgenOption,
reactDocgenOptions,
reactDocgenTypescriptOptions,
} = await presets.apply<TypescriptPresetOptions>('typescript', {});
let typescriptPresent;

try {
Expand Down Expand Up @@ -42,6 +48,7 @@ export const viteFinal: NonNullable<StorybookConfig['viteFinal']> = async (confi
// If react-docgen is specified, use it for everything, otherwise only use it for non-typescript files
await reactDocgen({
include: reactDocgenOption === 'react-docgen' ? /\.(mjs|tsx?|jsx?)$/ : /\.(mjs|jsx?)$/,
...reactDocgenOptions,
})
);
}
Expand Down
5 changes: 5 additions & 0 deletions code/frameworks/react-vite/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
import type { BuilderOptions, StorybookConfigVite } from '@storybook/builder-vite';

import type docgenTypescript from '@joshwooding/vite-plugin-react-docgen-typescript';
import type { reactDocgen } from './plugins/react-docgen.ts';

type FrameworkName = CompatibleString<'@storybook/react-vite'>;
type BuilderName = CompatibleString<'@storybook/builder-vite'>;
Expand All @@ -26,6 +27,8 @@ export type FrameworkOptions = {
legacyRootApi?: boolean;
};

export type ReactDocgenOptions = Parameters<typeof reactDocgen>[0];

type StorybookConfigFramework = {
framework:
| FrameworkName
Expand Down Expand Up @@ -58,6 +61,8 @@ type TypescriptOptions = TypescriptOptionsBase & {
* @default `'react-docgen'`
*/
reactDocgen: 'react-docgen-typescript' | 'react-docgen' | false;
/** Configures the built-in Vite `react-docgen` plugin */
reactDocgenOptions: ReactDocgenOptions;
/** Configures `@joshwooding/vite-plugin-react-docgen-typescript` */
reactDocgenTypescriptOptions: Parameters<typeof docgenTypescript>[0];
};
Expand Down
33 changes: 33 additions & 0 deletions docs/_snippets/main-config-typescript-react-docgen-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
```ts filename=".storybook/main.ts" renderer="react" language="ts" tabTitle="CSF 3"
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.
import type { StorybookConfig } from '@storybook/your-framework';

const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
typescript: {
reactDocgen: 'react-docgen',
reactDocgenOptions: {
exclude: [/node_modules\/.*/, /packages\/.*/],
},
},
};

export default config;
```

```ts filename=".storybook/main.ts" renderer="react" language="ts" tabTitle="CSF Next 🧪"
// Replace your-framework with the framework you are using (e.g., react-vite, nextjs, nextjs-vite)
import { defineMain } from '@storybook/your-framework/node';

export default defineMain({
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
typescript: {
reactDocgen: 'react-docgen',
reactDocgenOptions: {
exclude: [/node_modules\/.*/, /packages\/.*/],
},
},
});
```
18 changes: 18 additions & 0 deletions docs/api/main-config/main-config-typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ Type:
check?: boolean;
checkOptions?: CheckOptions;
reactDocgen?: 'react-docgen' | 'react-docgen-typescript' | false;
reactDocgenOptions?: {
include?: string | RegExp | (string | RegExp)[];
exclude?: string | RegExp | (string | RegExp)[];
};
reactDocgenTypescriptOptions?: ReactDocgenTypescriptOptions;
skipCompiler?: boolean;
}
Expand Down Expand Up @@ -75,6 +79,20 @@ Options to pass to `fork-ts-checker-webpack-plugin`, if [enabled](#check). See [

{/* prettier-ignore-end */}

## `reactDocgenOptions`

Type: `{ include?: string | RegExp | (string | RegExp)[]; exclude?: string | RegExp | (string | RegExp)[] }`

Available for Vite-based React projects when `reactDocgen` is enabled.

Configures the options passed to Storybook's built-in `react-docgen` Vite plugin, which can be useful in monorepos where you need to narrow the files that Storybook analyzes.

{/* prettier-ignore-start */}

<CodeSnippets path="main-config-typescript-react-docgen-options.md" />

{/* prettier-ignore-end */}

## `reactDocgenTypescriptOptions`

Type: `ReactDocgenTypescriptOptions`
Expand Down
1 change: 1 addition & 0 deletions docs/configure/integration/typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ See the [main configuration API reference](../../api/main-config/main-config.mdx
| `check` | Available for Webpack-based projects.<br />Enables type checking within Storybook<br />`typescript: { check: true },` |
| `checkOptions` | Requires the `check` option to be enabled.<br />Configures the [`fork-ts-checker-webpack-plugin`](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin) plugin<br />`typescript: { checkOptions: {},},` |
| `reactDocgen` | Configures the TypeScript parser used by Storybook.<br />Available options: `react-docgen` (default), `react-docgen-typescript`,` false`<br /> `typescript: { reactDocgen: 'react-docgen'},` |
| `reactDocgenOptions` | Available for Vite-based React projects when `reactDocgen` is enabled.<br />Configures Storybook's built-in `react-docgen` Vite plugin, including custom `include` and `exclude` filters.<br />`typescript: { reactDocgen: 'react-docgen', reactDocgenOptions: {},},` |
| `reactDocgenTypescriptOptions` | Requires the `reactDocgen`option to be `react-docgen-typescript`.<br /> Configures the `react-docgen-typescript-plugin` plugin per builder<br />`typescript: { reactDocgen: 'react-docgen-typescript', reactDocgenTypescriptOptions: {},},` |
| `skipCompiler` | Disables parsing Typescript files through the compiler<br />`typescript: { skipCompiler:false,},` |
</IfRenderer>
Expand Down
Loading