改头换面

Storybook 的主题、主题提供者和真正的深色模式

在 Github 上查看

Storybook 的主题、主题提供者和真正的深色模式

Storybook Facelift 是零配置的 - 它将只为原生主题返回一个亮/暗模式按钮

但您也可以

安装

npm i -D storybook-facelift

配置插件

将插件添加到您的 Storybook main.js 文件(或 main.ts - 从现在开始,我们将只假设为 js...)

module.exports = {
  addons: ['storybook-facelift'],
}

为了充分利用插件,您可能希望通过 preview.js 中的参数对其进行配置。

export const parameters = {
  facelift: {...},
}

TypeScript 支持示例

Storybook Facelift 提供了一个自定义的 Parameters 类型来帮助您在参数中获得类型安全。

它接受一个泛型,让您可以从其他插件添加更多参数类型并保留 Storybook 参数类型安全

import type { Parameters } from 'storybook-facelift'
import type { OtherAddonParam } from 'other-addon'

export const parameters: Parameters<{
  otherAddon: OtherAddonParam,
}> = {
  actions: { argTypesRegex: '^on[A-Z].*' },
  otherAddon: {...},
  facelift: {...},
}

配置 Story

您也可以在 Story 级别配置 Storybook Facelift,例如,在 Story 级别而不是全局级别启用使用主题提供者的自动主题化,甚至可能为此 Story 添加一个特殊的主题提供者

import React from 'react'
import { Tag } from './Tag'

export default {
  title: 'UI/Tag',
  component: Tag,
  parameters: {
    facelift: {
      addProvider: true,
      provider: 'styled',
      providerTheme: 'theme-1',
    },
  },
}

const Template = (args) => <Tag {...args} />

export const Controllable = Template.bind({})
Controllable.args = {
  label: 'Tag',
}

TypeScript 支持示例

Storybook Facelift 提供了一个自定义的 Meta 类型来帮助您在 Story 参数中获得类型安全。

此类型接受 2 个泛型参数,额外的参数类型和 Storybook 自己的 Args(遗憾的是,如果您希望应用 Args 泛型并且没有额外的插件参数类型需要提供,则必须提供一个空对象作为第一个泛型)

import React from 'react'
import { Tag } from './Tag'

import type { Story } from '@storybook/react'
import type { Meta } from 'storybook-facelift'
import type { TagProps } from './Tag'
import type { OtherAddonParam } from 'other-addon'

export default {
  title: 'UI/Tag',
  component: Tag,
  parameters: {
    otherAddon: {...},
    facelift: {...},
  },
} as Meta<{otherAddon: OtherAddonParam}>

const Template: Story<TagProps> = (args) => <Tag {...args} />

export const Controllable = Template.bind({})
Controllable.args = {
  label: 'Tag',
}

插件参数

"addProvider"?: boolean
"autoThemeStory"?: boolean // deprecated - use addProvider
"defaultTheme"?: string
"defaultVariant"?: "light" | "dark"
"docs"?: ParamDocs
"enhanceUi"?: boolean
"includeNative"?: boolean
"native"?: ParamNative
"override"?: ThemeOptionsOverride
"provider"?: "mui" | "styled" | "emotion"
"providerTheme"?: string
"themeConverters"?: Record<string, ThemeConverterFn>
"themes"?: ParamTheme[]
"ui"?: ParamUi

addProvider boolean

启用主题提供者(全局或 Story 级别)

defaultTheme string

Storybook 启动时使用的默认主题 - 主题参数中的键用作参考

defaultVariant "light" | "dark"

用于 Storybook 主题的默认主题变体

docs ParamDocs

增强的文档控制

// Set to true to hide the column borders in docs table
"hidePropertyBorders"?: boolean

// Set to true to hide description column in docs table
"hideDescription"?: boolean

// Set to true to hide default value column in docs table
"hideDefaults"?: boolean

// Set to true to hide the controls column in docs
"hideControls"?: boolean

// Set to true to hide the sibling stories shown below property table
"hideStories"?: boolean

// Set to either full or simple - full is default, and simple will ONLY show docs table
"type"?: "full" | "simple"

enhanceUi boolean

修复一些轻微的 CSS 错误,并允许使用 ui 参数

includeNative boolean

如果提供了自定义主题,则将此参数设置为 true 以包含原生 Storybook 主题

override ThemeOptionsOverride

Storybook 主题选项对象,它将扩展到用作所有主题创建默认值的默认 Storybook 主题选项上

