Storybook 擴充功能 Knobs (已棄用)
我們正棄用 Knobs,改用 @storybook/addon-controls。
討論: https://github.com/storybookjs/storybook/discussions/15060
Storybook 擴充功能 Knobs 可讓您使用 Storybook UI 動態編輯 props。您也可以在 Storybook 的 stories 中使用 Knobs 作為動態變數。
框架支援.
這就是 Knobs 的樣子
請查看上面的 即時 Storybook 或 觀看此影片。
開始使用
首先,您需要將 Knobs 作為開發依賴項安裝到您的專案中。
yarn add @storybook/addon-knobs --dev
此擴充功能的最新版本支援 Storybook v7。如果您使用的是較舊版本的 Storybook,則需要安裝與之匹配的此擴充功能版本,例如 @storybook/addon-knobs@6.4.0
。
在 .storybook/main.js
中
module.exports = {
addons: ['@storybook/addon-knobs'],
};
現在,使用 Knobs 編寫您的 stories。
使用 React
import React from 'react';
import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';
export default {
title: 'Storybook Knobs',
decorators: [withKnobs],
};
// Add the `withKnobs` decorator to add knobs support to your stories.
// You can also configure `withKnobs` as a global decorator.
// Knobs for React props
export const withAButton = () => (
<button disabled={boolean('Disabled', false)}>{text('Label', 'Hello Storybook')}</button>
);
// Knobs as dynamic variables.
export const asDynamicVariables = () => {
const name = text('Name', 'James');
const age = number('Age', 35);
const content = `I am ${name} and I'm ${age} years old.`;
return <div>{content}</div>;
};
使用 Vue.js
MyButton.story.js
import { storiesOf } from '@storybook/vue';
import { withKnobs, text, boolean } from '@storybook/addon-knobs';
import MyButton from './MyButton.vue';
export default {
title: 'Storybook Knobs',
decorators: [withKnobs],
};
// Assign `props` to the story's component, calling
// knob methods within the `default` property of each prop,
// then pass the story's prop data to the component’s prop in
// the template with `v-bind:` or by placing the prop within
// the component’s slot.
export const exampleWithKnobs = () => ({
components: { MyButton },
props: {
isDisabled: {
default: boolean('Disabled', false),
},
text: {
default: text('Text', 'Hello Storybook'),
},
},
template: `<MyButton :isDisabled="isDisabled">{{ text }}</MyButton>`,
});
MyButton.vue
<template>
<button :disabled="isDisabled">
<slot></slot>
</button>
</template>
<script>
export default {
props: {
isDisabled: {
type: Boolean,
default: false,
},
},
};
</script>
使用 Angular
import { storiesOf } from '@storybook/angular';
import { boolean, number, text, withKnobs } from '@storybook/addon-knobs';
import { Button } from '@storybook/angular/demo';
export default {
title: 'Storybook Knobs',
decorators: [withKnobs],
};
export const withKnobs = () => ({
component: Button,
props: {
text: text('text', 'Hello Storybook'), // The first param of the knob function has to be exactly the same as the component input.
},
});
使用 Ember
import { withKnobs, text, boolean } from '@storybook/addon-knobs';
import { hbs } from 'ember-cli-htmlbars';
export default {
title: 'StoryBook with Knobs',
decorators: [withKnobs],
};
export const button = () => ({
template: hbs`
<button disabled={{disabled}}>{{label}}</button>
`,
context: {
label: text('label', 'Hello Storybook'),
disabled: boolean('disabled', false),
},
});
分類
透過為 Knobs 指定 groupId
來分類。當 groupId
存在時,Knobs Storybook 面板中將會出現索引標籤,以在群組之間篩選。沒有 groupId
的 Knobs 會自動分類到 ALL
群組中。
export const inGroups = () => {
const personalGroupId = 'personal info';
const generalGroupId = 'general info';
const name = text('Name', 'James', personalGroupId);
const age = number('Age', 35, { min: 0, max: 99 }, personalGroupId);
const message = text('Hello!', 35, generalGroupId);
const content = `
I am ${name} and I'm ${age} years old.
${message}
`;
return <div>{content}</div>;
};
您可以在 Storybook 面板中看到您的 Knobs,如下所示。
可用的 Knobs
這些是您可以使用的 Knobs。您可以從 @storybook/addon-knobs
模組匯入這些 Knobs。以下是如何匯入 text Knob。
import { text } from '@storybook/addon-knobs';
就像這樣,您可以匯入任何其他以下 Knobs
text
允許您從使用者那裡取得一些文字。
import { text } from '@storybook/addon-knobs';
const label = 'Your Name';
const defaultValue = 'James';
const groupId = 'GROUP-ID1';
const value = text(label, defaultValue, groupId);
boolean
允許您從使用者那裡取得布林值。
import { boolean } from '@storybook/addon-knobs';
const label = 'Agree?';
const defaultValue = false;
const groupId = 'GROUP-ID1';
const value = boolean(label, defaultValue, groupId);
number
允許您從使用者那裡取得數字。
import { number } from '@storybook/addon-knobs';
const label = 'Age';
const defaultValue = 78;
const groupId = 'GROUP-ID1';
const value = number(label, defaultValue);
對於 groupId
的使用,請將預設 options
作為第三個引數傳遞。
const value = number(label, defaultValue, {}, groupId);
範圍綁定的數字
允許您使用範圍滑桿從使用者那裡取得數字。
import { number } from '@storybook/addon-knobs';
const label = 'Temperature';
const defaultValue = 73;
const options = {
range: true,
min: 60,
max: 90,
step: 1,
};
const groupId = 'GROUP-ID1';
const value = number(label, defaultValue, options, groupId);
color
允許您從使用者那裡取得顏色。
import { color } from '@storybook/addon-knobs';
const label = 'Color';
const defaultValue = '#ff00ff';
const groupId = 'GROUP-ID1';
const value = color(label, defaultValue, groupId);
object
允許您從使用者那裡取得 JSON 物件或陣列。
import { object } from '@storybook/addon-knobs';
const label = 'Styles';
const defaultValue = {
backgroundColor: 'red',
};
const groupId = 'GROUP-ID1';
const value = object(label, defaultValue, groupId);
編輯 knob 中的值時,請確保輸入有效的 JSON 語法。
array
允許您從使用者那裡取得字串陣列。
import { array } from '@storybook/addon-knobs';
const label = 'Styles';
const defaultValue = ['Red'];
const groupId = 'GROUP-ID1';
const value = array(label, defaultValue);
在編輯 knob 中的值時,您將需要使用分隔符號。預設情況下是逗號,但可以透過傳遞分隔符號變數來覆寫。
import { array } from '@storybook/addon-knobs'; const label = 'Styles'; const defaultValue = ['Red']; const separator = ':'; const value = array(label, defaultValue, separator);
對於 groupId
的使用,請將預設 separator
作為第三個引數傳遞。
const value = array(label, defaultValue, ',', groupId);
select
它允許您從使用者的下拉式選單中取得值。
import { select } from '@storybook/addon-knobs';
const label = 'Colors';
const options = {
Red: 'red',
Blue: 'blue',
Yellow: 'yellow',
Rainbow: ['red', 'orange', 'etc'],
None: null,
};
const defaultValue = 'red';
const groupId = 'GROUP-ID1';
const value = select(label, options, defaultValue, groupId);
選項也可以是陣列
import { select } from '@storybook/addon-knobs';
const label = 'Cats';
const options = ['linus', 'eleanor', 'lover'];
const defaultValue = 'eleanor';
const groupId = 'GROUP-ID2';
const value = select(label, options, defaultValue, groupId);
選項也可以是物件的陣列
const label = 'Dogs';
const arrayOfObjects = [
{
label: 'Sparky',
dogParent: 'Matthew',
location: 'Austin',
},
{
label: 'Juniper',
dogParent: 'Joshua',
location: 'Austin',
},
];
const defaultValue = arrayOfObjects[0];
const groupId = 'GROUP-ID3';
const value = select(label, arrayOfObjects, defaultValue, groupId);
單選按鈕
它允許您從使用者的單選按鈕清單中取得值。
import { radios } from '@storybook/addon-knobs';
const label = 'Fruits';
const options = {
Kiwi: 'kiwi',
Guava: 'guava',
Watermelon: 'watermelon',
};
const defaultValue = 'kiwi';
const groupId = 'GROUP-ID1';
const value = radios(label, options, defaultValue, groupId);
options
可設定的 UI,用於從一組選項中選取值。
import { optionsKnob } from '@storybook/addon-knobs';
const label = 'Fruits';
const valuesObj = {
Kiwi: 'kiwi',
Guava: 'guava',
Watermelon: 'watermelon',
};
const defaultValue = 'kiwi';
const optionsObj = {
display: 'inline-radio',
};
const groupId = 'GROUP-ID1';
const value = optionsKnob(label, valuesObj, defaultValue, optionsObj, groupId);
或者,您可以使用此匯入
import { optionsKnob as options } from '@storybook/addon-knobs';
...
const value = options(label, valuesObj, defaultValue, optionsObj, groupId);
optionsObj
的 display 屬性接受
radio
inline-radio
check
inline-check
select
multi-select
files
它允許您從使用者的檔案輸入中取得值。
import { files } from '@storybook/addon-knobs';
const label = 'Images';
const accept = '.xlsx, .pdf';
const defaultValue = [];
const groupId = 'GROUP-ID1';
const value = files(label, accept, defaultValue, groupId);
date
允許您從使用者那裡取得日期 (和時間)。
import { date } from '@storybook/addon-knobs';
const label = 'Event Date';
const defaultValue = new Date('Jan 20 2017');
const groupId = 'GROUP-ID1';
const value = date(label, defaultValue, groupId);
注意:預設值不得變更,例如,請勿執行
date('Label', new Date())
或date('Label')
。
date
knob 會以字串化的 Unix 時間戳記 (例如 "1510913096516"
) 傳回所選日期。如果您的元件需要不同形式的日期,您可以包裝 date
函式
function myDateKnob(name, defaultValue) {
const stringTimestamp = date(name, defaultValue);
return new Date(stringTimestamp);
}
button
它允許您加入按鈕和相關處理常式。
import { button } from '@storybook/addon-knobs';
const label = 'Do Something';
const handler = () => doSomething('foobar');
const groupId = 'GROUP-ID1';
button(label, handler, groupId);
在觸發處理常式後,Button knobs 會導致 story 重新轉譯。您可以讓處理常式傳回 false
來防止這種情況。
withKnobs 選項
withKnobs 也接受兩個可選選項作為 story 參數。用法
import { withKnobs } from '@storybook/addon-knobs';
export default {
title: 'Storybook Knobs',
decorators: [withKnobs],
};
export const defaultView = () => <div />;
defaultView.parameters = {
knobs: {
// Doesn't emit events while user is typing.
timestamps: true,
// Escapes strings to be safe for inserting as innerHTML. This option is true by default. It's safe to set it to `false` with frameworks like React which do escaping on their side.
// You can still set it to false, but it's strongly discouraged to set to true in cases when you host your storybook on some route of your main site or web app.
escapeHTML: true,
},
};
Typescript
如果您正在使用 Typescript,請確保您已為下列程式庫安裝類型定義
- node
- react
您可以使用以下命令安裝它們:(假設您正在使用 Typescript >2.0。)
yarn add @types/node @types/react --dev