Storybook framework adapter for SolidJS, using Vite.
Adds SolidJS support to Storybook.
- Solid 1 and Solid 2 support
- Vite-powered builder
- TypeScript-first setup
- ArgTypes generation from TypeScript
- CSF Next factory API (optional)
- Compatible with Storybook addons
- Integrated testing (Vitest, Playwright)
Run in your project:
npx create-storybook --type=solidThen start Storybook:
bun run storybookOpen the URL shown in the terminal.
You can customize Vite and Storybook as usual.
- Add stories in
src/**/*.stories.tsxorsrc/**/*.stories.js - Use Storybook addons for additional functionality
On Solid 1, import from storybook-solidjs-vite in config, preview, and stories:
// .storybook/main.ts
import type { StorybookConfig } from 'storybook-solidjs-vite';
const config: StorybookConfig = {
framework: 'storybook-solidjs-vite',
};
export default config;// .storybook/preview.tsx & stories
import type { Preview, Meta, StoryObj } from 'storybook-solidjs-vite';On Solid 2, use storybook-solidjs-vite/next in preview and stories β the types there match the Solid 2 renderer:
import type { Preview, Meta, StoryObj } from 'storybook-solidjs-vite/next';Imports without /next often still run, but TypeScript may complain because those types describe the Solid 1 renderer.
In main.ts either framework name is fine: storybook-solidjs-vite reads the major version from your installed solid-js, and storybook-solidjs-vite/next forces Solid 2.
framework: 'storybook-solidjs-vite'
framework: 'storybook-solidjs-vite/next'CSF Next works on Solid 1 and Solid 2.
// .storybook/main.ts
import { defineMain } from 'storybook-solidjs-vite/node';
export default defineMain({
framework: { name: 'storybook-solidjs-vite' },
});// .storybook/preview.tsx
import { definePreview } from 'storybook-solidjs-vite';
// for Solid 2, use:
// import { definePreview } from 'storybook-solidjs-vite/next';// src/Button.stories.ts
import preview from '../.storybook/preview';
import { Button } from './Button';
const meta = preview.meta({
component: Button,
});
export const Primary = meta.story({
args: { label: 'Button' },
});TypeScript props for docs and controls are generated with @joshwooding/vite-plugin-react-docgen-typescript.
Configure it with framework.options.docgen in .storybook/main.ts.
false β disable docgen
true (default) β enable docgen with the default configuration
object β override default configuration
import type { StorybookConfig } from 'storybook-solidjs-vite';
const config: StorybookConfig = {
framework: {
name: 'storybook-solidjs-vite',
options: {
docgen: {
savePropValueAsString: true,
shouldExtractLiteralValuesFromEnum: true,
propFilter: (prop: any) =>
prop.parent ? !/node_modules/.test(prop.parent.fileName) : true,
},
},
},
};
export default config;On args or globals changes, Storybook re-runs decorators and stories β the same model as React, where each update calls your functions again. Solid updates through fine-grained signals and usually does not need that.
If a decorator returns JSX, the extra runs can leave duplicate nodes in the DOM.
Use for decorators that return JSX. Ensures they run only once per story mount.
import { createJSXDecorator } from 'storybook-solidjs-vite';
export const decorator = createJSXDecorator((Story) => {
return (
<main>
<Story />
</main>
);
});Use for decorators that do not return JSX.
import { createDecorator } from 'storybook-solidjs-vite';
export const decorator = createDecorator((Story) => {
return Story();
});import { IS_SOLID_JSX_FLAG } from 'storybook-solidjs-vite';
export const decorator = (Story) => {
return <div><Story /></div>;
};
decorator[IS_SOLID_JSX_FLAG] = true;Check out Migration Guide for the instructions and breaking changes.
Contributions, issues and feature requests are welcome! Feel free to open an issue or submit a PR.
MIT
Maintained with β€οΈ by @kachurun
