Select

Maintainer:
korvin89
GitHub
size
pin
placeholder
label
multiple
filterable
disabled
hasClear
import {Select} from '@gravity-ui/uikit';

Select is a control that provides a list of options that a user can select.

Options

Options to select.

Defining options

You can define options as an array of objects or as the children of a component. The first approach is useful for cases where options require complex preparation and, possibly, memorization. The second one is convenient when there are few options, and their configuration does not require complex calculations.

Flat list

Array of objects

Child nodes

<Select
  placeholder="value"
  options={[
    {value: 'val_1', content: 'Value 1'},
    {value: 'val_2', content: 'Value 2'},
    {value: 'val_3', content: 'Value 3'},
    {value: 'val_4', content: 'Value 4'},
  ]}
/>
<Select placeholder="value">
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>

Grouped list

Array of objects

Child nodes

<Select
  placeholder="value"
  options={[
    {
      label: 'Group 1',
      options: [
        {value: 'val_1', content: 'Value 1'},
        {value: 'val_2', content: 'Value 2'},
      ],
    },
    {
      label: 'Group 2',
      options: [
        {value: 'val_3', content: 'Value 3'},
        {value: 'val_4', content: 'Value 4'},
      ],
    },
  ]}
/>
<Select placeholder="value">
  <Select.OptionGroup label="Group 1">
    <Select.Option value="val_1" content="Value 1" />
    <Select.Option value="val_2" content="Value 2" />
  </Select.OptionGroup>
  <Select.OptionGroup label="Group 2">
    <Select.Option value="val_3" content="Value 3" />
    <Select.Option value="val_4" content="Value 4" />
  </Select.OptionGroup>
</Select>

Storing data in options

You can define and store unique data in each option by using the option.data property. This can be useful when you need to enrich the data when using the onUpdate callback or, for example, when drawing your options with renderOption.

Selecting multiple options

To enable multiple selection, use the multiple property. Its default value is false.

<Select multiple={true} placeholder="values">
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>

Counter

You can add a counter of the selected items to the component using the hasCounter property.

0
<Select multiple={true} hasCounter={true} placeholder="values">
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>

Filtering options

To enable filter section, use the filterable property. Its default value is false.

<Select filterable={true} placeholder="Filterable">
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>

Size

To manage the default control and option size, use the size property. Its default size is m.

<Select size="s" placeholder="S Size">
  <Select.Option value="val_1">Value 1</Select.Option>
</Select>
<Select size="m" placeholder="M Size">
  <Select.Option value="val_1">Value 1</Select.Option>
</Select>
<Select size="l" placeholder="L Size">
  <Select.Option value="val_1">Value 1</Select.Option>
</Select>
<Select size="xl" placeholder="XL Size">
  <Select.Option value="val_1">Value 1</Select.Option>
</Select>

Control width

By default, the control width stretches to match the width of the content of the selected options. You can manage it by using the width property:

'max': Stretches to the full width of the parent.

number: Applies width in pixels.

Default

Max

In pixels

<Select>
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>
<Select width="max">
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>
<Select width={150}>
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>

You can manage the popup width with the popupWidth property. The available values are:

'fit': Apply control width.

number: Apply width in pixels.

Points to note about the default behavior:

  • The popup width is equal to the width of the widest option, but not wider than 90vw. This does not apply in case you use virtualization.

  • Narrow options are stretched to fit the width of the control.

Non-virtualized list

A regular list when all the elements are in the dom tree at once.

Default

Fit

In pixels

<Select>
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>
<Select>
  <Select.Option value="val_1">Loooooooooooooooooooong Value 1</Select.Option>
  <Select.Option value="val_2">Loooooooooooooooooooong Value 2</Select.Option>
  <Select.Option value="val_3">Loooooooooooooooooooong Value 3</Select.Option>
  <Select.Option value="val_4">Loooooooooooooooooooong Value 4</Select.Option>
</Select>
<Select popupWidth="fit">
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>
<Select popupWidth="fit">
  <Select.Option value="val_1">Loooooooooooooooooooong Value 1</Select.Option>
  <Select.Option value="val_2">Loooooooooooooooooooong Value 2</Select.Option>
  <Select.Option value="val_3">Loooooooooooooooooooong Value 3</Select.Option>
  <Select.Option value="val_4">Loooooooooooooooooooong Value 4</Select.Option>
</Select>
<Select popupWidth={80}>
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>
<Select popupWidth={80}>
  <Select.Option value="val_1">Loooooooooooooooooooong Value 1</Select.Option>
  <Select.Option value="val_2">Loooooooooooooooooooong Value 2</Select.Option>
  <Select.Option value="val_3">Loooooooooooooooooooong Value 3</Select.Option>
  <Select.Option value="val_4">Loooooooooooooooooooong Value 4</Select.Option>
