Storybook 擴充套件主題
深受 @storybook/addon-backgrounds 的啟發。
這個 Storybook 主題裝飾器可用於在 Storybook 的預覽中新增自訂 HTML 類別或多個類別。
相容性
此版本與 storybook 版本 6.0.x
相容。
安裝
npm i -D storybook-addon-themes
開始使用
然後將其新增到 storybook main.js
檔案(位於 Storybook 設定目錄中),以啟用此擴充套件
module.exports = {
addons: [
// Maybe other addons here...
'storybook-addon-themes'
// Or here...
],
};
請參閱 storybook 文件 以取得更多資訊。
參數
themes
參數接受 Theme
物件的陣列。
每個 Theme
都是一個具有以下屬性的物件
name
(string
):主題名稱class
(string | string[]
- 選用):與主題相關聯的 HTML 類別color
(string
):主題選取器中徽章的顏色default
[已棄用] (boolean
- 選用):是否預設選取主題?
themes
參數也接受具有以下屬性的物件
icon
(string
- 選用 - 預設為'mirror'
):在工具列中用於擴充套件的圖示(選項)default
(string
- 選用):預設選取的主題名稱list
(Theme[]
- 必要):主題清單clearable
(boolean
- 選用 - 預設為true
):使用者是否可以清除選取的主題?disable
(boolean
- 選用):為故事停用此擴充套件Decorator
(Component
- 選用):用作裝飾器元件的元件(請參閱下方以取得更多資訊)onChange
((themeName: Theme) => void
- 選用):主題變更時將執行的回呼target
(string
- 選用):使用document.querySelector()
選取並套用類別的目標元素。預設為body
,如果類別應套用至documentElement
,則為root
。
組態
全域
您可以在 storybook preview.js
檔案中全域設定主題
export const parameters = {
themes: {
default: 'twitter',
list: [
{ name: 'twitter', class: 'theme-twt', color: '#00aced' },
{ name: 'facebook', class: 'theme-fb', color: '#3b5998' }
],
},
};
為了向後相容,也可以直接在 Theme
物件上設定 default
(boolean
)。由於需要重新定義所有 Theme
物件才能變更預設主題,因此這已被棄用。
// deprecated
export const parameters = {
themes: [
{ name: 'twitter', class: 'theme-twt', color: '#00aced', default: true },
{ name: 'facebook', class: 'theme-fb', color: '#3b5998' }
],
};
請參閱 storybook 文件 以取得更多資訊。
在故事中(元件故事格式)
或在您的故事檔案中設定主題,如下所示
export default {
title: 'CSF|Button',
component: Button,
parameters: {
themes: {
default: 'twitter',
list: [
{ name: 'twitter', class: ['theme-twt', 'light-mode'], color: '#00aced' },
{ name: 'facebook', class: ['theme-fb', 'dark-mode'], color: '#3b5998' },
],
},
},
};
如果您只想為特定故事啟用擴充套件或覆寫主題,您可以寫入
export default {
title: 'CSF|Button',
component: Button,
};
export const withText = () => <Button onClick={action('clicked')}>Hello Button</Button>;
withText.story = {
parameters: {
themes: {
default: 'twitter',
list: [
{ name: 'twitter', class: ['theme-twt', 'light-mode'], color: '#00aced' },
{ name: 'facebook', class: ['theme-fb', 'dark-mode'], color: '#3b5998' },
],
},
},
};
在故事中(StoriesOf API)
或者使用舊的 StoriesOf API
import { storiesOf } from '@storybook/react'; // <- or your storybook framework
storiesOf('StoriesOf|Button', module)
.addParameters({
themes: {
default: 'twitter',
list: [
{ name: 'twitter', class: ['theme-twt', 'light-mode'], color: '#00aced' },
{ name: 'facebook', class: ['theme-fb', 'dark-mode'], color: '#3b5998' },
],
},
})
.add('with text', () => <button>Click me</button>);
以及針對單一故事
import { storiesOf } from '@storybook/react';
storiesOf('StoriesOf|Button', module)
.add('with text', () => <button>Click me</button>, {
themes: {
list: [
{ name: 'red', class: 'theme-red', color: 'rgba(255, 0, 0)' },
],
},
});
覆寫單一屬性
您也可以只覆寫 themes 參數中的單一鍵,例如為單一故事設定不同的預設值
export default {
title: 'CSF|Button',
component: Button,
};
export const withText = () => <Button onClick={action('clicked')}>Hello Button</Button>;
withText.story = {
parameters: {
themes: {
default: 'facebook',
},
},
};
搭配裝飾器使用
預設情況下,類別會新增到 body
元素或使用 target
設定的元素。
但在這種情況下,其他擴充套件(例如 @storybook/addon-storyshots)將看不到您的主題。
若要修正此問題,您可以在故事中新增 withThemes
裝飾器。
但是裝飾器方法並非適用於所有框架
請參閱此處以取得支援框架的清單。
全域
在 preview.js
檔案中全域設定裝飾器
import { addDecorator } from '@storybook/react'; // <- or your storybook framework
import { withThemes } from 'storybook-addon-themes/react'; // <- or your storybook framework
addDecorator(withThemes);
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
themes: {
default: 'twitter',
list: [
{ name: 'twitter', class: ['theme-twt', 'light-mode'], color: '#00aced' },
{ name: 'facebook', class: ['theme-fb', 'dark-mode'], color: '#3b5998' },
],
},
};
在故事中(元件故事格式)
或在您的故事檔案中(針對該檔案中的所有故事)
export default {
title: 'CSF|Button',
component: Button,
decorators: [ withThemes ],
parameters: {
themes: {
default: 'twitter',
list: [
{ name: 'twitter', class: ['theme-twt', 'light-mode'], color: '#00aced' },
{ name: 'facebook', class: ['theme-fb', 'dark-mode'], color: '#3b5998' },
],
},
},
};
或僅針對特定故事
export const withText = () => <Button onClick={action('clicked')}>Hello Button</Button>;
withText.story = {
decorators: [ withThemes ],
parameters: {
themes: {
default: 'twitter',
list: [
{ name: 'twitter', class: ['theme-twt', 'light-mode'], color: '#00aced' },
{ name: 'facebook', class: ['theme-fb', 'dark-mode'], color: '#3b5998' },
],
},
},
};
在故事中(StoriesOf API)
或者使用舊的 StoriesOf API
import { storiesOf } from '@storybook/react'; // <- or your storybook framework
import { withThemes } from 'storybook-addon-themes/react';
storiesOf('StoriesOf|Button', module)
.addDecorator(withThemes)
.add('with text', () => <button>Click me</button>);
自訂裝飾器
一般
您可以使用 theme
參數中的 Decorator
選項來提供將用作裝飾器的元件。
裝飾器將取得以下屬性
theme
:選取的主題,如果未選取任何主題則為undefined
。themes
:theme
參數的list
選項中提供的主題清單。themeClasses
:選取主題的格式化主題類別(如果選取主題中存在class
選項)。themeName
:選取主題的名稱(如果未選取任何主題則等於none
)。
別忘了使用 children
屬性 (React/HTML) 或 <slot></slot>
元素 (Vue/Svelte) 來呈現故事。
HTML 範例
若要使用 HTML storybook 管理反應性,您的裝飾器必須傳回包含兩個元素的陣列
- 要在故事中顯示的 HTML 元素
- 主題變更時將呼叫的更新回呼。如同裝飾器,回呼將接收相同的屬性(不含
children
)。
使用 CSS 檔案變更主題的自訂裝飾器範例
function getOrCreate(id) {
const elementOnDom = document.getElementById(id);
if (elementOnDom) {
return elementOnDom;
}
const element = document.createElement('link');
element.setAttribute('id', id);
element.setAttribute('rel', 'stylesheet');
return element;
}
function Decorator(props) {
const { children } = props;
function setStyles({ theme, themeName }) {
const link = getOrCreate('theme-stylesheet');
if (!theme) {
link.parentNode && link.parentNode.removeChild(link);
} else {
link.href = themeName === 'facebook' ? 'Button-fb.css' : 'Button-twt.css';
children.appendChild(link);
}
}
setStyles(props);
return [children, setStyles];
}
React 範例
與上述相同的 React 範例
function Decorator(props) {
const { children, themeName } = props;
return (
<>
{children}
{themeName === 'twitter' && <link rel="stylesheet" href="twitter.css"/>}
{themeName === 'facebook' && <link rel="stylesheet" href="facebook.css"/>}
</>
);
};
框架支援表
React | React Native | Vue | Angular | Polymer | Mithril | HTML | Marko | Svelte | Riot | Ember | Preact | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
不使用裝飾器的用法 | + | + | + | + | + | + | + | + | + | + | + | |
搭配裝飾器使用 | + | + | + | + |