附加元件主題切換

Storybook 附加元件,用於在多個背景之間切換

在 Github 上檢視

Storybook 附加元件主題切換

這個附加元件的靈感來自 @storybook/addon-backgroundsstorybook-addon-themes,並建立了更流暢且功能更豐富的實作。另請參閱 storybook-addon-background-toggle

這個附加元件可用於將自訂 HTML 類別新增至一個或多個目標 HTML 元素。所有選項都在下方說明,請參閱下方的 參數 章節。

https://nickofthyme.github.io/storybook-addon-theme-toggle/ 試用

https://user-images.githubusercontent.com/19007109/128076049-7aca13a8-9e5e-4ce2-9bc0-9f82ab662418.mp4

相容性

此版本與 Storybook 版本 >6.x 相容。

從 Storybook 6.3.0 開始,全域參數會與 URL 同步為查詢搜尋參數 (storybookjs/storybook#15056)。因此,這會鎖定預設全域,並在不同 Story 之間持續存在。如果您想避免此行為,可以使用 storybook@~6.2.0

安裝

yarn

yarn add -D storybook-addon-theme-toggle

npm

npm i -D storybook-addon-theme-toggle

開始使用

安裝後,將此附加元件新增至 Storybook 的 main.js 檔案中的 addons 陣列

// main.js
module.exports = {
  addons: [
    'storybook-addon-theme-toggle'
  ],
};

如需更多資訊,請參閱 Storybook 文件

參數

此外掛程式的參數位於 theme 鍵下,定義如下。

interface Parameters {
  /**
   * Ignores global values in url params
   *
   * @default true
   */
  ignoreQueryParams?: false;
  /**
   * Tefault theme id
   */
  default?: string;
  /**
   * Theme options to be applied
   */
  themes: Theme[];
  /**
   * Selected theme is clearable
   *
   * @default true
   */
  clearable?: boolean;
  /**
   * Disable addon at story level
   *
   * @default false
   */
  disable?: boolean;
  /**
   * Persist theme selection between stories
   *
   * @default false
   */
  persist?: boolean;
  /**
   * Blur tooltip on theme selection
   *
   * @default true
   */
  blurOnSelect?: boolean;
  /**
   * Override icon used in toolbar
   * See https://next--storybookjs.netlify.app/official-storybook/?path=/story/basics-icon--labels
   *
   * @default 'mirror'
   */
  icon?: IconsProps['icon'];
  /**
   * A callback that will be executed when the theme changes
   */
  onChange?: (theme: Theme) => void;
  /**
   * Target element selector(s) to apply class(es)
   *
   * @default 'body'
   */
  selector?: string | string[];
}

Theme 類型定義如下。

interface Theme {
  /**
   * id of the theme
   */
  id: string;
  /**
   * Title of the theme in theme selector ui
   *
   * @default {@link Theme#id}
   */
  title?: string;
  /**
   * Class or classes to be applied to targeted element(s) via selector(s)
   */
  class?: string | string[]
  /**
   * Badge color in the theme selector ui
   */
  color: string;
  /**
   * Url of image to display over color swatch on theme selector
   */
  imageUrl?: string
}

設定

全域層級

您可以在 Storybook 的 preview.(ts|js) 檔案中,於全域層級設定主題,如下所示。

// preview.ts

import type { ThemeParameter } from 'storybook-addon-theme-toggle';

type Parameters = ThemeParameter & {
  // other global parameter types
};

export const parameters: Parameters = {
  theme: {
    default: 'light',
    selector: 'body',
    onChange(theme) {
      // handle new theme
    },
    themes: [
      {
        id: 'light',
        title: 'Light',
        class: 'light',
        color: '#fff',
      },
      {
        id: 'dark',
        title: 'Dark',
        class: 'dark',
        color: '#000',
      },
    ],
  }
};

Story 層級

ThemeParameter 中定義的所有屬性都可以在 Story 層級覆寫。但是,建議只覆寫部分參數,以防止定義可能對所有 Story 的附加元件行為產生負面影響的參數。可接受的屬性包括 defaultblurOnSelectdisableignoreQueryParamsclearableThemeStoryParameter 類型是一個輔助程式,應用於限制在 Story 層級覆寫的屬性;

// story1.stories.tsx

import type { ThemeStoryParameter } from 'storybook-addon-theme-toggle';

const Example = () => <span>Hello!</span>;

Example.parameters: ThemeStoryParameter = {
  theme: {
    default: 'dark',
  }
};

在裝飾器中使用

全域 Storybook 裝飾器 可以用於許多事情。因此,在裝飾器中存取選取的主題非常重要。這也是選擇使用 globals 來維護選取主題狀態的主要原因。

以下是一個簡單的範例,說明如何透過 context.globals 存取主題。

// preview.tsx

import React from "react";

import type { DecoratorFunction } from "@storybook/addons";
import type { ThemeGlobals } from 'storybook-addon-theme-toggle';

const Decorator: DecoratorFunction<JSX.Element> = (Story, context) => {
  const globals = context.globals as ThemeGlobals;
  const selectedTheme = globals.theme;

  return (
    <div>
      <Story {...context} />
      <br />
      <pre>
        Theme: {selectedTheme}
        {JSON.stringify(globals, null, 2)}
      </pre>
    </div>
  );
};

export const decorators = [Decorator];

請在 .storybook/Decorator.tsx 中查看完整的範例。

目前 Storybook 未正確初始化全域變數,這表示它們初始值永遠會回傳 {}。為了修正這個問題,如果全域變數與預設/初始主題 ID 不同,我們會在發出 SET_STORIES 事件後更新全域變數。

框架支援

React
:白色勾號