CustomSelect
Компонент для выбора значения из выпадающего списка. Поддерживает широкие возможности по изменению внешнего вида, поиск по опциям и пользовательский рендеринг опций.
Связанные компоненты:
Режим работы
Компонент поддерживает работу как в неконтролируемом режиме, так и контролируемом. Это стандартное поведение React-компонентов, прочитать про это можно в документации React ↗.
Для использования неконтролируемого режима достаточно просто не передавать value или передавать defaultValue, если
требуется задать значение по умолчанию.
Для контролируемого режима используйте связку свойств value/onChange для задания значения и его изменения.
const colors = [
{
value: 'red',
label: 'Красный',
},
{
value: 'green',
label: 'Зелёный',
},
{
value: 'blue',
label: 'Синий',
},
];
// Неконтролируемое состояние
<CustomSelect options={colors} defaultValue="red" />;
// Контролируемое состояние
const [color, setColor] = React.useState('red');
<CustomSelect options={colors} value={color} onChange={(_, newColor) => setColor(newColor)} />;Состояния
disabled
Свойство disabled блокирует взаимодействие с компонентом и добавляет визуальную индикацию недоступности.
Валидация
Свойство status используется для визуализации валидации компонента - некорректности заполненного поля (значение "error")
или успешной валидации (значение "valid").
Кастомизация
Визуальное оформление
С помощью свойства renderOption можно влиять на отображение конкретного элемента выпадающего списка.
Вы можете изменить стандартный компонент CustomSelectOption или использовать свой компонент.
Кастомное поведение при поиске
Пример показывает, как реализовать кастомное поведение поиска: при вводе сохраняется локальный query, при отсутствии совпадений в списке появляется опция «Добавить пользователя …»,
её выбор добавляет новый элемент в options — вместе с пользовательским рендером опций это даёт удобный UX для создания элементов на лету.
Кастомный алгоритм поиска
Демонстрация кастомного алгоритма поиска иллюстрирует передачу filterFn для гибкого соответствия (по label и description),
поддержку searchable и кастомного рендера опций — полезно, когда нужно искать по нескольким полям или использовать нестандартные критерии.
Асинхронная загрузка списка
Асинхронный пример показывает подгрузку опций с задержкой/дебаунсом, управление состояниями fetching/remoteQuery,
минимальную длину запроса, очистку таймаутов и возможность заменить содержимое выпадающего списка (например, подсказкой «введите хотя бы три символа») — стандартный шаблон для работы с удалёнными API.
CustomSelectOption
Универсальный компонент для отрисовки одного из значений в выпадающем списке.
Передавайте данный компонент в свойство renderOption, для кастомизации значений выпадающего списка.
Помимо CustomSelect используется и в ChipsSelect.
Для реализации многоуровневых CustomSelectOption используйте свойство hierarchy,
которое позволяет создать нужный отступ в зависимости от уровня вложенности.
Тестирование (e2e)
Для поиска компонента и его элементов на странице cуществует ряд вспомогательных свойств:
По умолчанию все data-* атрибуты попадают на <input> компонента, это значит, что при передаче
data-testid или data-test-id идентификатор попадёт <input>.
Доступ к полю ввода может быть полезен для:
- получения текста, введённого пользователем при поиске опций, в режиме
searchable; - получения информации о наличии фокуса на компоненте;
- симуляции работы с компонентом с клавиатуры.
Используйте labelTextTestId:
- для симуляции работы с компонентом с помощью мыши, тач-устройства;
- для получения текста выбранной в данный момент опции.
Для взаимодействия с кнопкой очистки состояния компонента, которая появляется,
если CustomSelect имеет свойство searchable и пользователь выбрал опцию, используйте свойство clearButtonTestId.
CustomSelect внутри себя хранит невидимый <select>, для того, чтобы CustomSelect можно было использовать внутри формы.
Для получения доступа к <select> используйте свойство nativeSelectTestId. Полезно для доступа к значению value,
выбранной в данный момент опции.
Все перечисленные выше свойства устанавливают аттрибут data-testid у соответствующих элементов. Учитывайте это при построении селекторов.
Доступность (a11y)
Следуйте рекомендациям доступности компонента Select.
Индикация ассинхронной загрузки
Для того, чтобы уведомить пользователей скринридеров о том, что идет загрузка списка опций использутся специальные текстовые метки совместно со свойством fetching.
Текст этих меток можно переопределить с помощью свойств fetchingInProgressLabel и fetchingCompletedLabel. По умолчанию они соответственно: "Список опций загружается..." и "Опций загружено: ${options.length}"
Проблема определения выбранной опции
В текущей реализации (v7) компонент CustomSelect имеет проблему с доступностью в некоторых скринридерах (например, NVDA): пользователь не может узнать, какой вариант выбран.
Это происходит из-за сброса значения в input при потере фокуса.
Такое поведение было добавлено для ускорения ввода новых значений, но оно негативно влияет на доступность.
Решение
Мы изменили логику работы компонента. Чтобы включить исправленное поведение, используйте флаг accessible. Он введён для сохранения обратной совместимости в минорных обновлениях.
Рекомендация
Настоятельно рекомендуем включить этот флаг, так как в v8 он будет включён по умолчанию (accessible: true).
Свойства и методы
CustomSelect
| Свойство | Описание |
|---|---|
accessible | booleanВключает режим в котором выбранное значение По умолчанию: - |
after | ReactNodeДобавляет иконку справа. Рекомендации:
По умолчанию: - |
afterAlign | FieldIconsAlignВертикальное выравнивание иконки справа. По умолчанию: - |
align | AlignTypeПо умолчанию: - |
allowClearButton | booleanЕсли По умолчанию: - |
before | ReactNodeДобавляет иконку слева. Рекомендации:
По умолчанию: - |
beforeAlign | FieldIconsAlignВертикальное выравнивание иконки слева. По умолчанию: - |
ClearButton | ComponentType<CustomSelectClearButtonProps>Кастомная кнопка для очистки значения.
Должна принимать обязательное свойство По умолчанию: - |
clearButtonTestId | stringПередает атрибут По умолчанию: - |
defaultValue | SelectValueСм. По умолчанию: - |
dropdownAutoWidth | booleanШирина раскрывающегося списка зависит от контента. По умолчанию: - |
dropdownOffsetDistance | numberОтступ от выпадающего списка. По умолчанию: - |
emptyText | stringТекст, который будет отображен, если приходит пустой По умолчанию: - |
fetching | booleanЕсли По умолчанию: false |
fetchingCompletedLabel | string | ((optionsCount: number) => string)Текстовая метка для индикации завершения процесса загрузки данных для пользователей скринридерами. По умолчанию: По умолчанию: `Загружено опций: ${options.length}` |
fetchingInProgressLabel | stringТекстовая метка для индикации процесса загрузки данных для пользователей скринридерами. По умолчанию: По умолчанию: Список опций загружается... |
filterFn | false | FilterFn<OptionInterfaceT>Функция для кастомной фильтрации. По умолчанию поиск производится по По умолчанию: - |
forceDropdownPortal | booleanИспользовать Portal для рендеринга выпадающего списка. По умолчанию: - |
getRef | Ref<HTMLSelectElement>Deprecated: Since 7.9.0. Вместо этого используйте По умолчанию: - |
getRootRef | Ref<HTMLDivElement>По умолчанию: - |
getSelectInputRef | Ref<HTMLInputElement>Deprecated: Since 7.9.0. Вместо этого используйте Ref на внутрений компонент input. По умолчанию: - |
icon | ReactNodeИконка раскрывающегося списка. По умолчанию: - |
labelTextTestId | stringПередает атрибут По умолчанию: - |
mode | "default" | "plain"Режим отображения.
По умолчанию: - |
multiline | booleanФлаг для включения многострочного режима. По умолчанию: - |
nativeSelectTestId | stringDeprecated: Since 7.9.0. Вместо этого используйте Передает атрибут По умолчанию: - |
noMaxHeight | booleanОтключает максимальную высоту по умолчанию. По умолчанию: - |
onChange | ((e: ChangeEvent<HTMLSelectElement>, newValue: SelectValue) => void)Обработчик, срабатывающий при изменении выбранного значения. Вторым параметром прокидывается новое значение. По умолчанию: - |
onClose | VoidFunctionОбработчик закрытия выпадающего списка. По умолчанию: - |
onInputChange | ((e: ChangeEvent<HTMLInputElement>) => void)Событие изменения текстового поля. По умолчанию: - |
onInputKeyDown | ((e: KeyboardEvent<Element>, isOpen: boolean) => void)Обработчик события По умолчанию: - |
onOpen | VoidFunctionОбработчик открытия выпадающего списка. По умолчанию: - |
options | OptionInterfaceT[]Список опций в списке. По умолчанию: - |
overscrollBehavior | "auto" | "none" | "contain"Поведение overscroll, подробнее можно почитать в документации ↗. По умолчанию: - |
placeholder | stringТекст-подсказка при отсутствии выбранного значения. По умолчанию: - |
popupDirection | PopupDirectionНаправление раскрытия выпадающего списка. По умолчанию: - |
renderDropdown | (({ defaultDropdownContent, }: { defaultDropdownContent: ReactNode; }) => ReactNode)Рендер-проп для кастомного рендера содержимого дропдауна.
В По умолчанию: - |
renderOption | ((props: CustomSelectRenderOption<OptionInterfaceT>) => ReactNode)Рендер-проп для кастомного рендера опции. В объекте аргумента приходят свойства опции ↗. По умолчанию: - |
searchable | booleanЕсли По умолчанию: - |
selectType | SelectTypeТип отображения компонента. По умолчанию: - |
slotProps | ({ root?: (Omit<HTMLAttributes<HTMLDivElement>, "children"> & HasDataAttribute & HasRootRef<HTMLDivElement>); select?: (NativeHTMLSelectProps & ... 1 more ... & HasDataAttribute) | undefined; } & { ...; }) | undefinedСвойства, которые можно прокинуть внутрь компонента:
По умолчанию: - |
status | "default" | "error" | "valid"Статус отображения поля в форме. По умолчанию: - |
value | SelectValueВыбранное значение. По умолчанию: - |
CustomSelectOption
| Свойство | Описание |
|---|---|
after | ReactNodeВставляет элемент в конец блока после основного контента.
Например, можно передать компонент По умолчанию: - |
before | ReactNodeВставляет элемент в начало блока перед основным контентом.
Например, можно передать компонент По умолчанию: - |
description | ReactNodeДобавляет описание под основным блоком. По умолчанию: - |
disabled | booleanБлокирует весь блок. По умолчанию: - |
focused | booleanВключает состояние фокуса. По умолчанию: - |
getRootRef | Ref<HTMLDivElement>По умолчанию: - |
hierarchy | numberПозволяет создавать вложенность. По умолчанию: 0 |
hovered | booleanВключает состояние наведения. По умолчанию: - |
selected | booleanВключает состояние выбранного элемента списка. По умолчанию: - |