Storybook Backgrounds 背景配置完全指南:在 .storybook/preview 中自定义颜色选项与初始背景
2026/9/7 10:24:57 网站建设 项目流程

Storybook Backgrounds 背景配置完全指南:在 .storybook/preview 中自定义颜色选项与初始背景

【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook

导读

Backgrounds(背景色)是 Storybook 内置的核心功能,用于控制 Story 在 UI 中渲染时所处的背景颜色,帮助你在不同明暗背景下校验组件表现。本文将围绕当前仓库中docs/_snippets/addon-backgrounds-options-in-preview.md展开,讲解如何通过.storybook/preview.*中的backgrounds.options参数自定义可用的背景色列表,并通过initialGlobals设定初始背景色;同时结合code/core/src/backgrounds下的真实源码,剖析这些配置从参数解析到最终注入样式的底层链路。读完本文,你将能够配置全局背景色板、理解 options 键值与 globals 值之间的对应关系,并为任意组件或单个 Story 做局部覆写。

Backgrounds 功能与默认配置

Backgrounds 功能负责决定每个 Story 渲染时所处的画布背景。在 Storybook 中它是 Essentials 插件之一,相关完整文档见 docs/essentials/backgrounds.mdx。

开箱即用时,该功能内置了明暗两种背景。当前仓库中该功能的实现代码位于 code/core/src/backgrounds,其默认值定义在 code/core/src/backgrounds/defaults.ts:

export const DEFAULT_BACKGROUNDS: BackgroundMap = { light: { name: 'light', value: '#F8F8F8' }, dark: { name: 'dark', value: '#333' }, };

