import {Select} from '@gravity-ui/uikit';
Компонент Select — это контрол, который предоставляет список опций для выбора.
§Options
Опции для выбора.
§Определение опций
Опции можно определять в виде массива объектов или в качестве дочерних элементов компонента. Первый способ подходит для случаев, когда опции требуют сложной подготовки и, возможно, запоминания. Второй способ удобен, когда опций немного и их настройка не требует сложных вычислений.
§Одноуровневый список
import {Flex, Select} from '@gravity-ui/uikit'; const 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'}, ]; export default function () { return ( <> <Flex gap={1} alignItems="center"> Array of objects <Select placeholder="value" options={options} /> </Flex> <Flex gap={1} alignItems="center"> Child nodes <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> </Flex> </> ); }
§Группированный список
import {Flex, Select} from '@gravity-ui/uikit'; const groupedOptions = [ { 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'}, ], }, ]; export default function () { return ( <> <Flex gap={1} alignItems="center"> Array of objects <Select placeholder="value" options={groupedOptions} /> </Flex> <Flex gap={1} alignItems="center"> Child nodes <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> </Flex> </> ); }
§Хранение данных в опциях
С помощью свойства option.data можно определить и сохранить уникальные данные в каждой опции. Это может быть полезно при необходимости обогащения данных с использованием обратного вызова onUpdate или, например, при отрисовке опций с помощью renderOption.
§Выбор нескольких опций
Чтобы включить множественный выбор, используйте свойство multiple. Значение по умолчанию — false.
import {Select} from '@gravity-ui/uikit'; export default function () { return ( <Select multiple 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> ); }
§Счетчик
С помощью свойства hasCounter в компонент можно добавить счетчик выбранных опций.
import {Select} from '@gravity-ui/uikit'; export default function () { return ( <Select multiple hasCounter 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> ); }
§Фильтрация опций
Для активации секции фильтрации в списке опций используйте свойство filterable. Значение по умолчанию — false.
import {Select} from '@gravity-ui/uikit'; export default function () { return ( <Select filterable 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. Размер по умолчанию — m.
import {Select} from '@gravity-ui/uikit'; export default function () { return ( <> <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> </> ); }
§Ширина контрола
По умолчанию ширина контрола растягивается, чтобы соответствовать ширине содержимого выбранных опций. Вы можете самостоятельно регулировать ширину с помощью свойства width:
'max' — растягивает ширину контрола на всю ширину родительского элемента.
number — применяет ширину в пикселях.
Default
Max
In pixels
import {Select, SelectProps} from '@gravity-ui/uikit'; import {type CSSProperties} from 'react'; const containerStyle: CSSProperties = { width: 150, border: '2px dashed gray', textAlign: 'center', }; function SelectExample(props: SelectProps) { return ( <Select {...props}> <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> ); } export default function () { return ( <> <div style={containerStyle}> <h4>Default</h4> <SelectExample multiple /> </div> <div style={containerStyle}> <h4>Max</h4> <SelectExample width="max" multiple /> </div> <div style={containerStyle}> <h4>In pixels</h4> <SelectExample width={110} multiple /> </div> </> ); }
§Ширина списка опций.
Ширину списка опций можно изменять с помощью свойства popupWidth. Возможные значения:
'fit' — применяет ширину контрола.
number — применяет ширину в пикселях.
Особенности поведения по умолчанию:
-
Ширина списка опций соответствует ширине самой широкой опции, но не превышает
90vw. Это не применимо, если используется виртуализация. -
Узкие опции растягиваются до ширины контрола.
Default
Fit
In pixels
import {Box, Select, SelectProps} from '@gravity-ui/uikit'; import {type CSSProperties} from 'react'; const containerStyle: CSSProperties = { width: 200, border: '2px dashed gray', textAlign: 'center', }; function ShortValueSelect(props: SelectProps) { return ( <Select placeholder="Short value" {...props}> <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> ); } function LongValueSelect(props: SelectProps) { return ( <Select placeholder="Long value" {...props}> <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> ); } export default function () { return ( <> <div style={containerStyle}> <h4>Default</h4> <Box spacing={{my: 3}}> <ShortValueSelect /> </Box> <Box spacing={{my: 3}}> <LongValueSelect /> </Box> </div> <div style={containerStyle}> <h4>Fit</h4> <Box spacing={{my: 3}}> <ShortValueSelect popupWidth="fit" /> </Box> <Box spacing={{my: 3}}> <LongValueSelect popupWidth="fit" /> </Box> </div> <div style={containerStyle}> <h4>In pixels</h4> <Box spacing={{my: 3}}> <ShortValueSelect popupWidth={80} /> </Box> <Box spacing={{my: 3}}> <LongValueSelect popupWidth={80} /> </Box> </div> </> ); }
§Виртуализированный список
Для оптимального отображения большого количества опций в компоненте Selectпредусмотрен встроенный инструмент виртуализации списка. Виртуализация включается, когда количество опций превышает пороговое значение (по умолчанию 50). Пороговое значение можно изменить с помощью свойства virtualizationThreshold.
При включении виртуализации к элементу списка опций применяются определенные ограничения:
-
Ширина списка опций больше не изменяется в зависимости от длины самой длинной опции.
-
Минимальная ширина списка опций равна ширине контрола или
100px, если ширина контрола меньше100px.
Default
In pixels
import {Box, Select} from '@gravity-ui/uikit'; import {type CSSProperties} from 'react'; const containerStyle: CSSProperties = { width: 200, border: '2px dashed gray', textAlign: 'center', }; const shortOptions = Array.from({length: 1000}, (_, index) => ({ value: String(index), content: `Value ${index}`, })); const longOptions = Array.from({length: 1000}, (_, index) => ({ value: String(index), content: `Loooooooooooooooooooong Value ${index}`, })); export default function () { return ( <> <div style={containerStyle}> <h4>Default</h4> <Box spacing={{my: 3}}> <Select placeholder="Short value" options={shortOptions} /> </Box> <Box spacing={{my: 3}}> <Select placeholder="Long value" options={longOptions} /> </Box> </div> <div style={containerStyle}> <h4>In pixels</h4> <Box spacing={{my: 3}}> <Select placeholder="Short value" popupWidth={80} options={shortOptions} /> </Box> <Box spacing={{my: 3}}> <Select placeholder="Long value" popupWidth={80} options={longOptions} /> </Box> </div> </> ); }
§Расширенное использование
Существует множество способов настроить Select более тонко.
§Рендеринг пользовательского контрола
Для создания пользовательского контрола используйте свойство renderControl.
Обратите внимание, что для правильной работы контрола необходимо передать все аргументы в узел (как при использовании стандартной конфигурации).
import {Button, Select} from '@gravity-ui/uikit'; export default function () { return ( <Select renderControl={({onClick, onKeyDown, ref}) => ( <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> ); }
§Отображение секции пользовательской фильтрации
Для отображения секции пользовательской фильтрации используйте свойство renderFilter и установите filterable в значение true.
Обратите внимание, что для правильной работы фильтра необходимо передать все аргументы в узел (как при использовании стандартной конфигурации).
import type {SelectProps} from '@gravity-ui/uikit'; import {Button, Flex, Select, TextInput} from '@gravity-ui/uikit'; const renderFilter: SelectProps['renderFilter'] = (props) => { const {value, ref, onChange, onKeyDown} = props; return ( <Flex direction="column" gap={1}> <TextInput controlRef={ref} controlProps={{size: 1}} value={value} onUpdate={onChange} onKeyDown={onKeyDown} /> <Button size="xs">Do smth</Button> </Flex> ); }; export default function () { return ( <Select placeholder="Custom filter" filterable renderFilter={renderFilter}> <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> ); }
§Отображение пользовательских опций
Для отображения пользовательских опций используйте свойство renderOption:
import type {SelectProps} from '@gravity-ui/uikit'; import {Select} from '@gravity-ui/uikit'; const renderOption: SelectProps['renderOption'] = (option) => { return <div style={{color: option.data.color}}>{option.children}</div>; }; export default function () { return ( <Select placeholder="Custom options" renderOption={renderOption}> <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> ); }
§Отображение выбранных пользовательских опций
Для отображения выбранных пользовательских опций используйте свойство renderSelectedOption:
import type {SelectProps} from '@gravity-ui/uikit'; import {Select} from '@gravity-ui/uikit'; const renderSelectedOption: SelectProps['renderSelectedOption'] = (option) => { return <div style={{color: option.data.color}}>{option.children}</div>; }; export default function () { return ( <Select placeholder="Custom selected options" renderSelectedOption={renderSelectedOption}> <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> ); }
§Отображение опций с разной высотой
Опции имеют фиксированную высоту, в соответсвии с заданным свойством size. Если нужно отобразить опции с разной высотой, используйте свойство option.data, которое будет содержать информацию о требуемой высоте опции, а также getOptionHeight для установки этого значения.
import type {SelectProps} from '@gravity-ui/uikit'; import {Select} from '@gravity-ui/uikit'; const getOptionHeight: SelectProps['getOptionHeight'] = (option) => option.data.height; export default function () { return ( <Select placeholder="Different heights" getOptionHeight={getOptionHeight}> <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> ); }
§Отображение пользовательского счетчика опций
Для отображения пользовательского счетчика опций используйте свойство renderCounter. Счетчик отображается только при включенном множественном выборе (multiple={true}) и hasCounter={true}.
import type {SelectProps} from '@gravity-ui/uikit'; import {Select} from '@gravity-ui/uikit'; const renderCounter: SelectProps['renderCounter'] = (_, {count, disabled}) => { if (count === 0) { return null; } if (count >= 2) { return ( <div style={{ padding: '0 8px', color: disabled ? '#999' : '#027bf3', fontWeight: 'bold', }} > +{count} </div> ); } return count; }; export default function () { return ( <Select multiple hasCounter renderCounter={renderCounter}> <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> ); }
§Отображение списка опций
Свойство renderPopup позволяет управлять содержимым списка опций: изменять порядок стандартных элементов (фильтр, список), скрывать их или добавлять собственные элементы между ними, до или после них.
import type {SelectProps} from '@gravity-ui/uikit'; import {Select} from '@gravity-ui/uikit'; const renderPopup: SelectProps['renderPopup'] = ({renderList, renderFilter}) => { return ( <> {renderFilter()} <div style={{width: '100%', height: 20, backgroundColor: 'tomato'}} /> {renderList()} </> ); }; export default function () { return ( <Select filterable placeholder="Custom popup" renderPopup={renderPopup}> <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 (ошибка)
Это состояние Select указывает на некорректный ввод данных пользователем. Для изменения внешнего представления Select примените свойство validationState, задав ему значение "invalid". Опционально можно задать текст сообщения об ошибке через свойство errorMessage. По умолчанию текст сообщения выводится вне компонента.
Место вывода сообщения можно изменить с помощью свойства errorPlacement.
import {Select} from '@gravity-ui/uikit'; export default function () { return ( <> <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> </> ); }
§Свойства
| Имя | Описание | Тип | Значение по умолчанию |
|---|---|---|---|
| className | Имя класса контрола. | string | |
| defaultValue | Значения по умолчанию для выбранных опций в случае использования неуправляемого состояния. | string[] | |
| disabled | Указывает на то, что пользователь не может взаимодействовать с контролом. | boolean | false |
| filterable | Указывает на то, что список опций содержит секцию фильтрации. | boolean | false |
| filterOption | Используется для сравнения опции со значением фильтра. | function | |
| filterPlaceholder | Текст-заглушка по умолчанию для поля ввода фильтра. | string | |
| getOptionHeight | Используется для задания высоты опций. | function | |
| getOptionGroupHeight | Используется для задания высоты заголовка группы опций. | function | |
| hasClear | Позволяет отображать иконку для очистки выбранных опций. | boolean | false |
| id | HTML-атрибут id. | string | |
| label | Лейбл контрола. | string | |
| loading | Добавляет элемент загрузки в конец списка опций. Работает как постоянный индикатор загрузки, пока список опций пуст. | boolean | |
| multiple | Включает множественный выбор опций. | boolean | false |
| name | Имя контрола. | string | |
| onBlur | Обработчик, который вызывается, когда элемент теряет фокус. | function | |
| filter | Контролируемое значение фильтра. | string | '' |
| onFilterChange | Срабатывает при каждом изменении фильтра. | function | |
| onFocus | Обработчик, который вызывается, когда элемент получает фокус. | function | |
| onLoadMore | Срабатывает, когда индикатор загрузки становится видимым. | function | |
| onOpenChange | Срабатывает при каждом изменении видимости списка опций. | function | |
| onUpdate | Срабатывает, когда пользователь подтверждает изменение значения Select. | function | |
| options | Конфигурация опций. | (SelectOption | SelectOptionGroup)[] | |
| pin | Вид границ контрола. | string | 'round-round' |
| placeholder | Текст-заглушка. | string | |
| popupClassName | Имя класса (className) для списка опций. | string | |
| popupPlacement | Размещение списка опций относительно контрола. | PopupPlacement Array<PopupPlacement> | ['bottom-start', 'bottom-end', 'top-start', 'top-end'] |
| popupWidth | Ширина списка опций. | number | 'fit' | 'outfit' | 'outfit' |
| qa | Атрибут идентификатора для тестирования (data-qa). | string | |
| renderControl | Используется для рендеринга пользовательского контрола. | function | |
| renderCounter | Используется для рендеринга пользовательского счетчика. Работает только с hasCounter. | function | |
| renderEmptyOptions | Используется для рендеринга узла для пустого списка опций. | function | |
| renderFilter | Используется для рендеринга секции пользовательской фильтрации. | function | |
| renderOption | Используется для рендеринга пользовательских опций. | function | |
| renderOptionGroup | Используется для рендеринга заголовков групп опций. | function | |
| renderSelectedOption | Используется для рендеринга выбранных опций. | function | |
| renderPopup | Используется для рендеринга содержимого списка опций. | function | |
| size | Размер контрола и опций. | string | 'm' |
| value | Значения для выбранных опций, которые передаются в обработчик onUpdate. | string[] | |
| view | Вид контрола. | string | 'normal' |
| virtualizationThreshold | Порог количества опций, после которого включается виртуализация. | number | 50 |
| width | Ширина контрола | string | number | undefined |
| errorMessage | Текст ошибки. | string | |
| errorPlacement | Положение отображения ошибки. | outside inside | outside |
| validationState | Состояние валидации. | "invalid" | |
| hasCounter | Показывает количество выбранных опций. Счетчик появляется только тогда, когда включен множественный выбор. | boolean |
§API CSS
| Имя | Описание |
|---|---|
--g-select-focus-outline-color | Цвет обводки при фокусе на элементе (по умолчанию отсутствует). |