Select: updates story from knobs to control (#33954)

* Select: updates story from knobs to control

* exported default storybook config as meta

* disables non-functional controls
This commit is contained in:
Uchechukwu Obasi 2021-05-12 09:45:01 +01:00 committed by GitHub
parent b0094b325e
commit 8c03b80490
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,10 +3,12 @@ import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/st
import { SelectableValue } from '@grafana/data';
import { Icon, Select, AsyncSelect, MultiSelect, AsyncMultiSelect } from '@grafana/ui';
import { getAvailableIcons, IconName } from '../../types';
import { select, boolean, number } from '@storybook/addon-knobs';
import { SelectCommonProps } from './types';
import { Meta, Story } from '@storybook/react';
import { kebabCase } from 'lodash';
import { generateOptions } from './mockOptions';
import mdx from './Select.mdx';
import { auto } from '@popperjs/core';
export default {
title: 'Forms/Select',
@ -17,10 +19,56 @@ export default {
docs: {
page: mdx,
},
knobs: {
disable: true,
},
controls: {
exclude: [
'getOptionValue',
'getOptionLabel',
'formatCreateLabel',
'filterOption',
'className',
'components',
'defaultValue',
'id',
'inputId',
'onBlur',
'onChange',
'onCloseMenu',
'onCreateOption',
'onInputChange',
'onKeyDown',
'onOpenMenu',
'prefix',
'renderControl',
'options',
'isOptionDisabled',
'maxVisibleValues',
'aria-label',
'noOptionsMessage',
'menuPosition',
'value',
],
},
},
};
const BEHAVIOUR_GROUP = 'Behaviour props';
args: {
width: 0,
disabled: false,
isLoading: false,
invalid: false,
icon: 'arrow-down',
},
argTypes: {
width: { control: { type: 'range', min: 1, max: 100 } },
icon: {
control: {
type: 'select',
options: getAvailableIcons(),
},
},
},
} as Meta;
const loadAsyncOptions = () => {
return new Promise<Array<SelectableValue<string>>>((resolve) => {
@ -30,63 +78,16 @@ const loadAsyncOptions = () => {
});
};
const getKnobs = () => {
const disabled = boolean('Disabled', false, BEHAVIOUR_GROUP);
const invalid = boolean('Invalid', false, BEHAVIOUR_GROUP);
const loading = boolean('Loading', false, BEHAVIOUR_GROUP);
const prefixSuffixOpts = {
None: null,
Text: '$',
...getAvailableIcons().reduce<Record<string, string>>((prev, c) => {
return {
...prev,
[`Icon: ${c}`]: `icon-${c}`,
};
}, {}),
};
const VISUAL_GROUP = 'Visual options';
// ---
const prefix = select('Prefix', prefixSuffixOpts, null, VISUAL_GROUP);
const width = number('Width', 0, undefined, VISUAL_GROUP);
let prefixEl: any = prefix;
if (prefix && prefix.match(/icon-/g)) {
prefixEl = <Icon name={prefix.replace(/icon-/g, '') as IconName} />;
}
return {
width,
disabled,
invalid,
loading,
prefixEl,
};
const getPrefix = (prefix: string) => {
const prefixEl = <Icon name={prefix as IconName} />;
return prefixEl;
};
const getMultiSelectKnobs = () => {
const isClearable = boolean('Clearable', false, BEHAVIOUR_GROUP);
const closeMenuOnSelect = boolean('Close on Select', false, BEHAVIOUR_GROUP);
const maxVisibleValues = number('Max. visible values', 5, undefined, BEHAVIOUR_GROUP);
interface StoryProps extends Partial<SelectCommonProps<string>> {
icon: string;
}
return {
isClearable,
closeMenuOnSelect,
maxVisibleValues,
};
};
const getDynamicProps = () => {
const knobs = getKnobs();
return {
width: knobs.width,
disabled: knobs.disabled,
isLoading: knobs.loading,
invalid: knobs.invalid,
prefix: knobs.prefixEl,
};
};
export const Basic = () => {
export const Basic: Story<StoryProps> = (args) => {
const [value, setValue] = useState<SelectableValue<string>>();
return (
@ -97,16 +98,16 @@ export const Basic = () => {
onChange={(v) => {
setValue(v);
}}
{...getDynamicProps()}
prefix={getPrefix(args.icon)}
{...args}
/>
</>
);
};
/**
* Uses plain values instead of SelectableValue<T>
*/
export const BasicSelectPlainValue = () => {
export const BasicSelectPlainValue: Story<StoryProps> = (args) => {
const [value, setValue] = useState<string>();
return (
<>
@ -116,16 +117,16 @@ export const BasicSelectPlainValue = () => {
onChange={(v) => {
setValue(v.value);
}}
{...getDynamicProps()}
prefix={getPrefix(args.icon)}
{...args}
/>
</>
);
};
/**
* Uses plain values instead of SelectableValue<T>
*/
export const SelectWithOptionDescriptions = () => {
export const SelectWithOptionDescriptions: Story = (args) => {
// TODO this is not working with new Select
const [value, setValue] = useState<number>();
@ -148,7 +149,8 @@ export const SelectWithOptionDescriptions = () => {
onChange={(v) => {
setValue(v.value);
}}
{...getDynamicProps()}
prefix={getPrefix(args.icon)}
{...args}
/>
</>
);
@ -157,7 +159,7 @@ export const SelectWithOptionDescriptions = () => {
/**
* Uses plain values instead of SelectableValue<T>
*/
export const MultiPlainValue = () => {
export const MultiPlainValue: Story = (args) => {
const [value, setValue] = useState<string[]>();
return (
@ -168,13 +170,14 @@ export const MultiPlainValue = () => {
onChange={(v) => {
setValue(v.map((v: any) => v.value));
}}
{...getDynamicProps()}
prefix={getPrefix(args.icon)}
{...args}
/>
</>
);
};
export const MultiSelectWithOptionGroups = () => {
export const MultiSelectWithOptionGroups: Story = (args) => {
const [value, setValue] = useState<string[]>();
return (
@ -188,13 +191,14 @@ export const MultiSelectWithOptionGroups = () => {
onChange={(v) => {
setValue(v.map((v: any) => v.value));
}}
{...getDynamicProps()}
prefix={getPrefix(args.icon)}
{...args}
/>
</>
);
};
export const MultiSelectBasic = () => {
export const MultiSelectBasic: Story = (args) => {
const [value, setValue] = useState<Array<SelectableValue<string>>>([]);
return (
@ -205,14 +209,19 @@ export const MultiSelectBasic = () => {
onChange={(v) => {
setValue(v);
}}
{...getDynamicProps()}
{...getMultiSelectKnobs()}
prefix={getPrefix(args.icon)}
{...args}
/>
</>
);
};
MultiSelectBasic.args = {
isClearable: false,
closeMenuOnSelect: false,
maxVisibleValues: 5,
};
export const MultiSelectAsync = () => {
export const MultiSelectAsync: Story = (args) => {
const [value, setValue] = useState<Array<SelectableValue<string>>>();
return (
@ -223,13 +232,16 @@ export const MultiSelectAsync = () => {
onChange={(v) => {
setValue(v);
}}
allowCustomValue
{...getDynamicProps()}
prefix={getPrefix(args.icon)}
{...args}
/>
);
};
MultiSelectAsync.args = {
allowCustomValue: false,
};
export const BasicSelectAsync = () => {
export const BasicSelectAsync: Story = (args) => {
const [value, setValue] = useState<SelectableValue<string>>();
return (
@ -240,12 +252,13 @@ export const BasicSelectAsync = () => {
onChange={(v) => {
setValue(v);
}}
{...getDynamicProps()}
prefix={getPrefix(args.icon)}
{...args}
/>
);
};
export const AutoMenuPlacement = () => {
export const AutoMenuPlacement: Story = (args) => {
const [value, setValue] = useState<SelectableValue<string>>();
return (
@ -257,14 +270,18 @@ export const AutoMenuPlacement = () => {
onChange={(v) => {
setValue(v);
}}
{...getDynamicProps()}
prefix={getPrefix(args.icon)}
{...args}
/>
</div>
</>
);
};
AutoMenuPlacement.args = {
menuPlacement: auto,
};
export const CustomValueCreation = () => {
export const CustomValueCreation: Story = (args) => {
const [value, setValue] = useState<SelectableValue<string>>();
const [customOptions, setCustomOptions] = useState<Array<SelectableValue<string>>>([]);
const options = generateOptions();
@ -276,14 +293,18 @@ export const CustomValueCreation = () => {
onChange={(v) => {
setValue(v);
}}
allowCustomValue
allowCustomValue={args.allowCustomValue}
onCreateOption={(v) => {
const customValue: SelectableValue<string> = { value: kebabCase(v), label: v };
setCustomOptions([...customOptions, customValue]);
setValue(customValue);
}}
{...getDynamicProps()}
prefix={getPrefix(args.icon)}
{...args}
/>
</>
);
};
CustomValueCreation.args = {
allowCustomValue: true,
};