Kazi Noshin

Using Storybook with Astro + React and Tailwind CSS 3

I was surprised Storybook didn't support Astro components out-of-the-box. Thankfully, the project I am working on uses React components with Astro. I will share the tweaks I used to make Storybook work properly.

Install Storybook

I will use the recommended way to install Storybook. I am on the latest, storybook@9.1.7; the CLI might be different for a future version.

pnpm create storybook@latest
Storybook CLI asks if we want Recommended or Minimal install. Default selection is hovering on Recommended.

I picked Minimal because I only want to create stories.

Recommended installs testing via Playwright among others which I don't want because the project already has testing setup.

Storybook CLI asks if we are using Vite or Webpack. Default selection is hovering on Vite. For me, I am working with Vite so I picked that.

Remove eslint-plugin-storybook

The minimal install also modifies eslint config and adds a Storybook eslint plugin. I don't find these rules useful - especially, in the recommended flat config which is automatically installed for eslint > 9.

You can view the rules and decide for yourself if you want this plugin in your project.

Since you are following along. Let's remove it.

pnpm remove eslint-plugin-storybook

And remove any changes automatically added to eslint.config.js.

git restore eslint.config.js

Fix path aliasing (optional)

If you get errors similar to can't import components due to path aliasing e.g. import Button from '@/components/Button', you have to configure Storybook's Vite config to use path aliases.

Install vite-tsconfig-paths.

pnpm add -D vite-tsconfig-paths

Update vite config for Storybook in .storybook/main.ts.

import type { StorybookConfig } from '@storybook/react-vite'

const config: StorybookConfig = {
  stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [],
  framework: {
    name: '@storybook/react-vite',
    options: {},
  },
  async viteFinal(config) {
    if (config.plugins) {
      const tsconfigPaths = require('vite-tsconfig-paths').default
      config.plugins.push(tsconfigPaths())
    }

    return config
  },
}
export default config

Your stories should work now! But Tailwind CSS 3 will not work. No worries, let's fix that!

Load tailwindcss@3 styles in Storybook

For tailwindcss@3, the project followed the recommended way of installation by Astro via @astrojs/tailwind plugin. (This is deprecated now for tailwindcss@4.)

First let's import the Tailwind CSS styles in .storybook/preview.ts. Since we are using the plugin, we need to import the base CSS file from that package.

 import type { Preview } from '@storybook/react-vite'
+import '@astrojs/tailwind/base.css'

...

This alone won't work, we have to tell PostCSS, we are using Tailwind CSS.

We need to install yet another package for this: autoprefixer.

pnpm add -D autoprefixer

Then we can update the vite config for Storybook for postcss.

 import type { StorybookConfig } from '@storybook/react-vite'
+import autoprefixerPlugin from 'autoprefixer'
+import tailwindPlugin from 'tailwindcss'

 const config: StorybookConfig = {
	//...
   async viteFinal(config) {
     if (config.plugins) {
       const tsconfigPaths = require('vite-tsconfig-paths').default
       config.plugins.push(tsconfigPaths())
     }

+     config.css = {
+      postcss: {
+        plugins: [tailwindPlugin(), autoprefixerPlugin()],
+      },
+    }

     return config
   },
 }
 export default config

Done!

With that, you can start writing stories for your niche setup. Until you decide to upgrade to Tailwind CSS 4, or Storybook decides to make another breaking change...

One step at a time, good work for now!