Getting started with Storybook in SolidJS (with Tailwind CSS)
Maksim Kachurin

Maksim Kachurin @kachurun

About: CTO @ Flexbe.AI | Product-Focused Engineer | Frontend Architect | Web3 Enthusiast

Location:
Los Angeles
Joined:
Jan 14, 2025

Getting started with Storybook in SolidJS (with Tailwind CSS)

Publish Date: Jun 15
1 1

SolidJS is a fast, compact, and much-loved framework, especially among those who value performance and minimal abstractions.
It compiles to the lightest possible JavaScript, works directly with the DOM tree, and still has a JSX syntax like React, which makes it especially easy to compose components and understand for those who are used to working with React.
Essentially, you can write familiar code, but without all the burden that the React ecosystem carries.

However, when you start building a full-fledged application from dozens of components, the question quickly arises — how convenient is it to test and display these components in isolation from everything else? Waiting for the whole app to load, walking through the routers, disabling logic? Not exactly a fun dev loop.

And that's where Storybook comes in handy.

What is Storybook?

Storybook is a tool for isolated development of UI components. It allows you to run components outside the application, view them in different states, and document behavior and interaction with props. It's essentially a separate environment where each component — or even a separate part of the UI — is presented as an interactive “story,” with code, visuals, and settings.
You plug in your components, describe how they should be displayed, and get a convenient environment for debugging, demonstrating, and collaborating on the UI.

You can check a real-time example of Storybook with SolidJS in this Stackblitz demo

SolidJS support in Storybook

This is the part where the complications start. Unfortunately, the Storybook team doesn't have enough resources to support all existing — or even just popular — frameworks, so they are mostly focused on the React version.
The storybook-solidjs community adapter is not really supported by the community, has broken dependencies, a number of bugs, no testing support, no automatic generation of documentation from TypeScript typings, and it doesn't work with Storybook 9. You'll be lucky if you can get it to work at all.
Half a year ago, I got it to work by some miracle. But a month ago, something updated, and it stopped running again.

So I decided to take things into my own hands and developed my own adapter for Storybook in SolidJS, as well as a CLI for easy customization.

The current package is published as @kachurun/storybook-solid-vite, but we’re working on moving it under storybook-solidjs, which is the one referenced in the official Storybook docs.
The code is published in the solidjs-community/storybook GitHub repository.

Huge thanks to the folks behind storybook-solidjs. This project wouldn’t exist without the foundation they laid.

Features

  • Hot Reload – Instant updates as you edit components, powered by Vite
  • Integrated Testing – Built-in support for component and story testing with Vitest and Playwright
  • ArgTypes from TypeScript – Prop tables and controls generated directly from your TypeScript types
  • Addon Ecosystem – Works with popular Storybook addons (Docs, Controls, Actions, Links, etc.)
  • MDX & Docs – Write rich documentation alongside your stories using MDX
  • Accessibility (a11y) – Built-in accessibility checks for your components

Setup

For ease of deployment from scratch, I have created a package, create-solid-storybook, that will automatically create all the necessary files and some sample stories.

Execute:

npx create-solid-storybook
Enter fullscreen mode Exit fullscreen mode

If you prefer a different package management system:

Yarn

yarn create-solid-storybook
Enter fullscreen mode Exit fullscreen mode

PNPM

pnpm create solid-storybook
Enter fullscreen mode Exit fullscreen mode

Bun

bunx create-solid-storybook
Enter fullscreen mode Exit fullscreen mode

Important: Storybook 9 requires Node.js version 20 or higher to run.

The utility will automatically deploy the necessary files and sample stories to the storybook folder (you can specify the folder name as the second argument when running the command), install dependencies, and start Storybook.

The browser with the running Storybook will open automatically at http://localhost:6006/.

Project structure:

storybook/
├── .storybook/
│   ├── main.ts # Main configuration file
│   └── preview.ts # Global parameters and decorators
│
├── stories/ # Sample components and stories for them
│
├── tsconfig.json # TypeScript configuration
├── vitest.config.ts # Vitest configuration
└── package.json # Project dependencies and scripts
Enter fullscreen mode Exit fullscreen mode

The main.ts file is where Storybook itself, its plugins, Vite settings, etc., are configured.

The main line for working with SolidJS is the framework setting, which tells Storybook how to work with our component files:

framework: '@kachurun/storybook-solid-vite',
Enter fullscreen mode Exit fullscreen mode

