返回博客

样式插件:在 Storybook 中配置样式和主题

使用样式插件配置您的样式工具并为您的 UI 组件提供主题。

loading
Shaun Evening
@Integrayshaun
最后更新于

如何在 Storybook 中设置样式工具是社区中一个常见的问题。有大量的文章提供指导,但这些文章并不总是最新的。这最终会给您带来不必要的麻烦和大量的试错。

为了简化设置过程,我们推出了样式插件。它是一个与框架无关的解决方案,适用于 Tailwind、Material UI、Chakra、Emotion、Styled-components、SASS 和 PostCSS。

  • 🌎 提供全局样式
  • 🎨 添加主题提供程序
  • 🌗 一键切换主题
  • ‼️ 覆盖某个故事的主题
Switching between light and dark mode using the Styling Addon's theme switcher

入门

根据您使用的是 Storybook 6 还是 Storybook 7,有不同的版本可用。

# For Storybook 6
yarn add -D @storybook/addon-styling

# For Storybook 7
yarn add -D @storybook/addon-styling@next

安装后,打开您的 .storybook/main.js 文件并将 @storybook/addon-styling 添加到 addons 数组中。

module.exports = {
  stories: [
    "../stories/**/*.mdx",
    "../stories/**/*.stories.@(js|jsx|ts|tsx)",
  ],
  addons: [
    "@storybook/addon-essentials",
    "@storybook/addon-styling",
  ],
};

提供全局样式

如果您的全局样式定义在 CSS 文件中,您可以在 .storybook/preview.js 文件中导入您的样式表。Storybook 会在每次故事渲染时加载此处导入的所有文件。

// .storybook/preview.js

import '../src/styles.css'; // Your local styles
import 'bootstrap/dist/css/bootstrap.min.css'; // Styles from node_modules

React 的 UI 库(如 Material UI)将其全局样式作为 React 组件提供。为了使此组件可用于您的组件故事,您可以使用随附的 withThemeFromJSXProvider 装饰器。

// .storybook/preview.js
import { CssBaseline } from "@mui/material";
import { withThemeFromJSXProvider } from "@storybook/addon-styling";

/* snipped for brevity */

export const decorators = [
  withThemeFromJSXProvider({
    GlobalStyles: CssBaseline,
  }),
];

添加主题提供程序

React 库通常附带一个 ThemeProvider 组件,这是一个将主题共享给其子组件的包装器。withThemeFromJSXProvider 将接受该提供程序和您的主题配置,并为您包装所有故事。

// .storybook/preview.js
import { CssBaseline, ThemeProvider } from "@mui/material";
import { withThemeFromJSXProvider } from "@storybook/addon-styling";
import { myCustomTheme } from "../src/theme.js";

/* snipped for brevity */

export const decorators = [
  withThemeFromJSXProvider({
    themes: { myCustomTheme },
    Provider: ThemeProvider,
    GlobalStyles: CssBaseline,
  }),
];

切换主题

用户已经习惯了他们喜爱的应用程序提供多种主题——例如深色模式和高对比度模式。您需要查看您的故事在每种主题下的外观。样式插件为您处理了这个问题!🎉

当您使用多个主题配置 withThemeFromJSXProvider 时,它会在 Storybook 工具栏中添加一个下拉菜单,让您一键在不同主题之间切换。

// .storybook/preview.js
import { CssBaseline, ThemeProvider } from "@mui/material";
import { withThemeFromJSXProvider } from "@storybook/addon-styling";
import {
  myCustomTheme,
  myCustomDarkTheme,
  myCustomHighContrastTheme,
} from "../src/theme.js";

/* snipped for brevity */

export const decorators = [
  withThemeFromJSXProvider({
    themes: {
      light: myCustomTheme,
      dark: myCustomDarkTheme,
      highContrast: myCustomHighContrastTheme,
    },
    defaultTheme: "light",
    Provider: ThemeProvider,
    GlobalStyles: CssBaseline,
  }),
];

不使用 React 或 JSX?没问题!

很大一部分 Storybook 用户不使用 JSX 或 React。如果您是其中一员:别担心!我们为您提供了解决方案!样式插件包含另外两个装饰器,适用于根据父类或数据属性更改主题的用户。

例如,当父元素具有 .dark 类时,Tailwind 允许您激活深色模式。在这种情况下,将您的主题类添加到 withThemeFromClassName 中,并选择一个默认主题来设置主题选择器。

// .storybook/preview.js
import { withThemeByClassName } from "@storybook/addon-styling";

import "../src/tailwind.css";

export const decorators = [
  withThemeByClassName({
    themes: {
      light: "light",
      dark: "dark",
    },
    defaultTheme: "light",
  }),
];

