Storybook is an essential tool for building, testing, and documenting UI components. It opens the doors to faster front-end development, team collaboration, and a consistent design language across websites. In this article, we will cover how Storybook works, how to integrate Storybook in Drupal, how to handle components, and how to use Single Directory Components (SDC) in Drupal 10+.
Quick answer: Storybook is an open-source tool for building, testing, and documenting UI components in isolation. It is not part of Drupal core, but it integrates with a Drupal theme through the Drupal Storybook module or a Twig bridge such as vite-plugin-twig-drupal, and it works well with Single Directory Components (SDC) in Drupal 10+. Storybook runs separately from your site, so it speeds up development without affecting production.
What is Storybook?
Storybook is an open-source tool for developing, testing, and documenting UI components in isolation. Think of Storybook like a digital catalog for your website's building blocks. It runs as a standalone app where you can view, interact with, and test components without needing the full application (Drupal in this case). It supports components like buttons, cards, forms, etc. It uses "stories" to support component attributes such as button in "normal", or button in "hover" mode. Storybook supports frameworks like React, Vue, or plain HTML/Twig.
In Drupal, Storybook bridges the gap between frontend design and backend content management. Drupal themes use Twig templates for rendering content, and Storybook can preview these templates independently, which makes building reusable components consistent, easy, and sick!
Why use Storybook with Drupal themes?
Storybook is worth adding to Drupal theme development because it lets you build, preview, and document components without loading the full site. Storybook isn't native in Drupal, but integrating it will supercharge theme development.
- Isolated testing environment: You can tweak and preview parts of your website without logging into Drupal.
- Collaboration hub: Designers, developers, and stakeholders can browse and interact with a library of components without the need to send screenshots :)
- Consistency and reusability: Storybook ensures your theme's elements look and behave the same anywhere in the website.
- Built-in documentation: Storybook auto-generates docs from your code, so new members can quickly understand theme components even when complex.
- Technical perks: It supports addons for accessibility testing with axe-core, visual regression checks, and API mocking. It integrates with Drupal's Twig via tools like Twig.js to allow client-side rendering of server-side templates.
How do components work in Drupal Storybook?
In Drupal Storybook, a component is a small, reusable piece of UI represented by a "story". Components (like LEGO bricks) are small, reusable pieces that snap together to form a structure. In a Drupal theme, a card component is simply a reusable box that contains an image, a title, and some text. This component lives in a folder containing YAML metadata, Twig template, CSS/SCSS, JS, or any related asset. This highly modular approach not only separates all our concerns, but ensures that assets are auto loaded whenever the component is invoked.
In Storybook, a component is represented by "story", each story can have multiple variations (e.g. card with image / card without image). Components are implemented by:
- Creating a directory for each component (e.g. components/card)
- Adding files .twig for markup, .stories.js or .stories.twig for previews, and .yml data and props.
- By using tools like Twig.js or the Drupal Storybook module.
How do you set up Storybook for a Drupal theme?
You set up Storybook for a Drupal theme in six steps: install the module, configure the environment, set up Storybook in your theme, create a component and story, integrate the component into Drupal, then run and use Storybook.
Step 1: Install the Drupal Storybook module
- Run
composer require 'drupal/storybook:^1.0'
- Enable the module:
drush en storybook -y
- Grant permissions:
drush role:perm:add anonymous 'render storybook stories'
- For pure frontend, skip the module and use Twig.js directly
Step 2: Configure your environment
Edit development.services.yml (create if missing in sites/):
parameters:
twig.config:
debug: true
cache: false
storybook.development: true
cors.config:
enabled: true
allowedHeaders: ['*']
allowedMethods: ['*']
allowedOrigins: ['*']
exposedHeaders: false
maxAge: false
supportsCredentials: true
- Disable caches:
drush state:set twig_debug 1, drush state:set twig_cache_disable 1, drush state:set disable_rendered_output_cache_bins 1
- Rebuild cache:
drush cr
Step 3: Set up Storybook in your theme
- Navigate to your theme (e.g., themes/custom/my_theme/).
- Install Storybook:
npx storybook@latest init --type html (or --type server for server-side).
- Install Twig bridge:
npm i -D vite-plugin-twig-drupal twig-drupal-filters html-react-parser @modyfi/vite-plugin-yaml
Update your vite.config.js:
import { defineConfig } from "vite";
import yml from '@modyfi/vite-plugin-yaml';
import twig from 'vite-plugin-twig-drupal';
import { join } from "node:path";
export default defineConfig({
plugins: [
twig({
namespaces: {
components: join(__dirname, "components"),
},
}),
yml(),
],
});
Update .storybook/main.js for stories path: stories: ["../components/**/*.stories.@(js|jsx)"]
Add Drupal filters to .storybook/preview.js:
import Twig from 'twig';
import drupalFilters from 'twig-drupal-filters';
function setupFilters(twig) {
twig.cache();
drupalFilters(twig);
return twig;
}
setupFilters(Twig);
For Yarn users: yarn set version berry, then yarn dlx sb init --builder webpack5 --type server
Step 4: Create your first component and story
- Create folder: components/card/
- Add file card.component.yml (SDC metadata)
name: Card
props:
type: object
required:
- title
properties:
title:
type: string
title: Title
slots:
content:
title: Content
card.twig (template):
<div class="card">
<h2>{{ title }}</h2>
{{ content }}
</div>
card.stories.twig or card.stories.js:
import parse from 'html-react-parser';
import card from './card.twig';
import data from './card.yml';
export default { title: 'Components/Card' };
export const Default = () => parse(card(data));
- card.css for styles
- Generate stories (if using module):
drush storybook:generate-all-stories
Step 5: Integrate components into Drupal
In your theme's .info.yml, add namespaces:
components:
namespaces:
atoms: components/01-atoms
molecules: components/02-molecules
In templates (e.g., node.html.twig): {% include '@molecules/card/card.twig' with { title: node.title.value } %}
Attach libraries in .libraries.yml:
card:
css:
component:
dist/css/card.css: {}
Use in render arrays or blocks, as needed.
Step 6: Run and use Storybook
- Start:
npm run storybook.
- Browse components, toggle states, and test interactions.
- For live watching:
watch drush storybook:generate-all-stories
- Build for production:
npm run build-storybook
varTips
- Organize components as atoms, basic for buttons, molecules for forms, organisms for sections.
- For CORS issues, double-check configs, test in isolation first.
- Use addons like @lullabot/storybook-drupal-addon for deeper integration.
- For migration from Pattern Lab, recreate components in Storybook folders.
- Keep components platform-agnostic.
- Use Faker.js for mock data.
- Enable autodocs for automatic documentation.
- Always disable dev mode in production.
Varbase and Storybook in Drupal
Varbase is Storybook production-ready. Varbase Storybook design system and UI component library gives teams a single source of truth for consistent, customizable, and accessible interfaces. It ships with reusable documented components, aligned with WCAG standards and performance best practice.
Photo by DS stories