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
參數也接受具有以下屬性的物件
default
(string
- 選用):預設選取的主題名稱list
(Theme[]
- 必要):主題列表clearable
(boolean
- 選用 - 預設值為true
):使用者是否可以清除選取的主題?disable
(boolean
- 選用):停用故事的外掛Decorator
(Component
- 選用):用作裝飾器元件的元件(更多資訊請參閱下方)onChange
((themeName: Theme) => void
- 選用):當主題變更時將執行的回呼target
(string
- 選用):使用document.querySelector()
選取的目標元素,類別將套用至該元素。如果類別應套用至documentElement
,則預設為body
,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' }
],
},
};
為了向後相容,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 文件以取得更多資訊。
在故事中 (元件故事格式)
或在您的故事檔案中設定主題,如下所示
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)' },
],
},
});
覆寫單一屬性
您也可以僅覆寫主題參數上的單一索引鍵,例如為單一故事設定不同的預設值
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 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
不使用裝飾器的情況 | + | + | + | + | + | + | + | + | + | + | + | |
與裝飾器搭配使用 | + | + | + | + |