如何在Storybook中为HTML元素添加类切换控件以实现主题切换
Absolutely! You can absolutely add a theme toggle control to your Storybook stories that modifies HTML element classes to switch Tailwind themes—here's a step-by-step guide tailored to your needs:
1. Use Storybook Controls + Decorators for Core Logic
Storybook's decorators let you wrap components and inject dynamic behavior, while the Controls addon gives you interactive UI elements to tweak settings. We’ll build a decorator that listens to control inputs and updates the root HTML element’s classes in real time.
First, make sure the Controls addon is enabled (it’s default in Storybook 6+, but if not, add @storybook/addon-controls to your addons list in .storybook/main.js).
Add a Global Decorator (For All Stories)
To apply the theme toggle to every story, add this to .storybook/preview.js:
export const decorators = [ (Story, context) => { // Grab the selected theme from the control's args const selectedTheme = context.args.theme; // Define all possible theme classes your library uses const allThemes = ['theme-light', 'theme-dark', 'theme-accent-blue']; // Clean up: Remove all existing theme classes first allThemes.forEach(themeClass => { document.documentElement.classList.remove(themeClass); }); // Add the selected theme class to the root HTML element if (selectedTheme) { document.documentElement.classList.add(selectedTheme); } return <Story />; }, ]; // Define the global control for theme selection export const argTypes = { theme: { control: { type: 'select' }, // Dropdown menu options: ['theme-light', 'theme-dark', 'theme-accent-blue'], defaultValue: 'theme-light', description: 'Switch the component theme by adding/removing HTML classes' }, };
Now every story’s Controls panel will have a dropdown to pick a theme—selecting an option instantly adds/removes the corresponding class from the <html> element, triggering your Tailwind theme styles.
2. Customize Theme Options for Individual Stories
If some components only support specific themes, override the global argTypes in your story file:
import Button from './Button'; export default { title: 'Components/Button', component: Button, argTypes: { theme: { options: ['theme-light', 'theme-dark'], // Restrict to only these two defaultValue: 'theme-light' } } }; // Story template const Template = (args) => <Button {...args} />; export const Primary = Template.bind({}); Primary.args = { label: 'Primary Button' };
3. Optional: Use Radio Buttons Instead of a Dropdown
Prefer a more visual toggle? Switch the control type to inline-radio for button-style selection:
export const argTypes = { theme: { control: { type: 'inline-radio' }, options: ['theme-light', 'theme-dark', 'theme-accent-blue'], defaultValue: 'theme-light' }, };
Key Notes for Tailwind Setup
Make sure your tailwind.config.js is configured to recognize your theme classes. For example:
module.exports = { darkMode: 'class', // If using dark mode via class, or adjust for custom themes theme: { extend: { colors: { primary: { light: '#f59e0b', dark: '#92400e', blue: '#3b82f6' } } } } };
If you apply theme classes to <body> instead of <html>, just replace document.documentElement with document.body in the decorator code.
This setup gives you a seamless, interactive way to preview your components across all themes directly in Storybook!
内容的提问来源于stack exchange,提问作者ahmaxed

