diff --git a/packages/grafana-ui/src/components/Select/Select.story.tsx b/packages/grafana-ui/src/components/Select/Select.story.tsx index af46b5d38e4..e6e12b4e4c2 100644 --- a/packages/grafana-ui/src/components/Select/Select.story.tsx +++ b/packages/grafana-ui/src/components/Select/Select.story.tsx @@ -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>>((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>((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 = ; - } - - return { - width, - disabled, - invalid, - loading, - prefixEl, - }; +const getPrefix = (prefix: string) => { + const prefixEl = ; + 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> { + 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 = (args) => { const [value, setValue] = useState>(); return ( @@ -97,16 +98,16 @@ export const Basic = () => { onChange={(v) => { setValue(v); }} - {...getDynamicProps()} + prefix={getPrefix(args.icon)} + {...args} /> ); }; - /** * Uses plain values instead of SelectableValue */ -export const BasicSelectPlainValue = () => { +export const BasicSelectPlainValue: Story = (args) => { const [value, setValue] = useState(); 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 */ -export const SelectWithOptionDescriptions = () => { +export const SelectWithOptionDescriptions: Story = (args) => { // TODO this is not working with new Select const [value, setValue] = useState(); @@ -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 */ -export const MultiPlainValue = () => { +export const MultiPlainValue: Story = (args) => { const [value, setValue] = useState(); 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(); 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>>([]); 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>>(); 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>(); 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>(); return ( @@ -257,14 +270,18 @@ export const AutoMenuPlacement = () => { onChange={(v) => { setValue(v); }} - {...getDynamicProps()} + prefix={getPrefix(args.icon)} + {...args} /> ); }; +AutoMenuPlacement.args = { + menuPlacement: auto, +}; -export const CustomValueCreation = () => { +export const CustomValueCreation: Story = (args) => { const [value, setValue] = useState>(); const [customOptions, setCustomOptions] = useState>>([]); const options = generateOptions(); @@ -276,14 +293,18 @@ export const CustomValueCreation = () => { onChange={(v) => { setValue(v); }} - allowCustomValue + allowCustomValue={args.allowCustomValue} onCreateOption={(v) => { const customValue: SelectableValue = { value: kebabCase(v), label: v }; setCustomOptions([...customOptions, customValue]); setValue(customValue); }} - {...getDynamicProps()} + prefix={getPrefix(args.icon)} + {...args} /> ); }; +CustomValueCreation.args = { + allowCustomValue: true, +};