Storybook中CSS组件库交互式文档编写指南
时间:2026-07-17 20:41
为纯CSS类名库在Storybook中编写交互式文档,需手动封装壳组件将类名映射为props,通过argTypes实现参数实时调节。注意在preview js中正确引入CSS文件,并利用MDX展示原生HTML示例。常见问题包括类名拼写错误和CSS加载时机错位。
Storybook 本身并不直接渲染 CSS 组件——它渲染的是 JavaScript 或 TSX 组件。如果您的“CSS 组件库”(例如 Milligram、MDB UI Kit、css.gg)未封装成可导入的 JS 模块,直接编写 `Button.stories.js` 将无法正常运行,可能会报 `ReferenceError` 或显示空白页面。我们需要先确保 CSS 类名在 Storybook 环境中被识别并生效,然后才能添加交互逻辑。接下来,我们将分三步说明操作方法、实现原理以及常见陷阱。
### 如何将纯 CSS 类名转换为 Storybook 可用的组件?
纯 CSS 库(例如 `milligram.min.css`)仅提供类名,不导出任何函数或 React 组件。因此无法直接使用 `import { Button } from 'milligram'`——该库并无此导出。必须手动封装一层“壳组件”,即使仅是一个包含 class 名的空 `div` 也行。例如,Milligram 的按钮组件可以这样封装:
```jsx
export const MilligramButton = ({ label, variant = 'default', disabled = false }) => (
);
```
关键点在于:
- `className` 必须严格匹配原始库的 class 名称——建议查阅官网或源码确认,例如 Milligram 使用 `button` 而非 `btn`。
- 避免在 `.stories.js` 中直接编写 HTML 字符串;Storybook 的 HTML 模式不支持 JSX,但若使用 `@storybook/react` 则必须遵循 React 组件流程。
- 如果库支持 RTL(如 `mdb.rtl.min.css`),需在 `.storybook/preview.js` 中按需引入对应的 CSS 文件。
### 如何让 class 变量可动态调整而非固定?
`argTypes` 控制面板仅作用于组件 props,而非 class 字符串。因此,不能直接设置 `className: { control: 'text' }` 并期望它自动应用到 DOM 上——那只是一个字符串,未绑定逻辑。正确做法是将可变的 class 映射为 prop,然后在组件内部进行条件拼接。例如,css.gg 的 `Airplane` 图标支持 `size` 和 `color` 属性:
```jsx
export const Airplane = ({ size = '24px', color = '#000' }) => (
);
```
对应的 story 中这样配:
```jsx
argTypes: {
size: { control: { type: 'text' } },
color: { control: { type: 'color' } }
}
```
注意几个容易忽略的细节:
- 避免使用 `class` 属性控制尺寸或颜色——CSS 图标库通常依赖内联样式或 data 属性,建议查看 `icons/tsx/Airplane.tsx` 源码确认机制。
- 如果库使用 `data-*` 属性(如 `data-size`),则需在壳组件中透传,不能仅依赖 class。
- `control: 'select'` 适用于有限枚举值(例如 `['sm', 'md', 'lg']`),但需确保这些值在 CSS 中有对应的规则。
### 为什么 Storybook 启动后 CSS 没有生效?
最常见的原因是 CSS 文件未被 Storybook 加载,或加载时机不正确。两个必查点:检查 `.storybook/preview.js` 中是否使用了 `import`?例如 `import 'milligram/dist/milligram.min.css'` —— 该行必须存在且路径正确(`node_modules/milligram/...` 或相对路径)。如果使用 `@storybook/html` 框架,`import` 语句无效,需改用 `preview.js` 的 `parameters.docs.container` 注入 `
` 标签,或在 `main.js` 的 `webpackFinal` 中手动注入 CSS。打开浏览器 DevTools 的 Elements 面板,检查目标元素上是否包含预期的 class,以及是否被其他样式覆盖。若存在优先级冲突,可临时添加 `!important` 调试,但上线前必须移除。
### 如何在 MDX 文档中直接展示原始 HTML 和 class 示例?
有些团队希望设计师能够直接复制原生 HTML,而非 React 组件。此时使用 `.stories.mdx` 更为合适。示例(`Button.stories.mdx`):
```jsx
import { Meta } from '@storybook/blocks';
import { Button } from './MilligramButton';
## 原生用法
## React 封装用法
```
注意:
- `
` 标签必须小写,且不能嵌套 HTML 标签,否则 MDX 解析会失败。
- 若需高亮语法,应使用 `` {`