此处添加的任何值都将在最终主题输出中,除非值稍后被覆盖(通常所有值都除外 brandTitlebrandUrlbrandImage

"colorPrimary"?: string
"colorSecondary"?: string
"appBg"?: string
"appContentBg"?: string
"appBorderColor"?: string
"appBorderRadius"?: number
"fontBase"?: string
"fontCode"?: string
"textColor"?: string
"textInverseColor"?: string
"textMutedColor"?: string
"barTextColor"?: string
"barSelectedColor"?: string
"barBg"?: string
"inputBg"?: string
"inputBorder"?: string
"inputTextColor"?: string
"inputBorderRadius"?: number
"brandTitle"?: string
"brandUrl"?: string
"brandImage"?: string
"gridCellSize"?: number

native ParamNative

一些简单的方便参数来调整原生主题,以及通过 override 进行完全控制

// Title to show in the menu picker
"title"?: string

// Control which theme variants are available - defaults to ["light", "dark"]
"variants"?: ("light" | "dark")[]

// Control the usage of Storybooks theme values in the backgrounds
"background"?: "normal" | "reverse" | "equal" | "equal-reverse" | "equal-app" | "equal-content"

// Override any default native theme options from Storybook
"override"?: ThemeOptionsOverride

themeConverters Record<string, ThemeConverterFn>

提供自定义转换器函数,将您的自定义主题转换为 Storybook 主题

函数的键将使转换器可以通过主题的 converter 选项访问

转到 示例 以了解如何实现自定义主题

[key]: (props: {
  "override"?: ThemeOptionsOverride
  "theme": ThemeOptions
  "variant": "light" | "dark"
  "background"?: "normal" | "reverse" | "equal" | "equal-reverse" | "equal-app" | "equal-content"
  "responsiveFontSizes"?: boolean
}) => {
  "storybook": StorybookThemeOptions
  "instanciated": ThemeInstanciated
  "options": ThemeOptions
} | null

themes ParamTheme[]

主题配置

// Unique key for this theme entry
"key": string

// Use the built in support of Storybook or Material UI
// Or indicate you are providing a custom theme
"type": "native" | "mui" | "custom"

// The title used in the theme picker
"title": string

// The name of the converter function to use - if the theme type
// is "mui" or "native" you do not need to set this
"converter"?: string

// The theme provider to use for this theme if "addProvider" for story is true
"provider"?: "mui" | "styled" | "emotion"

// The key of the theme to use for the theme provider if "addProvider" is true
"providerTheme"?: string

// Indicate that this theme is only to be used for theme providers - not to theme Storybook
"providerOnly"?: boolean


// These are the theme options for light and/or dark mode.
"variants": {
  "light"?: ThemeOptions
  "dark"?: ThemeOptions
}

// Override any Storybook theme options value for this theme
"override"?: ThemeOptionsOverride

// Ability to configure how backgrounds are used in the Storybook theme
// 'reverse' will swap between app and content etc..
"background"?: "normal" | "reverse" | "equal" | "equal-reverse" | "equal-app" | "equal-content"

// This is for typography - use responsive font sizes or not (only MUI support)
"resposiveFontSizes"?: boolean

ui ParamUi

// How much to elevate the content panel
"elevation"?: 0 | 1 | 2 | 3 | 4

// Ability to override SB's own preview panel padding
"padding"?: string

// Ability to use a custom css box-shadow string for content elevation
"shadow"?: string

示例

仅包含亮变体的最小原生 Storybook 主题

export const parameters = {
  facelift: {
    themes: [
      {
        key: 'native-1',
        type: 'native',
        title: 'Custom Storybook theme',
        variants: {
          light: {
            colorPrimary: '#0000ff',
          },
        },
      },
    ],
  },
}

带有默认 Material UI 亮/暗主题的示例

使用默认 Material UI 主题的 Storybook 主题,并为所有 Story 添加具有相同主题的 Material UI 主题提供者

export const parameters = {
  facelift: {
    addProvider: true,
    themes: [
      {
        type: 'mui',
        key: 'mui-1',
        title: 'Default Material UI theme',
        variants: {
          light: {},
          dark: {},
        },
      },
    ],
  },
}

带有自定义亮主题和 Styled Components 主题提供者的示例

这个非常简单的示例将以一个最小的自定义主题对 Storybook 进行主题化,并向 Story 添加一个 Style Components 主题提供者

export const parameters = {
  facelift: {
    addProvider: true,
    themeConverters: {
      myCustomConverter: ({ theme, variant }) => ({
        storybook: {
          base: variant,
          colorPrimary: theme.primary,
          colorSecondary: theme.secondary,
        },
        options: theme,
        instanciated: theme,
      }),
    },
    themes: [
      {
        type: 'custom',
        key: 'custom-1',
        title: 'Custom UI theme',
        converter: 'myCustomConverter',
        provider: 'styled',
        variants: {
          light: {
            primary: '#ff0000',
            secondary: '#0000ff',
          },
        },
      },
    ],
  },
}