Skip to content

Commit

Permalink
Merge pull request #1745 from storybooks/select-knob-ordering
Browse files Browse the repository at this point in the history
Select knob key/value ordering
  • Loading branch information
ndelangen authored Jan 31, 2018
2 parents 2d8db3e + 5928842 commit 7b0b539
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 19 deletions.
19 changes: 19 additions & 0 deletions addons/knobs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,25 @@ const value = select(label, options, defaultValue);
> You can also provide options as an array like this: `['red', 'blue', 'yellow']`
### selectV2

In v4 this will replace `select`. The value from the select now uses the values from the `options` object.

```js
import { selectV2 } 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 value = selectV2(label, options, defaultValue)

### date

Allow you to get date (and time) from the user.
Expand Down
3 changes: 2 additions & 1 deletion addons/knobs/src/angular/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import {
array,
date,
select,
selectV2,
button,
manager,
} from '../base';

export { knob, text, boolean, number, color, object, array, date, select, button };
export { knob, text, boolean, number, color, object, array, date, select, selectV2, button };

export const angularHandler = (channel, knobStore) => getStory => context =>
prepareComponent({ getStory, context, channel, knobStore });
Expand Down
10 changes: 8 additions & 2 deletions addons/knobs/src/base.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import deprecate from 'util-deprecate';
import KnobManager from './KnobManager';

export const manager = new KnobManager();
Expand Down Expand Up @@ -45,8 +46,13 @@ export function object(name, value) {
return manager.knob(name, { type: 'object', value });
}

export function select(name, options, value) {
return manager.knob(name, { type: 'select', options, value });
export const select = deprecate(
(name, options, value) => manager.knob(name, { type: 'select', options, value }),
'in v4 keys/values of the options argument are reversed'
);

export function selectV2(name, options, value) {
return manager.knob(name, { type: 'select', selectV2: true, options, value });
}

export function array(name, value, separator = ',') {
Expand Down
40 changes: 40 additions & 0 deletions addons/knobs/src/components/__tests__/Select.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import { shallow } from 'enzyme'; // eslint-disable-line
import SelectType from '../types/Select';

describe('Select', () => {
let knob;

beforeEach(() => {
knob = {
name: 'Colors',
value: '#00ff00',
options: {
Green: '#00ff00',
Red: '#ff0000',
},
};
});

it('displays value', () => {
const wrapper = shallow(<SelectType knob={knob} />);

const green = wrapper.find('option').first();
expect(green.text()).toEqual('#00ff00');
expect(green.prop('value')).toEqual('Green');
});

describe('selectV2', () => {
beforeEach(() => {
knob.selectV2 = true;
});

it('correctly maps option keys and values', () => {
const wrapper = shallow(<SelectType knob={knob} />);

const green = wrapper.find('option').first();
expect(green.text()).toEqual('Green');
expect(green.prop('value')).toEqual('#00ff00');
});
});
});
23 changes: 16 additions & 7 deletions addons/knobs/src/components/types/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,27 @@ const styles = {
};

class SelectType extends React.Component {
_makeOpt(key, val) {
_makeOpt(key, value, selectV2) {
const opts = {
key,
value: key,
};

return <option {...opts}>{val}</option>;
let display = value;

if (selectV2) {
opts.value = value;
display = key;
}

return <option {...opts}>{display}</option>;
}
_options(values) {
_options({ options, selectV2 }) {
let data = [];
if (Array.isArray(values)) {
data = values.map(val => this._makeOpt(val, val));
if (Array.isArray(options)) {
data = options.map(val => this._makeOpt(val, val));
} else {
data = Object.keys(values).map(key => this._makeOpt(key, values[key]));
data = Object.keys(options).map(key => this._makeOpt(key, options[key], selectV2));
}

return data;
Expand All @@ -49,7 +56,7 @@ class SelectType extends React.Component {
value={knob.value}
onChange={e => onChange(e.target.value)}
>
{this._options(knob.options)}
{this._options(knob)}
</select>
);
}
Expand All @@ -64,6 +71,8 @@ SelectType.propTypes = {
knob: PropTypes.shape({
name: PropTypes.string,
value: PropTypes.string,
options: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
selectV2: PropTypes.bool,
}),
onChange: PropTypes.func,
};
Expand Down
9 changes: 6 additions & 3 deletions addons/knobs/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ import {
number,
object,
select,
selectV2,
text,
} from './base';

export { knob, text, boolean, number, color, object, array, date, button, select };
export { knob, text, boolean, number, color, object, array, date, button, select, selectV2 };

deprecate(() => {},
'Using @storybook/addon-knobs directly is discouraged, please use @storybook/addon-knobs/{{framework}}');
deprecate(
() => {},
'Using @storybook/addon-knobs directly is discouraged, please use @storybook/addon-knobs/{{framework}}'
);

// generic higher-order component decorator for all platforms - usage is discouraged
// This file Should be removed with 4.0 release
Expand Down
3 changes: 2 additions & 1 deletion addons/knobs/src/react/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ import {
array,
date,
select,
selectV2,
button,
manager,
} from '../base';

export { knob, text, boolean, number, color, object, array, date, select, button };
export { knob, text, boolean, number, color, object, array, date, select, selectV2, button };

export const reactHandler = (channel, knobStore) => getStory => context => {
const initialContent = getStory(context);
Expand Down
3 changes: 2 additions & 1 deletion addons/knobs/src/vue/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import {
array,
date,
select,
selectV2,
button,
manager,
} from '../base';

export { knob, text, boolean, number, color, object, array, date, select, button };
export { knob, text, boolean, number, color, object, array, date, select, selectV2, button };

export const vueHandler = (channel, knobStore) => getStory => context => ({
data() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ exports[`Storyshots Addons|Knobs.withKnobs tweaks static values 1`] = `
style="background-color:#ffff00;border:3px solid #ff00ff;padding:10px"
>
<p>
My name is Storyteller, I'm 70 years old, and my favorite fruit is apple.
My name is Storyteller, I'm 70 years old, and my favorite fruit is apple. I also enjoy lime.
</p>
<p>
My birthday is: January 20, 2017
Expand Down Expand Up @@ -70,7 +70,7 @@ exports[`Storyshots Addons|Knobs.withKnobsOptions tweaks static values with debo
If you are encountering performance issues with state updating too often, use withKnobsOptions to debounce changes.
</p>
<p>
My name is Storyteller, I'm 70 years old, and my favorite fruit is apple.
My name is Storyteller, I'm 70 years old, and my favorite fruit is apple. I also enjoy lime.
</p>
<p>
My birthday is: January 20, 2017
Expand Down
17 changes: 15 additions & 2 deletions examples/official-storybook/stories/addon-knobs.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
boolean,
color,
select,
selectV2,
array,
date,
button,
Expand Down Expand Up @@ -56,6 +57,12 @@ storiesOf('Addons|Knobs.withKnobs', module)
cherry: 'Cherry',
};
const fruit = select('Fruit', fruits, 'apple');
const otherFruits = {
Lime: 'lime',
Coconut: 'coconut',
Tomato: 'tomato',
};
const otherFruit = selectV2('Other Fruit', otherFruits, 'lime');
const dollars = number('Dollars', 12.5, { min: 0, max: 100, step: 0.01 });
const years = number('Years in NY', 9);

Expand All @@ -71,7 +78,7 @@ storiesOf('Addons|Knobs.withKnobs', module)
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}.`;
const intro = `My name is ${name}, I'm ${age} years old, and my favorite fruit is ${fruit}. I also enjoy ${otherFruit}.`;
const style = { backgroundColor, ...otherStyles };
const salutation = nice ? 'Nice to meet you!' : 'Leave me alone!';
const dateOptions = { year: 'numeric', month: 'long', day: 'numeric' };
Expand Down Expand Up @@ -113,6 +120,12 @@ storiesOf('Addons|Knobs.withKnobsOptions', module)
cherry: 'Cherry',
};
const fruit = select('Fruit', fruits, 'apple');
const otherFruits = {
Lime: 'lime',
Coconut: 'coconut',
Tomato: 'tomato',
};
const otherFruit = selectV2('Other Fruit', otherFruits, 'lime');
const dollars = number('Dollars', 12.5, { min: 0, max: 100, step: 0.01 });

const backgroundColor = color('background', '#ffff00');
Expand All @@ -127,7 +140,7 @@ storiesOf('Addons|Knobs.withKnobsOptions', module)
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}.`;
const intro = `My name is ${name}, I'm ${age} years old, and my favorite fruit is ${fruit}. I also enjoy ${otherFruit}.`;
const style = { backgroundColor, ...otherStyles };
const salutation = nice ? 'Nice to meet you!' : 'Leave me alone!';
const dateOptions = { year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' };
Expand Down

0 comments on commit 7b0b539

Please sign in to comment.