UNPKG

12.3 kBMarkdownView Raw
1# Storybook Addon Knobs
2
3Storybook Addon Knobs allow you to edit props dynamically using the Storybook UI.
4You can also use Knobs as a dynamic variable inside stories in [Storybook](https://storybook.js.org).
5
6[Framework Support](https://github.com/storybookjs/storybook/blob/master/ADDONS_SUPPORT.md).
7
8This is what Knobs looks like:
9
10[![Storybook Knobs Demo](docs/storybook-knobs-example.png)](https://storybooks-official.netlify.com/?knob-Dollars=12.5&knob-Name=Storyteller&knob-Years%20in%20NY=9&knob-background=%23ffff00&knob-Age=70&knob-Items%5B0%5D=Laptop&knob-Items%5B1%5D=Book&knob-Items%5B2%5D=Whiskey&knob-Other%20Fruit=lime&knob-Birthday=1484870400000&knob-Nice=true&knob-Styles=%7B%22border%22%3A%223px%20solid%20%23ff00ff%22%2C%22padding%22%3A%2210px%22%7D&knob-Fruit=apple&selectedKind=Addons%7CKnobs.withKnobs&selectedStory=tweaks%20static%20values&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybooks%2Fstorybook-addon-knobs)
11
12> Checkout the above [Live Storybook](https://storybooks-official.netlify.com/?knob-Dollars=12.5&knob-Name=Storyteller&knob-Years%20in%20NY=9&knob-background=%23ffff00&knob-Age=70&knob-Items%5B0%5D=Laptop&knob-Items%5B1%5D=Book&knob-Items%5B2%5D=Whiskey&knob-Other%20Fruit=lime&knob-Birthday=1484870400000&knob-Nice=true&knob-Styles=%7B%22border%22%3A%223px%20solid%20%23ff00ff%22%2C%22padding%22%3A%2210px%22%7D&knob-Fruit=apple&selectedKind=Addons%7CKnobs.withKnobs&selectedStory=tweaks%20static%20values&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybooks%2Fstorybook-addon-knobs) or [watch this video](https://www.youtube.com/watch?v=kopW6vzs9dg&feature=youtu.be).
13
14## Getting Started
15
16First of all, you need to install Knobs into your project as a dev dependency.
17
18```sh
19yarn add @storybook/addon-knobs --dev
20```
21
22Then, configure it as an addon by adding it to your `addons.js` file (located in the Storybook config directory).
23
24```js
25import '@storybook/addon-knobs/register';
26```
27
28Now, write your stories with Knobs.
29
30### With React
31```js
32import React from "react";
33import { withKnobs, text, boolean, number } from "@storybook/addon-knobs";
34
35export default {
36 title: "Storybook Knobs",
37 decorators: [withKnobs]
38};
39// Add the `withKnobs` decorator to add knobs support to your stories.
40// You can also configure `withKnobs` as a global decorator.
41
42// Knobs for React props
43export const withAButton = () => (
44 <button disabled={boolean("Disabled", false)}>
45 {text("Label", "Hello Storybook")}
46 </button>
47);
48
49// Knobs as dynamic variables.
50export const asDynamicVariables = () => {
51 const name = text("Name", "Arunoda Susiripala");
52 const age = number("Age", 89);
53
54 const content = `I am ${name} and I'm ${age} years old.`;
55 return <div>{content}</div>;
56};
57```
58
59### With Vue.js
60MyButton.story.js:
61```js
62import { storiesOf } from '@storybook/vue';
63import { withKnobs, text, boolean } from '@storybook/addon-knobs';
64
65import MyButton from './MyButton.vue';
66
67const stories = storiesOf('Storybook Knobs', module);
68
69// Add the `withKnobs` decorator to add knobs support to your stories.
70// You can also configure `withKnobs` as a global decorator.
71stories.addDecorator(withKnobs);
72
73// Assign `props` to the story's component, calling
74// knob methods within the `default` property of each prop,
75// then pass the story's prop data to the component’s prop in
76// the template with `v-bind:` or by placing the prop within
77// the component’s slot.
78stories.add('with a button', () => ({
79 components: { MyButton },
80 props: {
81 isDisabled: {
82 default: boolean('Disabled', false)
83 },
84 text: {
85 default: text('Text', 'Hello Storybook')
86 }
87 },
88 template: `<MyButton :isDisabled="isDisabled">{{ text }}</MyButton>`
89}));
90```
91
92MyButton.vue:
93```vue
94<template>
95 <button :disabled="isDisabled">
96 <slot></slot>
97 </button>
98</template>
99
100<script>
101export default {
102 props: {
103 isDisabled: {
104 type: Boolean,
105 default: false
106 }
107 }
108}
109</script>
110```
111
112### With Angular
113```js
114import { storiesOf } from '@storybook/angular';
115import { boolean, number, text, withKnobs } from '@storybook/addon-knobs';
116
117import { Button } from '@storybook/angular/demo';
118
119const stories = storiesOf('Storybook Knobs', module);
120
121// "withKnobs" decorator should be applied before the stories using knobs
122stories.addDecorator(withKnobs);
123
124// Knobs for Angular props
125stories.add('with a button', () => ({
126 component: Button,
127 props: {
128 text: text('text', 'Hello Storybook'), // The first param of the knob function has to be exactly the same as the component input.
129 },
130}));
131
132```
133
134Categorize 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.
135```js
136// Knob assigned a groupId.
137stories.add('as dynamic variables', () => {
138 const groupId = 'GROUP-ID1'
139 const name = text('Name', 'Arunoda Susiripala', groupId);
140
141 const content = `My name is ${name}.`;
142 return (<div>{content}</div>);
143});
144```
145
146You can see your Knobs in a Storybook panel as shown below.
147
148![](docs/demo.png)
149
150## Available Knobs
151
152These are the Knobs available for you to use. You can import these Knobs from the `@storybook/addon-knobs` module.
153Here's how to import the **text** Knob.
154
155```js
156import { text } from '@storybook/addon-knobs';
157```
158
159Just like that, you can import any other following Knobs:
160
161### text
162
163Allows you to get some text from the user.
164
165```js
166import { text } from '@storybook/addon-knobs';
167
168const label = 'Your Name';
169const defaultValue = 'Arunoda Susiripala';
170const groupId = 'GROUP-ID1';
171
172const value = text(label, defaultValue, groupId);
173```
174
175### boolean
176
177Allows you to get a boolean value from the user.
178
179```js
180import { boolean } from '@storybook/addon-knobs';
181
182const label = 'Agree?';
183const defaultValue = false;
184const groupId = 'GROUP-ID1';
185
186const value = boolean(label, defaultValue, groupId);
187```
188### number
189
190Allows you to get a number from the user.
191
192```js
193import { number } from '@storybook/addon-knobs';
194
195const label = 'Age';
196const defaultValue = 78;
197const groupId = 'GROUP-ID1';
198
199const value = number(label, defaultValue);
200```
201
202For use with `groupId`, pass the default `options` as the third argument.
203```
204const value = number(label, defaultValue, {}, groupId);
205```
206### number bound by range
207
208Allows you to get a number from the user using a range slider.
209
210```js
211import { number } from '@storybook/addon-knobs';
212
213const label = 'Temperature';
214const defaultValue = 73;
215const options = {
216 range: true,
217 min: 60,
218 max: 90,
219 step: 1,
220};
221const groupId = 'GROUP-ID1';
222
223const value = number(label, defaultValue, options, groupId);
224```
225
226### color
227
228Allows you to get a colour from the user.
229
230```js
231import { color } from '@storybook/addon-knobs';
232
233const label = 'Color';
234const defaultValue = '#ff00ff';
235const groupId = 'GROUP-ID1';
236
237const value = color(label, defaultValue, groupId);
238```
239
240### object
241
242Allows you to get a JSON object or array from the user.
243
244```js
245import { object } from '@storybook/addon-knobs';
246
247const label = 'Styles';
248const defaultValue = {
249 backgroundColor: 'red'
250};
251const groupId = 'GROUP-ID1';
252
253const value = object(label, defaultValue, groupId);
254```
255
256> Make sure to enter valid JSON syntax while editing values inside the knob.
257
258### array
259
260Allows you to get an array of strings from the user.
261
262```js
263import { array } from '@storybook/addon-knobs';
264
265const label = 'Styles';
266const defaultValue = ['Red'];
267const groupId = 'GROUP-ID1';
268
269const value = array(label, defaultValue);
270```
271
272> While editing values inside the knob, you will need to use a separator.
273> By default it is a comma, but this can be overridden by passing a separator variable.
274>
275> ```js
276> import { array } from '@storybook/addon-knobs';
277>
278> const label = 'Styles';
279> const defaultValue = ['Red'];
280> const separator = ':';
281> const value = array(label, defaultValue, separator);
282> ```
283
284For use with `groupId`, pass the default `separator` as the third argument
285```
286const value = array(label, defaultValue, ',', groupId);
287```
288
289### select
290
291It allows you to get a value from a select box from the user.
292
293```js
294import { select } from '@storybook/addon-knobs';
295
296const label = 'Colors';
297const options = {
298 Red: 'red',
299 Blue: 'blue',
300 Yellow: 'yellow',
301 Rainbow: ['red', 'orange', 'etc'],
302 None: null,
303};
304const defaultValue = 'red';
305const groupId = 'GROUP-ID1';
306
307const value = select(label, options, defaultValue, groupId);
308```
309
310> You can also provide options as an array like this: `['red', 'blue', 'yellow']`.
311
312
313### radio buttons
314
315It allows you to get a value from a list of radio buttons from the user.
316
317```js
318import { radios } from '@storybook/addon-knobs';
319
320const label = 'Fruits';
321const options = {
322 Kiwi: 'kiwi',
323 Guava: 'guava',
324 Watermelon: 'watermelon',
325};
326const defaultValue = 'kiwi';
327const groupId = 'GROUP-ID1';
328
329const value = radios(label, options, defaultValue, groupId);
330```
331
332### options
333
334Configurable UI for selecting a value from a set of options.
335
336```js
337import { optionsKnob as options } from '@storybook/addon-knobs';
338
339const label = 'Fruits';
340const valuesObj = {
341 Kiwi: 'kiwi',
342 Guava: 'guava',
343 Watermelon: 'watermelon',
344};
345const defaultValue = 'kiwi';
346const optionsObj = {
347 display: 'inline-radio'
348};
349const groupId = 'GROUP-ID1';
350
351const value = options(label, valuesObj, defaultValue, optionsObj, groupId);
352```
353> The display property for `optionsObj` accepts:
354> - `radio`
355> - `inline-radio`
356> - `check`
357> - `inline-check`
358> - `select`
359> - `multi-select`
360
361### files
362
363It allows you to get a value from a file input from the user.
364
365```js
366import { files } from '@storybook/addon-knobs';
367
368const label = 'Images';
369const accept = '.xlsx, .pdf';
370const defaultValue = [];
371const groupId = 'GROUP-ID1';
372
373const value = files(label, accept, defaultValue, groupId);
374```
375
376> You can optionally specify a [list of file types](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept) which the file input should accept.
377> Multiple files can be selected, and will be returned as an array of [Data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs).
378
379### date
380
381Allows you to get date (and time) from the user.
382
383```js
384import { date } from '@storybook/addon-knobs';
385
386const label = 'Event Date';
387const defaultValue = new Date('Jan 20 2017');
388const groupId = 'GROUP-ID1';
389
390const value = date(label, defaultValue, groupId);
391```
392
393> Note: the default value must not change - e.g., do not do `date('Label', new Date())` or `date('Label')`.
394
395The `date` knob returns the selected date as stringified Unix timestamp (e.g. `"1510913096516"`).
396If your component needs the date in a different form you can wrap the `date` function:
397
398```js
399function myDateKnob(name, defaultValue) {
400 const stringTimestamp = date(name, defaultValue)
401 return new Date(stringTimestamp)
402}
403```
404
405### button
406
407It allows you to include a button and associated handler.
408
409```js
410import { button } from '@storybook/addon-knobs';
411
412const label = 'Do Something';
413const handler = () => doSomething('foobar');
414const groupId = 'GROUP-ID1';
415
416button(label, handler, groupId);
417```
418
419Button knobs cause the story to re-render after the handler fires.
420You can prevent this by having the handler return `false`.
421
422### withKnobs options
423
424withKnobs also accepts two optional options as story parameters.
425Usage:
426
427```js
428import { storiesOf } from '@storybook/react';
429import { withKnobs } from '@storybook/addon-knobs';
430
431const stories = storiesOf('Storybook Knobs', module);
432
433stories.addDecorator(withKnobs)
434stories.add('story name', () => ..., {
435 knobs: {
436 timestamps: true, // Doesn't emit events while user is typing.
437 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.
438 // 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.
439 }
440});
441```
442
443## Typescript
444
445If you are using Typescript, make sure you have the type definitions installed for the following libs:
446
447- node
448- react
449
450You can install them using:
451*assuming you are using Typescript >2.0.*
452
453```sh
454yarn add @types/node @types/react --dev
455```
456