Skip to content

elite174/storybook-solid-js

Repository files navigation

Storybook for Solid-js example

This repo is the example of adoption storybook for solid-js.

Thanks to guys from this thread: solidjs/solid-docs-next#35

Instructions

Storybook v8

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).

Storybook v7

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!

HMR

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>>;

Storybook v6

To see the files for the storybook v6 see THIS.

1. Initialize storybook in your repo as html project:

npx storybook init --type html

2. Update storybook config files in .storybook folder as follows:

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
  },
];

Comments

  • .npmrc file is necessary because I use npm v8, however storybook doesn't support it, and that's why it requires this file.

About

The basic setup of storybook for solid-js

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published