也就是说,工具栏背景色下拉中默认展示两个选项:键light(浅色#F8F8F8)与键dark(深色#333)。文档示例片段中展示的dark: '#333'与源码默认值一致,light的具体色值以你安装版本实际生效值为准。

你并不局限于这组默认色,可以通过.storybook/preview.*中的parameters.backgrounds.options完全自定义自己的色板,并用initialGlobals指定 Storybook 启动后 Story 默认采用的背景色。下面逐步展开。

在 .storybook/preview 中配置全局背景选项

配置入口

背景配置应放在.storybook/preview.js|jsx|ts|tsxparameters中。由于parametersinitialGlobals遵循 Storybook 的层级合并规则,放在preview.*中的配置会对项目中所有组件与所有 Story全局生效。

CSF 3 写法(JavaScript / 通用)
export default { parameters: { backgrounds: { options: { // 👇 Default options dark: { name: 'Dark', value: '#333' }, light: { name: 'Light', value: '#F7F9F2' }, // 👇 Add your own maroon: { name: 'Maroon', value: '#400' }, }, }, }, initialGlobals: { // 👇 Set the initial background color backgrounds: { value: 'light' }, }, };
CSF 3 写法(TypeScript / 通用)
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc. import type { Preview } from '@storybook/your-framework'; const preview: Preview = { parameters: { backgrounds: { options: { // 👇 Default options dark: { name: 'Dark', value: '#333' }, light: { name: 'Light', value: '#F7F9F2' }, // 👇 Add your own maroon: { name: 'Maroon', value: '#400' }, }, }, }, initialGlobals: { // 👇 Set the initial background color backgrounds: { value: 'light' }, }, }; export default preview;

options 对象结构说明

backgrounds.options的类型定义可以在 code/core/src/backgrounds/types.ts 中找到:

export interface Background { name: string; value: string; } export type BackgroundMap = Record<string, Background>;
  • 对象键(如darklightmaroon:背景的标识符,用于在 toolbar 中定位、也用于globals.backgrounds.value的取值匹配。必须保持唯一且字符串形式;
  • name:显示在工具栏下拉菜单中的文案(如DarkLightMaroon);
  • value:实际应用在画布上的 CSS 颜色值,支持任意合法的 CSS 颜色表达(十六进制、rgb()rgba()、命名颜色等)。

示例中先“重写”了默认的两个选项,再新增自定义色maroon。这种写法意味着:preview 级别的 options 会覆盖整个默认色板。若你只需要在默认明暗基础上追加颜色,请在对象中同时保留dark/light键(如示例所示),否则它们会消失。

用 initialGlobals 设置初始背景

initialGlobals负责设置 Storybook 启动时的初始全局状态。对 Backgrounds 而言,其全局状态以backgrounds为命名空间(见 code/core/src/backgrounds/preview.ts):

const initialGlobals: Record<string, GlobalState> = { [PARAM_KEY]: { value: undefined, grid: false }, };

value必须与options中的某个键匹配。例如上面的配置将value设为'light',于是首屏 Story 会直接以浅色背景#F7F9F2渲染,无需手动切换。这一设计也支持仅通过initialGlobals换初始色、而不改动options色板的常见需求。

CSF Next 时代的写法(definePreview)

在 CSF Next 实验语法中,.storybook/preview使用definePreview()包装配置,parametersinitialGlobals的写法保持不变。以下展示当前仓库文档中给出的各渲染器变体。

React
// Replace your-framework with the framework you are using (e.g., react-vite, nextjs, nextjs-vite) import { definePreview } from '@storybook/your-framework'; export default definePreview({ parameters: { backgrounds: { options: { // 👇 Default options dark: { name: 'Dark', value: '#333' }, light: { name: 'Light', value: '#F7F9F2' }, // 👇 Add your own maroon: { name: 'Maroon', value: '#400' }, }, }, }, initialGlobals: { // 👇 Set the initial background color backgrounds: { value: 'light' }, }, });
// Replace your-framework with the framework you are using (e.g., react-vite, nextjs, nextjs-vite) import { definePreview } from '@storybook/your-framework'; export default definePreview({ parameters: { backgrounds: { options: { // 👇 Default options dark: { name: 'Dark', value: '#333' }, light: { name: 'Light', value: '#F7F9F2' }, // 👇 Add your own maroon: { name: 'Maroon', value: '#400' }, }, }, }, initialGlobals: { // 👇 Set the initial background color backgrounds: { value: 'light' }, }, });
Vue 3
import { definePreview } from '@storybook/vue3-vite'; export default definePreview({ parameters: { backgrounds: { options: { // 👇 Default options dark: { name: 'Dark', value: '#333' }, light: { name: 'Light', value: '#F7F9F2' }, // 👇 Add your own maroon: { name: 'Maroon', value: '#400' }, }, }, }, initialGlobals: { // 👇 Set the initial background color backgrounds: { value: 'light' }, }, });
import { definePreview } from '@storybook/vue3-vite'; export default definePreview({ parameters: { backgrounds: { options: { // 👇 Default options dark: { name: 'Dark', value: '#333' }, light: { name: 'Light', value: '#F7F9F2' }, // 👇 Add your own maroon: { name: 'Maroon', value: '#400' }, }, }, }, initialGlobals: { // 👇 Set the initial background color backgrounds: { value: 'light' }, }, });
Angular
import { definePreview } from '@storybook/angular'; export default definePreview({ parameters: { backgrounds: { options: { // 👇 Default options dark: { name: 'Dark', value: '#333' }, light: { name: 'Light', value: '#F7F9F2' }, // 👇 Add your own maroon: { name: 'Maroon', value: '#400' }, }, }, }, initialGlobals: { // 👇 Set the initial background color backgrounds: { value: 'light' }, }, });
Web Components
import { definePreview } from '@storybook/web-components-vite'; export default definePreview({ parameters: { backgrounds: { options: { // 👇 Default options dark: { name: 'Dark', value: '#333' }, light: { name: 'Light', value: '#F7F9F2' }, // 👇 Add your own maroon: { name: 'Maroon', value: '#400' }, }, }, }, initialGlobals: { // 👇 Set the initial background color backgrounds: { value: 'light' }, }, });
import { definePreview } from '@storybook/web-components-vite'; export default definePreview({ parameters: { backgrounds: { options: { // 👇 Default options dark: { name: 'Dark', value: '#333' }, light: { name: 'Light', value: '#F7F9F2' }, // 👇 Add your own maroon: { name: 'Maroon', value: '#400' }, }, }, }, initialGlobals: { // 👇 Set the initial background color backgrounds: { value: 'light' }, }, });

注意:不同渲染器对应不同的包名,示例中的@storybook/your-framework需要替换为实际使用的包(如@storybook/react-vite@storybook/nextjs@storybook/vue3-vite@storybook/angular@storybook/web-components-vite等),具体以 code/addons 及各框架渲染器实际导出的 Preview 类型为准。

底层原理:从 options 到画布背景样式

.storybook/preview里声明的这段配置,最终由 Backgrounds 的预览插件消费。其入口在 code/core/src/backgrounds/preview.ts,通过definePreviewAddon把装饰器withBackgroundAndGrid、默认参数与初始全局状态注册进 Storybook。其中默认参数(code/core/src/backgrounds/preview.ts)为disable: false,grid 默认cellSize: 20opacity: 0.5cellAmount: 5

真正把配置应用出去的是装饰器 code/core/src/backgrounds/decorator.ts,关键处理逻辑可以概括为:

  1. 读取配置:从parameters[backgrounds]解构出options(缺省时回退为DEFAULT_BACKGROUNDS)、disablegrid
  2. 解析全局值:从globals[backgrounds]取出value(兼容字符串或{ value }两种形态,见 types.ts),即当前选中的背景键;
  3. 查表取值:用该键在options中查找对应条目,取value字段作为 CSS 颜色;若找不到匹配,则退化为'transparent'
  4. 注入样式:通过addBackgroundStyle.sb-show-main(story 模式)或 docs 模式下的#anchor--… .docs-story容器注入background: <color> !important;样式(decorator.ts);
  5. 禁用判断shownBackground = !!item && !disable,只有当选中项存在且未禁用该功能时,才会真的渲染背景色。

这解释了为什么initialGlobals.backgrounds.value必须是options的某个键——它本质上是查表的索引。同时也可以看到,当配置的options为空对象或未提供时,代码会自动使用默认的明暗两项作为兜底。

此外,装饰器会遵循系统prefers-reduced-motion设置,仅在允许动画时注入transition: background-color 0.3s(decorator.ts),避免无障碍场景下不必要的色彩过渡。

局部覆写:组件级与 Story 级 options

除了在preview.*全局配置,backgrounds参数遵循 Storybook 的参数继承机制,可在组件 Meta 层单个 Story 层进行局部覆写。

例如,仅针对某个组件的全部 Story 调整色板,可在其Button.stories.ts中配置parameters.backgrounds.options,完整的多渲染器示例见 docs/_snippets/addon-backgrounds-options-in-meta.md,核心思路如下:

const meta = { component: Button, parameters: { backgrounds: { options: { // 👇 Override the default `dark` option dark: { name: 'Dark', value: '#000' }, // 👇 Add a new option gray: { name: 'Gray', value: '#CCC' }, }, }, }, } satisfies Meta<typeof Button>; export default meta;

在该例子中,dark选项在组件层级被改写为#000,并新增gray选项。结合 Storybook 的合并规则,这会对该组件下的所有 Story 生效。

为指定 Story 固定背景(globals)

如果想让某个 Story 永远渲染在指定背景上(例如需要展示“深色模式下”的效果),可以通过globals直接绑定颜色,示例参见 docs/_snippets/addon-backgrounds-define-globals.md:

export default { component: Button, globals: { // 👇 Set background value for all component stories backgrounds: { value: 'gray', grid: false }, }, }; export const OnDark = { globals: { // 👇 Override background value for this story backgrounds: { value: 'dark' }, }, };

需要特别注意:一旦通过globals为某个 Story 指定了backgrounds.value,该颜色会被强制应用,无法再用工具栏切换。这正是 docs/essentials/backgrounds.mdx 中 Callout 提示强调的行为,适合用来保证回归测试或文档页中 Story 始终处于确定底色。若只是想设置“初始显示”的背景、同时保留用户在工具栏切换的自由度,应使用initialGlobals(全局启动态)而不是globals

周边配置速查:disable、grid 与完整 API

理解 preview 配置后,Backgrounds 命名空间下还有几个同源参数常与 options 搭配使用,详见 docs/essentials/backgrounds.mdx 的 API 段落。

disable

类型boolean。置为true可关闭背景功能,典型用法是在某个 Story 上单独关闭,例如 docs/_snippets/addon-backgrounds-disabled.md 中的:

export const Large = { parameters: { backgrounds: { disable: true }, }, };

若需要在整个 Storybook 级别关闭该功能,建议在main.*的 addons 配置中处理而非逐文件配置 disable。在 code/core/src/backgrounds/decorator.ts 可以看到,disable直接参与shownBackground计算,最终决定样式是否注入。

grid

背景网格用于快速核对组件对齐情况。网格没有额外配置也能工作,如需自定义可在parameters.backgrounds.grid中提供,可用属性包括:

属性类型说明
cellAmountnumber次要网格线数量,默认5
cellSizenumber主要网格线尺寸,默认20
disableboolean关闭网格
offsetX/offsetYnumber网格偏移,默认在fullscreen布局下为0padded布局下为16(docs 模式下为20
opacitynumber网格线透明度,默认0.5

完整可运行的网格配置示例见 docs/_snippets/addon-backgrounds-grid.md。该参数与 options 一样支持在 preview、meta、story 各级配置。需要注意区分默认值:preview.ts中插件声明层给出的网格默认值为cellSize: 20 / opacity: 0.5 / cellAmount: 5(preview.ts),而装饰器内部用于兜底的defaultGridcellSize: 100 / cellAmount: 10 / opacity: 0.8(decorator.ts),前者通常先于后者生效。

globals 与 parameters 完整类型

backgrounds全局状态支持两种形态:{ value?: string; grid?: boolean }或直接的value字符串;参数对象结构在 types.ts 中有完整 TypeScript 定义,含defaultdisablegridoptions四个可选字段,其中default用于声明默认背景键,options即本文核心配置项。对比可以发现 docs 与源码在个别历史字段(如default)上可能存在版本差异,以你所安装 Storybook 版本的导出类型为准。

如何验证配置是否生效

配置完成后,可借助仓库中已有的验证资源确认行为:

  • Story 层面:参考模板 Story code/core/template/stories/backgrounds/globals.stories.ts,它演示了通过 globals 声明背景值的标准用法;
  • 端到端测试:查看 code/e2e-sandbox/addon-backgrounds.spec.ts,了解 Playwright 如何断言背景色切换、网格展示与 docs 模式下背景注入等行为;
  • 运行 Storybook 后在工具栏中展开背景下拉,确认自定义色名称(name)与色值列表出现;切换选项后,检查画布容器background的计算样式是否等于对应value

小结

.storybook/preview.*中配置 Backgrounds 是让整个组件库统一背景规范的最直接手段:parameters.backgrounds.options决定“有哪些背景可用”,initialGlobals.backgrounds.value决定“启动时用哪一个”。若需要精确到组件或 Story 粒度,则可配合parameters(改色板)与globals(锁定背景)按层级覆写。结合 code/core/src/backgrounds/decorator.ts 的源码可以看出,这一切配置最终都收敛为一次“按 options 键查表 → 将 CSS 颜色注入预览容器”的简单而可预测的行为,理解这条链路之后,你就能从容定制出贴合团队设计规范的背景工作流。

【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询