如果您使用的是像 Bootstrap 这样通过 data 属性设置主题的工具,您可以将您的主题、默认主题和属性名称提供给 withThemeFromDataAttribute 来设置主题选择器。

// .storybook/preview.js
import { withThemeByDataAttribute } from "@storybook/addon-styling";
import "bootstrap/dist/css/bootstrap.min.css";

export const decorators = [
  withThemeByDataAttribute({
    themes: {
      light: "light",
      dark: "dark",
    },
    defaultTheme: "light",
    attributeName: "data-bs-theme",
  }),
];

覆盖主题

如果您使用的是像 Chromatic 这样的工具,您可能需要您的故事在应用不同主题时的快照。为此,将 parameters.theming.themeOverride 设置为您希望应用于故事的主题名称。

Switching to the "Primary Dark" story for the story component overrides the theme to dark

配置 CSS 处理工具

CSS 处理工具扩展了 CSS 的功能,以便您可以使用更少的代码获得更多样式效果。这就是为什么我们添加了选项,以便您可以将 Sass 和 Postcss 包含在 Storybook 的 webpack 配置中。如果您使用的是 Storybook 7 并配合 Vite 或 Next.js framework,则已经为您处理了这一点。

Sass

为了替换已弃用的 @storybook/preset-sass,样式插件提供了 Sass 的配置选项。

首先安装一些额外的依赖项

yarn add -D style-loader sass sass-loader resolve-url-loader

然后更新 .storybook/main.js 中的 @storybook/addon-styling 配置以包含 sass

// .storybook/main.js
module.exports = {
  stories: ["../stories/**/*.mdx", "../stories/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-essentials",
    {
      name: "@storybook/addon-styling",
      options: {
        sass: {
          implementation: require("sass"),
        },
      },
    },
  ],
};

现在您可以将 Sass 文件导入到 .storybook/preview.js 中。

// .storybook/preview.js

import '../src/styles.scss';

需要更高级的 Sass 配置?请查看插件文档中关于 options.sass 的完整 API。

PostCSS

为了替换已弃用的 @storybook/preset-postcss,addon-styling 提供了 PostCSS 的配置选项。更新 .storybook/main.js 中的 @storybook/addon-styling 配置以包含 postCss,它将使用您在 postcss.config.js 文件中设置的选项。

// .storybook/main.js
module.exports = {
  stories: ["../stories/**/*.mdx", "../stories/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-essentials",
    {
      name: "@storybook/addon-styling",
      options: {
        postCss: true,
      },
    },
  ],
};

如果您需要用于 Tailwind 的 Postcss 8,请确保安装它,然后将该实现传递给设置中

// .storybook/main.js
module.exports = {
  stories: ["../stories/**/*.mdx", "../stories/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-essentials",
    {
      name: "@storybook/addon-styling",
      options: {
        postCss: {
          implementation: require("postcss"),
        },
      },
    },
  ],
};

配置完成后,您现在可以将您的 Tailwind CSS 文件导入到 .storybook/preview.js 中,并且代码的任何更改都会随着您的故事一起重新构建您的 CSS。

要了解 options.postCss 的完整 API,请查看插件文档

总结

样式插件简化了 Storybook 的配置,以满足您的所有样式需求,例如全局样式、主题提供程序和 CSS 处理工具。该插件允许在主题之间切换以及覆盖特定故事的主题,最棒的是它与框架无关,帮助您以任何您选择的方式交付最佳作品!

虽然这简化了您的样式工具配置,但我们希望让它变得更简单!从 Tailwind 开始,我们正在探索为最流行的库共享 codemods,帮助您自动设置此配置,以便您可以直接开始编写故事。

您对样式插件感到兴奋吗?您还希望看到 Storybook 与其他哪些集成?请在 Twitter 上@storybookjs 或在 Storybook Discord 服务器上与我们联系!我们迫不及待想见到您 🤩

加入 Storybook 邮件列表

获取最新新闻、更新和发布

7,180开发者及以上

我们正在招聘!

加入 Storybook 和 Chromatic 背后的团队。构建被数十万开发者用于生产环境的工具。远程优先。

查看职位

热门文章

Storybook for React Native (6.5)

性能改进,支持组件故事格式、控件和参数。此外还有新的配置文件格式以与 Storybook 核心保持一致。
loading
Daniel Williams

Storybook 7.0

下一代组件开发和测试
loading
Michael Shilman

Storybook for SvelteKit

通过我们的新框架对 SvelteKit 1.0 提供零配置支持
loading
Jeppe Reinhold
加入社区
7,180开发者及以上
原因为何选择 Storybook组件驱动的 UI
文档指南教程更新日志遥测
社区插件参与其中博客
展示探索项目组件词汇表
开源软件
Storybook - Storybook 中文

特别鸣谢 Netlify CircleCI