Storybook Addon Knobs allow you to edit React props dynamically using the Storybook UI. You can also use Knobs as a dynamic variable inside stories in Storybook.
This is how Knobs look like:
Checkout the above Live Storybook or watch this video.
First of all, you need to install knobs into your project as a dev dependency.
npm install @storybook/addon-knobs --save-dev
Then, configure it as an addon by adding it to your addons.js
file (located in the Storybook config directory).
import '@storybook/addon-knobs/register';
Now, write your stories with knobs.
import { storiesOf } from '@storybook/react';
import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';
const stories = storiesOf('Storybook Knobs', module);
// Add the `withKnobs` decorator to add knobs support to your stories.
// You can also configure `withKnobs` as a global decorator.
stories.addDecorator(withKnobs);
// Knobs for React props
stories.add('with a button', () => (
<button disabled={boolean('Disabled', false)} >
{text('Label', 'Hello Storybook')}
</button>
));
// Knobs as dynamic variables.
stories.add('as dynamic variables', () => {
const name = text('Name', 'Arunoda Susiripala');
const age = number('Age', 89);
const content = `I am ${name} and I'm ${age} years old.`;
return (<div>{content}</div>);
});
import { storiesOf } from '@storybook/vue';
import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';
import MyButton from './Button.vue';
const stories = storiesOf('Storybook Knobs', module);
// Add the `withKnobs` decorator to add knobs support to your stories.
// You can also configure `withKnobs` as a global decorator.
stories.addDecorator(withKnobs);
// Knobs for Vue props
// Knobs for Vue props
stories.add('with a button', () => ({
components: { MyButton },
template:
`<button disabled="${boolean('Disabled', false)}" >
${text('Label', 'Hello Storybook')}
</button>`
}));
// Knobs as dynamic variables.
stories.add('as dynamic variables', () => {
const name = text('Name', 'Arunoda Susiripala');
const age = number('Age', 89);
const content = `I am ${name} and I'm ${age} years old.`;
return `<div>${content}</div>`;
});
import { storiesOf } from '@storybook/angular';
import { boolean, number, text, withKnobs } from '@storybook/addon-knobs';
import { Button } from '@storybook/angular/demo';
const stories = storiesOf('Storybook Knobs', module);
// "withKnobs" decorator should be applied before the stories using knobs
stories.addDecorator(withKnobs);
// Knobs for Angular props
stories.add('with a button', () => ({
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.
},
}));
Categorize your knobs by assigning them a groupId
. When a groupId
exists, tabs will appear in the knobs storybook panel to filter between the groups. Knobs without a groupId
are automatically categorized into the ALL
group.
// Knob assigned a groupId.
stories.add('as dynamic variables', () => {
const groupId = 'GROUP-ID1'
const name = text('Name', 'Arunoda Susiripala', groupId);
const content = `My name is ${name}.`;
return (<div>{content}</div>);
});
You can see your Knobs in a Storybook panel as shown below.
These are the knobs available for you to use. You can import these Knobs from the @storybook/addon-knobs
module.
Here's how to import the text Knob.
import { text } from '@storybook/addon-knobs';
Just like that, you can import any other following Knobs:
Allows you to get some text from the user.
import { text } from '@storybook/addon-knobs';
const label = 'Your Name';
const defaultValue = 'Arunoda Susiripala';
const groupId = 'GROUP-ID1';
const value = text(label, defaultValue, groupId);
Allows you to get a boolean value from the user.
import { boolean } from '@storybook/addon-knobs';
const label = 'Agree?';
const defaultValue = false;
const groupId = 'GROUP-ID1';
const value = boolean(label, defaultValue, groupId);
Allows you to get a number from the user.
import { number } from '@storybook/addon-knobs';
const label = 'Age';
const defaultValue = 78;
const groupId = 'GROUP-ID1';
const value = number(label, defaultValue);
For use with groupId
, pass the default options
as the third argument
const value = number(label, defaultValue, {}, groupId);
Allows you to get a number from the user using a range slider.
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);
Allows you to get a colour from the user.
import { color } from '@storybook/addon-knobs';
const label = 'Color';
const defaultValue = '#ff00ff';
const groupId = 'GROUP-ID1';
const value = color(label, defaultValue, groupId);
Allows you to get a JSON object or array from the user.
import { object } from '@storybook/addon-knobs';
const label = 'Styles';
const defaultValue = {
backgroundColor: 'red'
};
const groupId = 'GROUP-ID1';
const value = object(label, defaultValue, groupId);
Make sure to enter valid JSON syntax while editing values inside the knob.
Allows you to get an array of strings from the user.
import { array } from '@storybook/addon-knobs';
const label = 'Styles';
const defaultValue = ['Red'];
const groupId = 'GROUP-ID1';
const value = array(label, defaultValue);
While editing values inside the knob, you will need to use a separator. By default it's a comma, but this can be override by passing a separator variable.
import { array } from '@storybook/addon-knobs'; const label = 'Styles'; const defaultValue = ['Red']; const separator = ':'; const value = array(label, defaultValue, separator);
For use with groupId
, pass the default separator
as the third argument
const value = array(label, defaultValue, ',', groupId);
Allows you to get a value from a select box from the user.
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);
You can also provide options as an array like this:
['red', 'blue', 'yellow']
Allows you to get a value from a list of radio buttons from the user.
import { radios } from '@storybook/addon-knobs';
const label = 'Fruits';
const options = {
Kiwi: 'kiwi',
Guava: 'guava',
Watermelon: 'watermelon',
};
const defaultValue = 'kiwi';
const value = radios(label, options, defaultValue);
Configurable UI for selecting a value from a set of options.
import { optionsKnob as options } from '@storybook/addon-knobs';
const label = 'Fruits';
const valuesObj = {
Kiwi: 'kiwi',
Guava: 'guava',
Watermelon: 'watermelon',
};
const defaultValue = 'kiwi';
const optionsObj = {
display: 'inline-radio'
};
const value = options(label, valuesObj, defaultValue, optionsObj);
The display property for
optionsObj
accepts:
radio
inline-radio
check
inline-check
select
multi-select
Allows you to get a value from a file input from the user.
import { files } from '@storybook/addon-knobs';
const label = 'Images';
const defaultValue = [];
const value = files(label, accept, defaultValue);
Multiple files can be selected, and will be returned as an array of Data URLs
Allow you to get date (and time) from the user.
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);
Note: the default value must not change - e.g., do not do
date('Label', new Date())
ordate('Label')
The date
knob returns the selected date as stringified Unix timestamp (e.g. "1510913096516"
).
If your component needs the date in a different form you can wrap the date
function:
function myDateKnob(name, defaultValue) {
const stringTimestamp = date(name, defaultValue)
return new Date(stringTimestamp)
}
Allows you to include a button and associated handler.
import { button } from '@storybook/addon-knobs';
const label = 'Do Something';
const handler = () => doSomething('foobar');
const groupId = 'GROUP-ID1';
button(label, handler, groupId);
withKnobs also accepts two optional options as story parameters. Usage:
import { storiesOf } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs';
const stories = storiesOf('Storybook Knobs', module);
stories.addDecorator(withKnobs)
stories.add('story name', () => ..., {
knobs: {
timestamps: true, // Doesn't emit events while user is typing.
escapeHTML: 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 unrecommendend in cases when you host your storybook on some route of your main site or web app.
}
});
If you are using typescript, make sure you have the type definitions installed for the following libs:
- node
- react
You can install them using npm install -save @types/node @types/react
, assuming you are using Typescript >2.0.