</Select>

Virtualized list

For optimal display of a large number of options, Select has a built-in list virtualization tool. Virtualization is enabled after overcoming the threshold of the number of options (50 by default). You can manage this value using the virtualizationThreshold property.

When using virtualization, some restrictions apply to the popup element:

  • The popup width no longer gets adjusted to the length of the longest option.

  • The minimum width of the popup is equal to the width of the control, or 100px if the control is shorter.

Default

In pixels

<Select>
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>
<Select>
  <Select.Option value="val_1">Loooooooooooooooooooong Value 1</Select.Option>
  <Select.Option value="val_2">Loooooooooooooooooooong Value 2</Select.Option>
  <Select.Option value="val_3">Loooooooooooooooooooong Value 3</Select.Option>
  <Select.Option value="val_4">Loooooooooooooooooooong Value 4</Select.Option>
</Select>
<Select popupWidth="fit">
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>
<Select popupWidth="fit">
  <Select.Option value="val_1">Loooooooooooooooooooong Value 1</Select.Option>
  <Select.Option value="val_2">Loooooooooooooooooooong Value 2</Select.Option>
  <Select.Option value="val_3">Loooooooooooooooooooong Value 3</Select.Option>
  <Select.Option value="val_4">Loooooooooooooooooooong Value 4</Select.Option>
</Select>
<Select popupWidth={80}>
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>
<Select popupWidth={80}>
  <Select.Option value="val_1">Loooooooooooooooooooong Value 1</Select.Option>
  <Select.Option value="val_2">Loooooooooooooooooooong Value 2</Select.Option>
  <Select.Option value="val_3">Loooooooooooooooooooong Value 3</Select.Option>
  <Select.Option value="val_4">Loooooooooooooooooooong Value 4</Select.Option>
</Select>

Advanced usage

There are many ways to customize your Select.

Rendering custom control

To render a custom control, use the renderControl property. Note: You should forward all arguments to your node in order to enable consistent behavior, just as when using the default control.

<Select
  renderControl={({onClick, onKeyDown, ref}) => {
    return <button ref={ref} onClick={onClick} extraProps={{onKeyDown}}>Custom control</button>
  }}
>
  <Select.Option value="val_1">Value 1</Select.Option>
  <Select.Option value="val_2">Value 2</Select.Option>
  <Select.Option value="val_3">Value 3</Select.Option>
  <Select.Option value="val_4">Value 4</Select.Option>
</Select>

Rendering custom filter section

To render a custom filter section, use the renderFilter property and set the filterable property to true. Note: You need to forward all arguments to your node in order to enable a properly working filter, just as when using the default configuration.

<Select
  placeholder="Custom filter"
  filterable={true}
  renderFilter={({onChange, onKeyDown, ref, value}) => {
    return (
      <div style={{display: 'flex', flexDirection: 'column'}}>
        <input
          ref={ref}
          value={value}
          size="1"
          onKeyDown={onKeyDown}
          onChange={(e) => onChange(e.target.value)}
        />
        <button>Do smth</button>
      </div>
    );
  }}
>
  <Select.Option value="val_1">Value 1</Select.Option>
</Select>

Rendering custom options

To render custom options, use the renderOption property:

<Select
  renderOption={(option) => {
    return (
      <div style={{color: option.data.color}}>
        {option.children}
      </div>
    );
  }}
>
  <Select.Option value="val_1" data={{color: '#8FE1A1'}}>Value 1</Select.Option>
  <Select.Option value="val_2" data={{color: '#38C0A8'}}>Value 2</Select.Option>
  <Select.Option value="val_3" data={{color: '#3A7AC3'}}>Value 3</Select.Option>
  <Select.Option value="val_4" data={{color: '#534581'}}>Value 4</Select.Option>
</Select>

Rendering custom selected options

To render custom selected options, use the renderSelectedOption property:

<Select
  renderSelectedOption={(option) => {
    return (
      <div style={{color: option.data.color}}>
        {option.children}
      </div>
    );
  }}
>
  <Select.Option value="val_1" data={{color: '#8FE1A1'}}>Value 1</Select.Option>
  <Select.Option value="val_2" data={{color: '#38C0A8'}}>Value 2</Select.Option>
  <Select.Option value="val_3" data={{color: '#3A7AC3'}}>Value 3</Select.Option>
  <Select.Option value="val_4" data={{color: '#534581'}}>Value 4</Select.Option>
</Select>

Rendering options with different heights

Options have a fixed height according to the size property. If you need to render options with different heights, you can use the option.data property. It will store information about what height you need to set for the options, as well as the getOptionHeight property to set this value.

<Select
  getOptionHeight={(option) => option.data.height}
