在 Storybook - 基本介紹 & 安裝 有提到 .storybook/preview.js
這支 js 檔是用來控制 Story 呈現的方式,它會在 Canvas 中被載入並影響著畫面的內容,如果要做全局的設定像是本篇接下來要介紹的 parameters
, decorators
以及 globalTypes
就都會在 preview.js 中做設定。
parameters 是用於定義 Storybook 功能和不同 Addons 行為的參數,因此不同的 Addons 會有不同的 parameters。
舉例來說我們有介紹過 Toolbars 中用於切換背景顏色的 backgrounds addons,我們就能透過自定義 parameters.backgrounds 來客製化更多的可切換的背景顏色。
// .storybook/preview.js
export const parameters = {
backgrounds: {
values: [
{ name: 'red', value: '#f00' },
{ name: 'green', value: '#0f0' },
{ name: 'blue', value: '#00f' }
]
}
}
decorators 是一種在維持原有 Story 不變的情況下,額外包一層自定義的 DOM 容器 (container) 、引入上下文環境 (context) 或添加假資料的方法,許多 Addons 便是透過 decorators 來做到強大又便利的功能。
舉例來說,可能在某些情境下,元件的樣式因為太靠畫面的邊緣,而一直被遮擋著,因此我們會希望可以讓元件和邊緣有更大的間距來完美的展示元件的樣貌,這時我們就能運用 decorators 來達到此事。
// .storybook/preview.js
export const decorators = [(story) => ({
components: { story },
template: '<div style="margin: 3em;"><story /></div>'
})]
parameters 和 decorators 都一樣,除了可以在 preview.js 中作全局的設定,也能在元件和 Story 層級中作設定。
元件層級
// Button.stories.js
import Button from './Button.vue'
export default {
title: 'Components/Button',
component: Button,
parameters: {
backgrounds: {
values: [
{ name: 'red', value: '#f00' },
{ name: 'green', value: '#0f0' },
{ name: 'blue', value: '#00f' }
]
}
},
decorators: [(story) => ({
component: { story },
template: '<div style="margin: 3em;"><story /></div>'
})]
}
Story 層級
// Button.stories.js
import Button from './Button.vue'
export default {
component: Button,
title: 'Components/Button',
}
export const Primary = () => ({
components: { Button },
template: '<Button primary label="Hello World" />',
})
Primary.parameters = {
backgrounds: {
values: [
{ name: 'red', value: '#f00' },
{ name: 'green', value: '#0f0' },
{ name: 'blue', value: '#00f' }
]
}
}
Primary.decorators = [(story) => ({
component: { story },
template: '<div style="margin: 3em;"><story /></div>'
})]
如果在全局、元件和 Story 層級同時都有設定的 paramters 和 decorators 時,採用的權重順序會是
story > 元件 > 全局
Toolbars 中除了有我們安裝的 addons 工具以外,我們也可以自己創建一個工具,由於工具不屬於特定的 Story,因此他們不會透過 args 的方式與 Story 互動,而是會透過 "globals" 屬性以及全局的 decorators 來實現。
那我們現在就來示範一個可以將元件切換成 dark mode 的自製工具,首先在 preview.js 中透過 globalTypes 來添加自己的工具項目。
// .storybook/preview.js
export const globalTypes = {
darkMode: {
name: 'Dark Mode',
defaultValue: 'default',
toolbar: {
items: ['default', 'dark'],
showName: true,
}
}
}
接著再添加 decorators 並透過 decorator 函數的第二個參數 context 取得 globals.darkMode 改變元件的 background color。
// .storybook/preview.js
export const globalTypes = {
darkMode: {
name: 'Dark Mode',
defaultValue: 'default',
toolbar: {
items: ['default', 'dark'],
showName: true,
}
}
}
export const decorators = [(story, context) => {
const darkModeColor = {
default: 'auto',
dark: '#333333'
}
return {
component: { story },
template: `<story style="background-color: ${darkModeColor[context.globals.darkMode]}"/>`
}
}]
大功告成!
這邊補充說明一下,當 globals 發生變化時, Story 會重新渲染,所以 decorators 也會跟著重新執行,此外 decorator 的第二個參數 context 除了 globals 以外也包含著其他的關鍵值。
今天的分享就到這邊,如果大家對我分享的內容有興趣歡迎點擊追蹤 & 訂閱系列文章,如果對內容有任何疑問,或是文章內容有錯誤,都非常歡迎留言討論或指教的!
明天要來分享的是 Storybook 主題的第四篇 Controls,那我們明天見!