mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
b0094b325e
commit
8c03b80490
@ -3,10 +3,12 @@ import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/st
|
|||||||
import { SelectableValue } from '@grafana/data';
|
import { SelectableValue } from '@grafana/data';
|
||||||
import { Icon, Select, AsyncSelect, MultiSelect, AsyncMultiSelect } from '@grafana/ui';
|
import { Icon, Select, AsyncSelect, MultiSelect, AsyncMultiSelect } from '@grafana/ui';
|
||||||
import { getAvailableIcons, IconName } from '../../types';
|
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 { kebabCase } from 'lodash';
|
||||||
import { generateOptions } from './mockOptions';
|
import { generateOptions } from './mockOptions';
|
||||||
import mdx from './Select.mdx';
|
import mdx from './Select.mdx';
|
||||||
|
import { auto } from '@popperjs/core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Forms/Select',
|
title: 'Forms/Select',
|
||||||
@ -17,10 +19,56 @@ export default {
|
|||||||
docs: {
|
docs: {
|
||||||
page: mdx,
|
page: mdx,
|
||||||
},
|
},
|
||||||
|
knobs: {
|
||||||
|
disable: true,
|
||||||
},
|
},
|
||||||
};
|
controls: {
|
||||||
|
exclude: [
|
||||||
const BEHAVIOUR_GROUP = 'Behaviour props';
|
'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',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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 = () => {
|
const loadAsyncOptions = () => {
|
||||||
return new Promise<Array<SelectableValue<string>>>((resolve) => {
|
return new Promise<Array<SelectableValue<string>>>((resolve) => {
|
||||||
@ -30,63 +78,16 @@ const loadAsyncOptions = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getKnobs = () => {
|
const getPrefix = (prefix: string) => {
|
||||||
const disabled = boolean('Disabled', false, BEHAVIOUR_GROUP);
|
const prefixEl = <Icon name={prefix as IconName} />;
|
||||||
const invalid = boolean('Invalid', false, BEHAVIOUR_GROUP);
|
return prefixEl;
|
||||||
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 getMultiSelectKnobs = () => {
|
interface StoryProps extends Partial<SelectCommonProps<string>> {
|
||||||
const isClearable = boolean('Clearable', false, BEHAVIOUR_GROUP);
|
icon: string;
|
||||||
const closeMenuOnSelect = boolean('Close on Select', false, BEHAVIOUR_GROUP);
|
}
|
||||||
const maxVisibleValues = number('Max. visible values', 5, undefined, BEHAVIOUR_GROUP);
|
|
||||||
|
|
||||||
return {
|
export const Basic: Story<StoryProps> = (args) => {
|
||||||
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 = () => {
|
|
||||||
const [value, setValue] = useState<SelectableValue<string>>();
|
const [value, setValue] = useState<SelectableValue<string>>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -97,16 +98,16 @@ export const Basic = () => {
|
|||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue(v);
|
setValue(v);
|
||||||
}}
|
}}
|
||||||
{...getDynamicProps()}
|
prefix={getPrefix(args.icon)}
|
||||||
|
{...args}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses plain values instead of SelectableValue<T>
|
* Uses plain values instead of SelectableValue<T>
|
||||||
*/
|
*/
|
||||||
export const BasicSelectPlainValue = () => {
|
export const BasicSelectPlainValue: Story<StoryProps> = (args) => {
|
||||||
const [value, setValue] = useState<string>();
|
const [value, setValue] = useState<string>();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -116,16 +117,16 @@ export const BasicSelectPlainValue = () => {
|
|||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue(v.value);
|
setValue(v.value);
|
||||||
}}
|
}}
|
||||||
{...getDynamicProps()}
|
prefix={getPrefix(args.icon)}
|
||||||
|
{...args}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses plain values instead of SelectableValue<T>
|
* Uses plain values instead of SelectableValue<T>
|
||||||
*/
|
*/
|
||||||
export const SelectWithOptionDescriptions = () => {
|
export const SelectWithOptionDescriptions: Story = (args) => {
|
||||||
// TODO this is not working with new Select
|
// TODO this is not working with new Select
|
||||||
|
|
||||||
const [value, setValue] = useState<number>();
|
const [value, setValue] = useState<number>();
|
||||||
@ -148,7 +149,8 @@ export const SelectWithOptionDescriptions = () => {
|
|||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue(v.value);
|
setValue(v.value);
|
||||||
}}
|
}}
|
||||||
{...getDynamicProps()}
|
prefix={getPrefix(args.icon)}
|
||||||
|
{...args}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -157,7 +159,7 @@ export const SelectWithOptionDescriptions = () => {
|
|||||||
/**
|
/**
|
||||||
* Uses plain values instead of SelectableValue<T>
|
* Uses plain values instead of SelectableValue<T>
|
||||||
*/
|
*/
|
||||||
export const MultiPlainValue = () => {
|
export const MultiPlainValue: Story = (args) => {
|
||||||
const [value, setValue] = useState<string[]>();
|
const [value, setValue] = useState<string[]>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -168,13 +170,14 @@ export const MultiPlainValue = () => {
|
|||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue(v.map((v: any) => v.value));
|
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[]>();
|
const [value, setValue] = useState<string[]>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -188,13 +191,14 @@ export const MultiSelectWithOptionGroups = () => {
|
|||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue(v.map((v: any) => v.value));
|
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>>>([]);
|
const [value, setValue] = useState<Array<SelectableValue<string>>>([]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -205,14 +209,19 @@ export const MultiSelectBasic = () => {
|
|||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue(v);
|
setValue(v);
|
||||||
}}
|
}}
|
||||||
{...getDynamicProps()}
|
prefix={getPrefix(args.icon)}
|
||||||
{...getMultiSelectKnobs()}
|
{...args}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
MultiSelectBasic.args = {
|
||||||
|
isClearable: false,
|
||||||
|
closeMenuOnSelect: false,
|
||||||
|
maxVisibleValues: 5,
|
||||||
|
};
|
||||||
|
|
||||||
export const MultiSelectAsync = () => {
|
export const MultiSelectAsync: Story = (args) => {
|
||||||
const [value, setValue] = useState<Array<SelectableValue<string>>>();
|
const [value, setValue] = useState<Array<SelectableValue<string>>>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -223,13 +232,16 @@ export const MultiSelectAsync = () => {
|
|||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue(v);
|
setValue(v);
|
||||||
}}
|
}}
|
||||||
allowCustomValue
|
prefix={getPrefix(args.icon)}
|
||||||
{...getDynamicProps()}
|
{...args}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
MultiSelectAsync.args = {
|
||||||
|
allowCustomValue: false,
|
||||||
|
};
|
||||||
|
|
||||||
export const BasicSelectAsync = () => {
|
export const BasicSelectAsync: Story = (args) => {
|
||||||
const [value, setValue] = useState<SelectableValue<string>>();
|
const [value, setValue] = useState<SelectableValue<string>>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -240,12 +252,13 @@ export const BasicSelectAsync = () => {
|
|||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue(v);
|
setValue(v);
|
||||||
}}
|
}}
|
||||||
{...getDynamicProps()}
|
prefix={getPrefix(args.icon)}
|
||||||
|
{...args}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AutoMenuPlacement = () => {
|
export const AutoMenuPlacement: Story = (args) => {
|
||||||
const [value, setValue] = useState<SelectableValue<string>>();
|
const [value, setValue] = useState<SelectableValue<string>>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -257,14 +270,18 @@ export const AutoMenuPlacement = () => {
|
|||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue(v);
|
setValue(v);
|
||||||
}}
|
}}
|
||||||
{...getDynamicProps()}
|
prefix={getPrefix(args.icon)}
|
||||||
|
{...args}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
AutoMenuPlacement.args = {
|
||||||
|
menuPlacement: auto,
|
||||||
|
};
|
||||||
|
|
||||||
export const CustomValueCreation = () => {
|
export const CustomValueCreation: Story = (args) => {
|
||||||
const [value, setValue] = useState<SelectableValue<string>>();
|
const [value, setValue] = useState<SelectableValue<string>>();
|
||||||
const [customOptions, setCustomOptions] = useState<Array<SelectableValue<string>>>([]);
|
const [customOptions, setCustomOptions] = useState<Array<SelectableValue<string>>>([]);
|
||||||
const options = generateOptions();
|
const options = generateOptions();
|
||||||
@ -276,14 +293,18 @@ export const CustomValueCreation = () => {
|
|||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue(v);
|
setValue(v);
|
||||||
}}
|
}}
|
||||||
allowCustomValue
|
allowCustomValue={args.allowCustomValue}
|
||||||
onCreateOption={(v) => {
|
onCreateOption={(v) => {
|
||||||
const customValue: SelectableValue<string> = { value: kebabCase(v), label: v };
|
const customValue: SelectableValue<string> = { value: kebabCase(v), label: v };
|
||||||
setCustomOptions([...customOptions, customValue]);
|
setCustomOptions([...customOptions, customValue]);
|
||||||
setValue(customValue);
|
setValue(customValue);
|
||||||
}}
|
}}
|
||||||
{...getDynamicProps()}
|
prefix={getPrefix(args.icon)}
|
||||||
|
{...args}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
CustomValueCreation.args = {
|
||||||
|
allowCustomValue: true,
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user