>
  <Select.Option value="val_1" data={{height: 20}}>Value 1</Select.Option>
  <Select.Option value="val_2" data={{height: 40}}>Value 2</Select.Option>
  <Select.Option value="val_3" data={{height: 60}}>Value 3</Select.Option>
  <Select.Option value="val_4" data={{height: 80}}>Value 4</Select.Option>
</Select>

Rendering custom popup

To render custom popup, use the renderPopup property.

<Select
  filterable
  placeholder="Custom popup"
  renderPopup={({renderList, renderFilter}) => {
    return (
      <React.Fragment>
        {renderFilter()}
        <div style={{width: "100%", height: "20px", backgroundColor: "tomato"}} />
        {renderList()}
      </React.Fragment>
    );
  }}
>
  <Select.Option value="val_1" data={{color: '#8FE1A1'}}>Value 1</Select.Option>
  <Select.Option value="val_2" data={{color: '#38C0A8'}}>Value 2</Select.Option>
  <Select.Option value="val_3" data={{color: '#3A7AC3'}}>Value 3</Select.Option>
  <Select.Option value="val_4" data={{color: '#534581'}}>Value 4</Select.Option>
</Select>

Error

This Select state is for incorrect user input. To change the Select appearance, use the validationState property with the "invalid" value. Optionally, you can provide an error message through the errorMessage property. By default, the message text is rendered outside the component. You can change this with the errorPlacement property.

Error message
<Select
    placeholder="Placeholder"
    errorMessage="Error message"
    validationState="invalid"
>
    <Select.Option value="val_1">Value 1</Select.Option>
    <Select.Option value="val_2">Value 2</Select.Option>
    <Select.Option value="val_3">Value 3</Select.Option>
    <Select.Option value="val_4">Value 4</Select.Option>
</Select>
<Select
    placeholder="Placeholder"
    errorPlacement="inside"
    errorMessage="Error message"
    validationState="invalid"
>
    <Select.Option value="val_1">Value 1</Select.Option>
    <Select.Option value="val_2">Value 2</Select.Option>
    <Select.Option value="val_3">Value 3</Select.Option>
    <Select.Option value="val_4">Value 4</Select.Option>
</Select>

Properties

NameDescriptionTypeDefault
classNameControl classNamestring
defaultValueDefault values that represent selected options in case of using an uncontrolled statestring[]
disabledShows that the user cannot work with the controlbooleanfalse
filterableShows that select popup has a filter sectionbooleanfalse
filterOptionUsed to compare option with filterfunction
filterPlaceholderDefault filter input placeholder textstring
getOptionHeightUsed to set height of customized user optionsfunction
getOptionGroupHeightUsed to set height of customized user option groupfunction
hasClearEnables displaying icon for clearing selected optionsbooleanfalse
idid HTML attributestring
labelControl labelstring
loadingAdds the loading item to the end of the option list. Works like a persistent loading indicator while the options list is empty.boolean
multipleShows whether multiple options can be selected in the listbooleanfalse
nameName of the controlstring
onBlurHandler that is called when the element loses focus.function
filterControlled filter valuestring''
onFilterChangeFires every time after changing the filterfunction
onFocusHandler that is called when the element gets focusfunction
onLoadMoreFires when the loading indicator gets visiblefunction
onOpenChangeFires every time after changing popup visibilityfunction
onUpdateFires when an alteration to the Select value is committed by the userfunction
optionsOptions to select(SelectOption | SelectOptionGroup)[]
pinControl border viewstring'round-round'
placeholderPlaceholder textstring
popupClassNamePopup with the option list classNamestring
popupPlacementPopup placementPopupPlacement Array<PopupPlacement>['bottom-start', 'bottom-end', 'top-start', 'top-end']
popupWidthPopup widthnumber | 'fit' | 'outfit''outfit'
qaTest id attribute (data-qa)string
renderControlUsed to render user controlfunction
renderEmptyOptionsUsed to render a node for an empty option listfunction
renderFilterUsed to render user filter sectionfunction
renderOptionUsed to render user optionsfunction
renderOptionGroupUsed to render user option groupsfunction
renderSelectedOptionUsed to render user selected optionsfunction
renderPopupUsed to render user popup contentfunction
sizeControl / options sizestring'm'
valueValues that represent selected optionsstring[]
viewControl viewstring'normal'
virtualizationThresholdOption count threshold after which virtualization is enablednumber50
widthControl widthstring | numberundefined
errorMessageError textstring
errorPlacementError positionoutside insideoutside
validationStateValidation state"invalid"
hasCounterShows the selected option count. The counter appears only when the multiple selection is enabled.boolean

CSS API

NameDescription
--g-select-focus-outline-colorOutline color if focused (missing by default)