UNPKG

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