Storybook 主題擴充功能
深受 @storybook/addon-backgrounds 的啟發。
這個 Storybook 主題裝飾器可以用於在 Storybook 的預覽中加入自訂的 HTML class 或多個 classes。
相容性
此版本與 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 class(es)color
(string
):主題選擇器中徽章的顏色default
[已過時] (boolean
- 選填):是否預設選取此主題?
themes
參數也接受具有以下屬性的物件
default
(string
- 選填):預設選取的主題名稱list
(Theme[]
- 必填):主題清單clearable
(boolean
- 選填 - 預設為true
):使用者是否可以清除所選主題?disable
(boolean
- 選填):針對某個 story 停用此擴充功能Decorator
(Component
- 選填):用作裝飾器元件的元件(關於更多資訊,請參閱下方)onChange
((themeName: Theme) => void
- 選填):主題變更時將執行的回呼函式
設定
全域
您可以在 storybook 的 preview.js
檔案中全域設定主題
export const parameters = {
themes: {
default: 'twitter',
list: [
{ name: 'twitter', class: 'theme-twt', color: '#00aced' },
{ name: 'facebook', class: 'theme-fb', color: '#3b5998' }
],
},
};
為了向後相容,default
(boolean
) 也可以直接在 Theme
物件上設定。這已經過時了,因為需要重新定義所有 Theme
物件,因此很難更改預設主題。
// deprecated
export const parameters = {
themes: [
{ name: 'twitter', class: 'theme-twt', color: '#00aced', default: true },
{ name: 'facebook', class: 'theme-fb', color: '#3b5998' }
],
};
請參閱storybook 文件以取得更多資訊。
在 story 中 (Component Story Format)
或者在您的 story 檔案中設定主題,如下所示
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' },
],
},
},
};
如果您只想針對特定的 story 啟用擴充功能或覆寫主題,您可以寫入
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' },
],
},
},
};
在 story 中 (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>);
以及針對單一 story
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 參數上的單一鍵,例如為單一 story 設定不同的預設值
export default {
title: 'CSF|Button',
component: Button,
};
export const withText = () => <Button onClick={action('clicked')}>Hello Button</Button>;
withText.story = {
parameters: {
themes: {
default: 'facebook',
},
},
};
與裝飾器搭配使用
預設情況下,classes 將會新增到 body
元素。
但在這種情況下,其他擴充功能(例如 @storybook/addon-storyshots)將無法看到您的主題。
若要修正此問題,您可以在您的 story 中新增 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' },
],
},
};
在 story 中 (Component Story Format)
或者在您的 story 檔案中(針對該檔案中的所有 story)
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' },
],
},
},
};
或者僅針對特定 story
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' },
],
},
},
};
在 story 中 (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
:所選主題的格式化主題 classes(如果所選主題上存在class
選項)。themeName
:所選主題的名稱(如果沒有選取任何主題,則等於none
)。
請勿忘記使用 children
prop (React/HTML) 或 <slot></slot>
元素 (Vue/Svelte) 來轉譯 story。
HTML 範例
為了使用 HTML storybook 管理反應性,您的裝飾器必須傳回包含兩個元素的陣列
- 要在 story 中顯示的 HTML 元素
- 主題變更時將呼叫的更新回呼。與裝飾器一樣,回呼將接收相同的 props(不含
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 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
不使用裝飾器的用法 | + | + | + | + | + | + | + | + | + | + | + | |
與裝飾器搭配使用 | + | + | + | + |