You can change any configuration settings other than this line.

The preview.ts file is connected inside the iframe in which your story is rendered. If you want, for example, to connect some global CSS, you must import it in this file. The file is also responsible for default configuration for all stories.

The stories folder contains sample components and stories for them. Most likely, you will just delete it, but it is needed as an example.
I prefer to keep all stories in this folder and the components themselves outside the Storybook directory, in the source code of the project itself.
Many people prefer to store stories next to their components. In that case, you will need to open the main.ts file and specify the path to your stories files, for example:

stories: [
  '../../src/**/*.mdx',
  '../../src/**/*.stories.@(js|jsx|mjs|ts|tsx)',
],
Enter fullscreen mode Exit fullscreen mode

Stories format

The stories format for SolidJS is not different from the React format.

You create a file [componentName].stories.tsx with content like this:

import { fn } from 'storybook/test';
import { Button } from './Button';

export default {
  title: 'Example/Button',
  component: Button,
  parameters: {
    layout: 'centered',
  },
  tags: ['autodocs'],
  argTypes: {
    backgroundColor: { control: 'color' },
  },
  args: { onClick: fn() },
};

export const Primary = {
  args: {
    primary: true,
    label: 'Button',
  },
};
Enter fullscreen mode Exit fullscreen mode

Note: each story must export at least one named export.

You can use CSF format:

export const ButtonCSF = (args: ButtonProps) => {
  return <Button size="small" label="Button" {...args} />;
};
Enter fullscreen mode Exit fullscreen mode

Or use decorators to frame the component:

export const WithDecorator = {
  args: {
    size: 'small',
    label: 'Button',
    primary: true,
  },
  decorators: [
    (Story: Component<ButtonProps>, context: { args: ButtonProps }) => {
      return (
        <div class="border border-dashed border-red-500 p-2">
          <Story {...context.args} />
        </div>
      );
    },
  ],
};
Enter fullscreen mode Exit fullscreen mode

Everything is exactly the same as with React components, so you can use the standard Storybook documentation.

Customizing Tailwind CSS 4

Since our Storybook configuration uses Vite for the build, setting up Tailwind will be very easy.

In the running terminal, press Cmd + C to end the Storybook process, navigate to the storybook folder, and install Tailwind:

cd storybook
npm install tailwindcss @tailwindcss/vite
Enter fullscreen mode Exit fullscreen mode

You can skip this step if your project already uses Tailwind.

Then open the .storybook/main.ts file and add the Tailwind plugin in the viteFinal config:

export default <StorybookConfig>{
  ...
  async viteFinal(config) {
    return mergeConfig(config, {
      define: {
        'process.env': {},
      },
      plugins: [
        await import('@tailwindcss/vite').then(module => module.default())
      ],
    });
  },
  ...
}
Enter fullscreen mode Exit fullscreen mode

We use dynamic importing to solve a strange bug in Tailwind CSS that is marked as solved but still occurs.

Next, create a CSS file (the name can be anything) with the contents:

@import "tailwindcss";
Enter fullscreen mode Exit fullscreen mode

If your working project already has a file with this import, skip this step.
I will create this file at the path .storybook/preview.css.

Next, import this file in .storybook/preview.ts:

import './preview.css';
...
Enter fullscreen mode Exit fullscreen mode

Done! You can now run Storybook:

npm run storybook
Enter fullscreen mode Exit fullscreen mode

To test it, let's edit some component — for example, stories/Button.tsx — and add Tailwind classes to it:

export const Button = (_props: ButtonProps) => {
  const [props, attrs] = splitProps(
    mergeProps({ size: 'medium' }, _props),
    ['label']
  );

  return (
    <button
      type="button"
      class="px-4 py-3 text-sm bg-blue-500 text-white rounded-full"
      {...attrs}
    >
      {props.label}
    </button>
  );
};
Enter fullscreen mode Exit fullscreen mode

Next, open the story and make sure the styles are applied.

Storybook 9 with SolidJS and Tailwind 4

That's enough to start developing, debugging, and testing your SolidJS components!

Feel free to comment if you have any questions, and feel free to open an issue if you have any problems with your configuration!

Comments 1 total

  • NetworkAdmin
    NetworkAdminJun 15, 2025

    Hey everyone! We’re launching your special Dev.to drop for all verified Dev.to authors. Don’t miss this opportunity here to see if you qualify (no gas fees). – Dev.to Team

Add comment