From 9c29266eeb1570adde4e818fcfeafa9be3702bf4 Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 17 Sep 2019 20:56:24 -0500 Subject: [PATCH] addon-knobs now support options as an array OF objects. fixes issue #810 --- CONTRIBUTING.md | 4 +-- addons/knobs/README.md | 34 +++++++++++++++++-- addons/knobs/src/components/types/Select.tsx | 22 ++++++++---- .../stories/addon-knobs/with-knobs.stories.js | 17 +++++++++- 4 files changed, 64 insertions(+), 13 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a084900bab8e..080a123a4684 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -327,9 +327,7 @@ First we are going to install storybook, then we are going to link `@storybook/r You should now have a working storybook dev environment up and running. -> TODO: update this section (is already incorrect) - -Save and go to `http://localhost:9009` (or wherever storybook is running) +Save and go to `http://localhost:9011` (or wherever storybook is running) If you don't see the changes rerun `yarn storybook` again in your sandbox app diff --git a/addons/knobs/README.md b/addons/knobs/README.md index 9573ee40b030..6939d1d3f91c 100644 --- a/addons/knobs/README.md +++ b/addons/knobs/README.md @@ -287,7 +287,7 @@ const value = array(label, defaultValue, ',', groupId); ### select -Allows you to get a value from a select box from the user. +Allows you to get a value from a select box from the user (options as an object shown below) ```js import { select } from '@storybook/addon-knobs'; @@ -306,7 +306,37 @@ const groupId = 'GROUP-ID1'; const value = select(label, options, defaultValue, groupId); ``` -> You can also provide options as an array like this: `['red', 'blue', 'yellow']` +options can also be an array + +```js +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); +``` + +options can also be an array OF objects + +```js +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, options, defaultValue, groupId); +``` ### radio buttons diff --git a/addons/knobs/src/components/types/Select.tsx b/addons/knobs/src/components/types/Select.tsx index 8a7f387859f4..50a5d52b5648 100644 --- a/addons/knobs/src/components/types/Select.tsx +++ b/addons/knobs/src/components/types/Select.tsx @@ -30,15 +30,23 @@ const SelectType: FunctionComponent & { deserialize: typeof deserialize; } = ({ knob, onChange }) => { const { options } = knob; - const entries = Array.isArray(options) - ? options.reduce>((acc, k) => ({ ...acc, [k]: k }), {}) - : (options as Record); - const selectedKey = Object.keys(entries).find(k => { - if (Array.isArray(knob.value)) { - return JSON.stringify(entries[k]) === JSON.stringify(knob.value); + const callbackReduceArrayOptions = (acc: any, option: any, i: number) => { + if (typeof option !== 'object') return { ...acc, [option]: option }; + const label = option.label || option.key || i; + return { ...acc, [label]: option }; + }; + + const entries = Array.isArray(options) ? options.reduce(callbackReduceArrayOptions, {}) : options; + + const selectedKey = Object.keys(entries).find(key => { + const { value: knobVal } = knob; + const entryVal = entries[key]; + + if (Array.isArray(knobVal)) { + return JSON.stringify(entryVal) === JSON.stringify(knobVal); } - return entries[k] === knob.value; + return entryVal === knobVal; }); return ( diff --git a/examples/official-storybook/stories/addon-knobs/with-knobs.stories.js b/examples/official-storybook/stories/addon-knobs/with-knobs.stories.js index b31e0970d512..c960fa50edde 100644 --- a/examples/official-storybook/stories/addon-knobs/with-knobs.stories.js +++ b/examples/official-storybook/stories/addon-knobs/with-knobs.stories.js @@ -75,12 +75,27 @@ export const tweaksStaticValues = () => { const images = files('Happy Picture', 'image/*', [ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfiARwMCyEWcOFPAAAAP0lEQVQoz8WQMQoAIAwDL/7/z3GwghSp4KDZyiUpBMCYUgd8rehtH16/l3XewgU2KAzapjXBbNFaPS6lDMlKB6OiDv3iAH1OAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE4LTAxLTI4VDEyOjExOjMzLTA3OjAwlAHQBgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOC0wMS0yOFQxMjoxMTozMy0wNzowMOVcaLoAAAAASUVORK5CYII=', ]); + // array of objects + const arrayOfObjects = [ + { + label: 'Sparky', + dogParent: 'Matthew', + location: 'Austin', + }, + { + label: 'Juniper', + dogParent: 'Joshua', + location: 'Austin', + }, + ]; + + const dog = select('Dogs', arrayOfObjects, arrayOfObjects[0]); // NOTE: the default value must not change - e.g., do not do date('Label', new Date()) or date('Label') const defaultBirthday = new Date('Jan 20 2017 GMT+0'); const birthday = date('Birthday', defaultBirthday); - const intro = `My name is ${name}, I'm ${age} years old, and my favorite fruit is ${fruit}. I also enjoy ${otherFruit}.`; + const intro = `My name is ${name}, I'm ${age} years old, and my favorite fruit is ${fruit}. I also enjoy ${otherFruit}, and hanging out with my dog ${dog.label}`; const style = { backgroundColor, ...otherStyles }; const salutation = nice ? 'Nice to meet you!' : 'Leave me alone!'; const dateOptions = { year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' };