文件
Storybook 文件

命名元件和階層

觀看影片教學

Storybook 提供了一種強大的方式來組織您的故事,為您提供必要的工具,可根據您的組織需求和偏好來分類、搜尋和篩選您的故事。

結構和階層

在組織 Storybook 時,有兩種方法可以建構您的故事:隱含顯式隱含方法是依賴您故事的實體位置將其放置在側邊欄中,而顯式方法則是利用 title 參數來放置故事。

Storybook sidebar hierarchy

根據您建構 Storybook 的方式,您可以看到故事階層由不同的部分組成

  • 類別:Storybook 產生的故事和文件頁面的最上層群組
  • 資料夾:在側邊欄中將元件和故事分組的中層組織單位,代表應用程式的功能或區段
  • 元件:代表故事正在測試的元件的低層組織單位
  • 文件:元件的自動產生 文件頁面
  • 故事:測試特定元件狀態的個別故事

命名故事

建立故事時,您可以明確使用 title 參數來定義故事在側邊欄中的位置。它也可用於分組相關元件,在可展開的介面中,協助 Storybook 組織,為您的使用者提供更直觀的體驗。例如

Button.stories.ts
// Replace your-framework with the name of your framework
import type { Meta } from '@storybook/your-framework';
 
import { Button } from './Button';
 
const meta: Meta<typeof Button> = {
  /* 👇 The title prop is optional.
   * See https://storybook.dev.org.tw/docs/configure/#configure-story-loading
   * to learn how to generate automatic titles
   */
  title: 'Button',
  component: Button,
};
 
export default meta;

產生如下結果

Stories hierarchy without paths

分組

也可以在可展開的介面中將相關元件分組,以協助 Storybook 組織。若要執行此動作,請使用 / 作為分隔符號

Button.stories.ts|tsx
// Replace your-framework with the name of your framework
import type { Meta } from '@storybook/your-framework';
 
import { Button } from './Button';
 
const meta: Meta<typeof Button> = {
  /* 👇 The title prop is optional.
   * See https://storybook.dev.org.tw/docs/configure/#configure-story-loading
   * to learn how to generate automatic titles
   */
  title: 'Design System/Atoms/Button',
  component: Button,
};
 
export default meta;
CheckBox.stories.ts|tsx
// Replace your-framework with the name of your framework
import type { Meta } from '@storybook/your-framework';
 
import { CheckBox } from './Checkbox';
 
const meta: Meta<typeof CheckBox> = {
  /* 👇 The title prop is optional.
   * See https://storybook.dev.org.tw/docs/configure/#configure-story-loading
   * to learn how to generate automatic titles
   */
  title: 'Design System/Atoms/Checkbox',
  component: CheckBox,
};
 
export default meta;

產生如下結果

Stories hierarchy with paths

根目錄

預設情況下,最上層群組會在 Storybook UI 中顯示為「根目錄」(即,大寫、不可展開的項目)。如果您需要,可以設定 Storybook 並停用此行為。如果您需要為使用者提供簡化的體驗,這會很有用;然而,如果您有一個由多個元件故事組成的龐大 Storybook,我們建議您根據檔案階層命名元件。

單一故事提升

單一故事元件(即,沒有同層的元件故事),其顯示名稱與元件名稱完全相同(title 的最後一部分)會自動提升,以取代 UI 中的父元件。例如

Button.stories.ts|tsx
// Replace your-framework with the name of your framework
import type { Meta, StoryObj } from '@storybook/your-framework';
 
import { Button as ButtonComponent } from './Button';
 
const meta: Meta<typeof ButtonComponent> = {
  /* 👇 The title prop is optional.
   * See https://storybook.dev.org.tw/docs/configure/#configure-story-loading
   * to learn how to generate automatic titles
   */
  title: 'Design System/Atoms/Button',
  component: ButtonComponent,
};
 
export default meta;
type Story = StoryObj<typeof ButtonComponent>;
 
// This is the only named export in the file, and it matches the component name
export const Button: Story = {};

Stories hierarchy with single story hoisting

因為故事匯出會自動「啟動大小寫」(myStory 會變成 "My Story"),所以您的元件名稱應與此相符。或者,您可以使用 myStory.storyName = '...' 來覆寫故事名稱,使其與元件名稱相符。

故事排序

Storybook 預設會依照故事匯入的順序來排序。不過,您可以透過在 preview.js 檔案的 options 參數中加入 storySort 來客製化此模式,以符合您的需求並提供更直觀的體驗。

.storybook/preview.ts
// Replace your-framework with the framework you are using (e.g., react, vue3)
import { Preview } from '@storybook/your-framework';
 
const preview: Preview = {
  parameters: {
    options: {
      // The `a` and `b` arguments in this function have a type of `import('@storybook/types').IndexEntry`. Remember that the function is executed in a JavaScript environment, so use JSDoc for IntelliSense to introspect it.
      storySort: (a, b) =>
        a.id === b.id ? 0 : a.id.localeCompare(b.id, undefined, { numeric: true }),
    },
  },
};
 
export default preview;

除了唯一的故事識別碼之外,您還可以使用 titlename 和匯入路徑,透過 storySort 函數來排序您的故事。

storySort 也可以接受一個設定物件。

.storybook/preview.ts
// Replace your-framework with the framework you are using (e.g., react, vue3)
import { Preview } from '@storybook/your-framework';
 
const preview: Preview = {
  parameters: {
    options: {
      storySort: {
        method: '',
        order: [],
        locales: '',
      },
    },
  },
};
 
export default preview;
欄位類型描述是否必要預設值範例
method字串告知 Storybook 故事的顯示順序Storybook 設定'alphabetical'
order陣列要顯示的故事,依照提供的名稱排序空陣列 []['Intro', 'Components']
includeNames布林值在排序計算中包含故事名稱falsetrue
locales字串需要顯示的語系系統語系en-US

要依字母順序排序您的故事,請將 method 設定為 'alphabetical',並選擇性地設定 locales 字串。若要使用自訂列表排序您的故事,請使用 order 陣列;不符合 order 列表中項目的故事將會顯示在列表中的項目之後。

order 陣列可以接受巢狀陣列來排序第二層的故事種類。例如

.storybook/preview.ts
// Replace your-framework with the framework you are using (e.g., react, vue3)
import { Preview } from '@storybook/your-framework';
 
const preview: Preview = {
  parameters: {
    options: {
      storySort: {
        order: ['Intro', 'Pages', ['Home', 'Login', 'Admin'], 'Components'],
      },
    },
  },
};
 
export default preview;

這會產生以下的故事順序

  1. Intro 然後是 Intro/* 故事
  2. Pages 故事
  3. Pages/HomePages/Home/* 故事
  4. Pages/LoginPages/Login/* 故事
  5. Pages/AdminPages/Admin/* 故事
  6. Pages/* 故事
  7. ComponentsComponents/* 故事
  8. 所有其他故事

如果您希望將特定的類別排序到列表的末尾,您可以在 order 陣列中插入一個 * 來指示「所有其他故事」應該去哪裡

.storybook/preview.ts
// Replace your-framework with the framework you are using (e.g., react, vue3)
import { Preview } from '@storybook/your-framework';
 
const preview: Preview = {
  parameters: {
    options: {
      storySort: {
        order: ['Intro', 'Pages', ['Home', 'Login', 'Admin'], 'Components', '*', 'WIP'],
      },
    },
  },
};
 
export default preview;

在此範例中,WIP 類別會顯示在列表的末尾。

請注意,order 選項與 method 選項無關;故事會先依照 order 陣列排序,然後依照 method: 'alphabetical' 或預設的 configure() 匯入順序排序。