mirror of
https://github.com/grafana/grafana.git
synced 2026-07-30 00:08:10 -05:00
Docs: Select (#23398)
* Start Select docs * Writ emore docs * Apply suggestions from code review Co-Authored-By: Alex Khomenko <Clarity-89@users.noreply.github.com> Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
This commit is contained in:
co-authored by
Alex Khomenko
parent
b980cedfd5
commit
fa6a43c6e5
@@ -0,0 +1,133 @@
|
||||
import { Props, Preview } from "@storybook/addon-docs/blocks";
|
||||
import { Select, AsyncSelect, MultiSelect, AsyncMultiSelect } from "./Select";
|
||||
import { generateOptions } from "./mockOptions";
|
||||
|
||||
# Select variants
|
||||
|
||||
Select is an input with the ability to search and create new values. It should be used when you have a list of options. If the data has a tree structure, consider using `Cascader` instead.
|
||||
Select has some features:
|
||||
|
||||
- Search a list of values
|
||||
- Select multiple values
|
||||
- Select from async data
|
||||
- Create custom values that aren't in the list
|
||||
|
||||
## Select
|
||||
|
||||
Select is the base for every component on this page. The approaches mentioned here are also applicable to `AsyncSelect`, `MultiSelect`, `AsyncMultiSelect`.
|
||||
|
||||
### Options format
|
||||
|
||||
There are four properties for each option:
|
||||
|
||||
- `label` - Text that is visible in the menu.
|
||||
- `value` - Could be anything, but is usually a string. Used to identify what is **actually** selected.
|
||||
- `description` - Longer description that describes the choice. Use this sparingly.
|
||||
- `imgUrl` - URL to an image. Use this when an image or icon provides more context for the option.
|
||||
|
||||
```jsx
|
||||
const options = [
|
||||
{ label: "Basic option", value: 0 },
|
||||
{ label: "Option with description", value: 1, description: "this is a description" },
|
||||
{
|
||||
label: "Option with description and image",
|
||||
value: 2,
|
||||
description: "This is a very elaborate description, describing all the wonders in the world.",
|
||||
imgUrl: "https://placekitten.com/40/40",
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
### Creatable option
|
||||
|
||||
Creatable option is used when you want to be able to add a custom value to the list of options. `allowCustomValue` needs to be true and you must handle the value creation with `onCreateOption`.
|
||||
|
||||
```jsx
|
||||
import { Select } from "@grafana/ui";
|
||||
|
||||
const SelectComponent = () => {
|
||||
const [value, setValue] = useState<SelectableValue<number>>();
|
||||
|
||||
return (
|
||||
<Select
|
||||
options={option}
|
||||
value={value}
|
||||
allowCustomValue
|
||||
onCreateOption={customValue => {
|
||||
setValue(customValue);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## AsyncSelect
|
||||
|
||||
Like regular Select, but handles fetching options asynchronously. Use the `loadOptions` prop for the async function that loads the options. If `defaultOptions` is set to `true`, `loadOptions` will be called when the component is mounted.
|
||||
|
||||
```jsx
|
||||
|
||||
import { AsyncSelect } from '@grafana/ui';
|
||||
|
||||
const basicSelectAsync = () => {
|
||||
const [value, setValue] = useState<SelectableValue<string>>();
|
||||
|
||||
return (
|
||||
<AsyncSelect
|
||||
loadOptions={loadAsyncOptions}
|
||||
defaultOptions
|
||||
value={value}
|
||||
onChange={v => {
|
||||
setValue(v);
|
||||
}}
|
||||
size="md"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
Where the async function could look like this:
|
||||
|
||||
```tsx
|
||||
const loadAsyncOptions = () => {
|
||||
return new Promise()<Array<SelectableValue<string>>>(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(options);
|
||||
}, 2000);
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
## MultiSelect
|
||||
|
||||
Possible to Select multiple values at the same time.
|
||||
|
||||
```tsx
|
||||
import { MultiSelect } from "@grafana/ui";
|
||||
|
||||
const multiSelect = () => {
|
||||
const [value, setValue] = useState<Array<SelectableValue<string>>>([]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<MultiSelect
|
||||
options={options}
|
||||
value={value}
|
||||
onChange={v => {
|
||||
setValue(v);
|
||||
}}
|
||||
size="md"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## AsyncMultiSelect
|
||||
|
||||
Like MultiSelect but handles data asynchronously with the `loadOptions` prop.
|
||||
|
||||
## Props
|
||||
|
||||
<Props of={Select} />
|
||||
@@ -10,11 +10,18 @@ import { ButtonSelect } from './ButtonSelect';
|
||||
import { getIconKnob } from '../../utils/storybook/knobs';
|
||||
import kebabCase from 'lodash/kebabCase';
|
||||
import { generateOptions } from './mockOptions';
|
||||
import mdx from './Select.mdx';
|
||||
|
||||
export default {
|
||||
title: 'Forms/Select',
|
||||
component: Select,
|
||||
decorators: [withCenteredStory, withHorizontallyCenteredStory],
|
||||
subcomponents: { AsyncSelect, MultiSelect, AsyncMultiSelect },
|
||||
parameters: {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const loadAsyncOptions = () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { kebabCase } from 'lodash';
|
||||
|
||||
export const generateOptions = () => {
|
||||
export const generateOptions = (desc = false) => {
|
||||
const values = [
|
||||
'Sharilyn Markowitz',
|
||||
'Naomi Striplin',
|
||||
@@ -28,5 +28,6 @@ export const generateOptions = () => {
|
||||
return values.map<SelectableValue<string>>(name => ({
|
||||
value: kebabCase(name),
|
||||
label: name,
|
||||
description: desc ? `This is a description of ${name}` : undefined,
|
||||
}));
|
||||
};
|
||||
|
||||
@@ -6,12 +6,15 @@ export type SelectValue<T> = T | SelectableValue<T> | T[] | Array<SelectableValu
|
||||
|
||||
export interface SelectCommonProps<T> {
|
||||
allowCustomValue?: boolean;
|
||||
/** Focus is set to the Select when rendered*/
|
||||
autoFocus?: boolean;
|
||||
backspaceRemovesValue?: boolean;
|
||||
className?: string;
|
||||
/** Used for custom components. For more information, see `react-select` */
|
||||
components?: any;
|
||||
defaultValue?: any;
|
||||
disabled?: boolean;
|
||||
/** Function for formatting the text that is displayed when creating a new value*/
|
||||
formatCreateLabel?: (input: string) => string;
|
||||
getOptionLabel?: (item: SelectableValue<T>) => string;
|
||||
getOptionValue?: (item: SelectableValue<T>) => string;
|
||||
@@ -20,14 +23,17 @@ export interface SelectCommonProps<T> {
|
||||
isLoading?: boolean;
|
||||
isMulti?: boolean;
|
||||
isOpen?: boolean;
|
||||
/** Disables the possibility to type into the input*/
|
||||
isSearchable?: boolean;
|
||||
maxMenuHeight?: number;
|
||||
menuPlacement?: 'auto' | 'bottom' | 'top';
|
||||
menuPosition?: 'fixed' | 'absolute';
|
||||
/** The message to display when no options could be found */
|
||||
noOptionsMessage?: string;
|
||||
onBlur?: () => void;
|
||||
onChange: (value: SelectableValue<T>) => {} | void;
|
||||
onCloseMenu?: () => void;
|
||||
/** allowCustomValue must be enabled. Function decides what to do with that custom value. */
|
||||
onCreateOption?: (value: string) => void;
|
||||
onInputChange?: (label: string) => void;
|
||||
onKeyDown?: (event: React.KeyboardEvent) => void;
|
||||
|
||||
Reference in New Issue
Block a user