旋鈕 (Knobs)

用於編輯 props 的 Storybook 擴充功能

在 Github 上查看

Storybook 擴充功能旋鈕(已棄用)

我們正在棄用旋鈕,改用 @storybook/addon-controls。

討論: https://github.com/storybookjs/storybook/discussions/15060

Storybook 擴充功能旋鈕讓您可以使用 Storybook UI 動態編輯 props。您也可以在 Storybook 的故事中將旋鈕用作動態變數。

框架支援.

這就是旋鈕的外觀

Storybook Knobs Demo

查看以上 即時 Storybook觀看此影片

開始使用

首先,您需要將旋鈕作為開發依賴項安裝到您的專案中。

yarn add @storybook/addon-knobs --dev

此擴充功能的最新版本支援 Storybook v7。如果您使用的是舊版 Storybook,則需要安裝此擴充功能的匹配版本,例如 @storybook/addon-knobs@6.4.0

.storybook/main.js

module.exports = {
  addons: ['@storybook/addon-knobs'],
};

現在,使用旋鈕編寫您的故事。

使用 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),
  },
});

分類

透過為其分配 groupId 來分類您的旋鈕。當存在 groupId 時,旋鈕 Storybook 面板中會出現索引標籤,以在群組之間進行篩選。沒有 groupId 的旋鈕會自動分類到 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 面板中看到您的旋鈕。

可用旋鈕

以下是您可以使用的旋鈕。您可以從 @storybook/addon-knobs 模組匯入這些旋鈕。以下是如何匯入 text 旋鈕。

import { text } from '@storybook/addon-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);

請確保在旋鈕中編輯值時輸入有效的 JSON 語法。

array

允許您從使用者取得字串陣列。

import { array } from '@storybook/addon-knobs';

const label = 'Styles';
const defaultValue = ['Red'];
const groupId = 'GROUP-ID1';

const value = array(label, defaultValue);

在旋鈕中編輯值時,您需要使用分隔符號。預設為逗號,但可以透過傳遞分隔符號變數來覆寫。

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 的顯示屬性接受

  • 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);

您可以選擇性地指定檔案輸入應接受的檔案類型清單。可以選取多個檔案,並且會以 Data URL 陣列的形式傳回。

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 旋鈕會以字串化的 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);

在處理常式觸發後,按鈕旋鈕會導致故事重新呈現。您可以讓處理常式傳回 false 來防止這種情況。

withKnobs 選項

withKnobs 也接受兩個可選選項作為故事參數。用法

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
由以下人員製作
  • domyen
    domyen
  • kasperpeulen
    kasperpeulen
  • valentinpalkovic
    valentinpalkovic
  • jreinhold
    jreinhold
  • kylegach
    kylegach
  • ndelangen
    ndelangen
可搭配使用
    Angular
    Ember
    HTML
    Marko
    Mithril
    Preact
    Rax
    React
    Riot
    Svelte
    Vue
    Web Components
標籤