This repo is the example of adoption storybook for solid-js.
Thanks to guys from this thread: solidjs/solid-docs#35
Everything works out of the box. Don't forget to render JSX component in your story file to make HMR work (see Counter.stories.tsx
file).
Solid works the best with storybook with @storybook/html-vite configuration. So init your storybook project with HTML type and add the following code:
preview.js
export const decorators = [
(Story) => {
const solidRoot = document.createElement("div");
render(Story, solidRoot);
return solidRoot;
},
];
main.js
export const config = {
// some default fields
// ...
viteFinal(config) {
// make solid work
config.plugins?.unshift(solid({ hot: false }));
return config;
}
};
You need to change the following files.
1. .storybook/main.js
module.exports = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
],
framework: {
name: "@storybook/html-vite",
options: {},
},
docs: {
autodocs: "tag",
},
};
2. .storybook/preview.js
If you want HMR works for solid you need to add /* @refresh reload */
to the beginning of this file however it's not the only change.
See the details below.
/* @refresh reload */
/**
* Don't forget the line above for HMR!
*
* Note: for some reason HMR breaks if you change .stories file,
* however reloading the page fixes this issue
*/
import { render } from "solid-js/web";
export const decorators = [
(Story) => {
const solidRoot = document.createElement("div");
render(Story, solidRoot);
return solidRoot;
},
];
/** Autogenerated by Storybook */
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
That's it!
To make HMR work for your component you need to render it as JSX:
// Correct! HMR works!
// Let's assume that this is storybook meta object
export default {
// ...
render: (props) => <Counter {...props} />,
// ...
} as Meta<ComponentProps<typeof Counter>>;
If you write the code like this, it won't work:
// Wrong! HMR doesn't work!
// Let's assume that this is storybook meta object
export default {
// ...
render: Counter,
// ...
} as Meta<ComponentProps<typeof Counter>>;
Here's an example story for Counter
component.
import { Counter, CounterProps } from "../Counter";
import type { Meta, StoryObj } from "@storybook/html";
import type { ComponentProps } from "solid-js";
type Story = StoryObj<CounterProps>;
export const Default: Story = {
args: {
initialValue: 12,
theme: "default",
},
};
export default {
title: "Example/Counter",
tags: ["autodocs"],
/**
* Here you need to render JSX for HMR work!
*
* render: Counter won't trigger HMR updates
*/
render: (props) => <Counter {...props} />,
argTypes: {
initialValue: { control: "number" },
theme: {
options: ["default", "red"],
control: { type: "radio" },
},
},
} as Meta<ComponentProps<typeof Counter>>;
To see the files for the storybook v6 see THIS.
1. Initialize storybook in your repo as html project:
npx storybook init --type html
main.js
Add vite-plugin-solid
to storybook config.
const Solid = require("vite-plugin-solid");
module.exports = {
stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
],
framework: "@storybook/html",
core: {
builder: "@storybook/builder-vite",
},
features: {
storyStoreV7: true,
},
// Add solid plugin here
async viteFinal(config, { configType }) {
config.plugins.unshift(Solid({ hot: false }));
return config;
},
};
preview.js
Customize your preview.js
file as follows.
import { render } from "solid-js/web";
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
export const decorators = [
(Story) => {
const root = document.getElementById("root");
const solidRoot = document.createElement("div");
solidRoot.setAttribute("id", "solid-root");
root.appendChild(solidRoot);
render(Story, solidRoot);
return solidRoot;
// return createRoot(() => Story()); // do not work correctly https://github.com/solidjs/solid/issues/553
},
];
- .npmrc file is necessary because I use npm v8, however storybook doesn't support it, and that's why it requires this file.