Select
Select позволяет выбрать один пункт из короткого закрытого списка. Он показывает выбранное значение и отправляет его вместе с формой.
<tk-field label="Department" helper="Shown on your profile">
<tk-select name="department" placeholder="Select a department">
<option>Design</option>
<option>Engineering</option>
<option>Finance</option>
</tk-select>
</tk-field>Поместите select в aria-label. Внутри Field ставьте required и
disabled на Field.
Анатомия
| Часть | Что это |
|---|---|
tk-select |
сам элемент; одна остановка Tab |
| поле | показывает выбранное значение или приглашение и шеврон; занимает ширину контейнера |
| шеврон | переворачивается, пока меню открыто; скрыт в режиме только для чтения |
| меню | список пунктов; ширина как у поля; открывается под полем, а у нижнего края экрана над ним |
| пункт | одна строка; выбранный отмечает галочка |
| заголовок группы | необязательный заголовок над несколькими пунктами; его нельзя выбрать |
В меню видно примерно пять с половиной строк, дальше оно прокручивается; обрезанная строка показывает, что ниже есть ещё. На сенсорных экранах открывается то же меню, системного списка нет.
Варианты
<tk-select variant="filter" filter-label="Status"> <option>Open</option> <option>Closed</option> </tk-select> <tk-select variant="filter" filter-label="Owner"> <option selected>Me</option> <option>Anyone</option> </tk-select>
field(по умолчанию): поле формы на всю ширину контейнера. Назовите его через Field илиaria-label.filter: компактная кнопка для панели фильтров. Пока ничего не выбрано, на ней написано «Status», потом «Status: Open», и кнопка получает тонированную заливку.filter-labelобязателен: это и видимый текст, и доступное имя. Фильтр не кладут в Field.
Размеры
<tk-select aria-label="Sort by"> <option selected>Newest first</option> <option>Oldest first</option> </tk-select> <tk-select size="large" aria-label="Show"> <option selected>All projects</option> <option>Starred projects</option> </tk-select>
size |
Высота | Отступ по бокам | Текст значения | Строка пункта |
|---|---|---|---|---|
medium (по умолчанию) |
32px | space-8 |
Body Small (14/20) | 32px |
large |
36px | space-10 |
Body Medium (16/24) | 36px |
Текст пунктов в обоих размерах Label Medium (14/20). Строка с описанием выше. Высоты совпадают с Input и Button, поэтому форма выстраивается в ряд. Длинные значения и пункты обрезаются многоточием и не переносятся.
Состояния
<tk-select aria-label="Region" disabled> <option selected>Europe</option> </tk-select> <tk-select aria-label="Currency" readonly> <option selected>Euro</option> </tk-select>
При наведении поле не меняется. При фокусе с клавиатуры его рамка меняет цвет и
становится толще; отдельной рамки фокуса снаружи нет. Вариант filter при наведении
тонируется и при фокусе показывает рамку фокуса.
disabled: на поле нельзя перейти, меню не открывается, значение не отправляется. Лучше оставить поле активным или сделать егоreadonlyи объяснить причину в подсказке.readonly: значение видно и отправляется. На поле можно перейти, но меню не открывается и шеврон скрыт.- Ошибка: задайте
errorна Field. Сообщение появится ниже, а рамка станет красной, даже в фокусе.
<tk-field label="Plan" required error="Select a plan to continue">
<tk-select placeholder="Select a plan">
<option>Free</option>
<option>Pro</option>
</tk-select>
</tk-field>Пункты списка
<tk-select aria-label="Plan" placeholder="Select a plan"> <option value="free" data-description="For trying things out">Free</option> <option value="pro" data-description="Adds version history">Pro</option> <option value="team" disabled>Team (coming soon)</option> </tk-select>
- Пункты пишутся дочерними
<option>. Еслиvalueне задан, значением становится текст пункта. - Начальное значение задаёт
selectedна пункте илиvalueна select. Без них поле показывает приглашение; первый пункт сам не выбирается. disabledоставляет пункт видимым, но пропускает его. Напишите в тексте, почему он недоступен.data-descriptionдобавляет короткую вторую строку. Пишите туда то, что помогает выбрать, например цену или лимит. Не описывайте каждый пункт. Скринридер читает описание после названия пункта.
<tk-select aria-label="Office" placeholder="Select an office">
<option>Remote</option>
<optgroup label="Europe">
<option>Berlin</option>
<option>Lisbon</option>
</optgroup>
</tk-select><optgroup label="…"> объединяет пункты под заголовком. Клавиатура пропускает
заголовки. Другие дочерние элементы игнорируются.
Когда использовать
- Select подходит для списка примерно от 4 пунктов до одного экрана, когда места мало.
- Для 2–3 пунктов берите
Radio group , а также когда пункты нужно сравнивать рядом. Сначала попробуйте задать вопрос так, чтобы пунктов было меньше. - Для длинного списка, например стран или валют, берите
Combobox . - Если можно выбрать несколько, нужен
Multiselect . - Если пункты выполняют действия, а не задают значение, нужно
Menu .
Текст
- Подпись: назовите, о чём спрашиваете, с заглавной буквы только в начале и без
двоеточия. Она задаётся на Field или в
filter-label. - Приглашение: «Выберите…», с заглавной буквы только в начале, без точки в конце. Нужно, только если нет разумного значения по умолчанию. После выбора оно исчезает, поэтому не пишите в нём ничего важного.
- Пункты: одна короткая строка, заглавная буква только в начале, без запятых и точек с запятой. Упорядочивайте по алфавиту или так, чтобы порядок можно было угадать.
- Не начинайте пункты с иконки или эмодзи. Набрав «S», человек должен попасть на «Sweden».
- Заголовки групп: одно-два слова.
- Значение заранее: не выбирайте заранее ответ на вопрос. Для настройки выберите текущее или самое вероятное значение.
- Ошибка: скажите, как исправить, словами из подписи: «Выберите регион проживания».
Подробнее в
Можно / нельзя
| ✅ Можно | ❌ Нельзя |
|---|---|
| Radio group для 2–3 пунктов | Select для «Да» и «Нет» |
| Combobox для стран и других длинных списков | Select, который прокручивают через десятки пунктов |
| Подпись через Field | Приглашение вместо подписи |
| Вопрос без ответа, пока человек не ответит | Заранее выбранный ответ на вопрос |
| Порядок, в котором пункт легко найти | Пункты, которые начинаются с иконки или эмодзи |
| Menu для действий | Действия внутри select |
Связанные
Field : подпись, подсказка и ошибка вокруг select.Radio group : 2–3 пункта, все на виду.Combobox : один пункт из длинного списка, с поиском по мере ввода.Multiselect : несколько пунктов; у него тот же вариантfilter.Country select : combobox со встроенным списком стран.Menu : пункты, которые выполняют действия.Select family : как эти четыре компонента соотносятся.
API
Атрибуты
| Атрибут | Тип | По умолчанию | Что делает |
|---|---|---|---|
placeholder |
string | — | приглашение, пока ничего не выбрано |
value |
string | '' |
значение выбранного пункта; '' значит, ничего не выбрано |
name |
string | — | имя поля в форме |
required |
boolean | false |
пустое значение не даёт отправить форму; видимой отметки нет (звёздочку добавляет Field) |
disabled |
boolean | false |
не в фокусе, не открывается, не попадает в форму |
readonly |
boolean | false |
в фокусе и отправляется, но не открывается и не меняется |
autocomplete |
string | — | подсказка для автозаполнения, например country; браузеры поддерживают её в нестандартных полях по-разному |
size |
medium | large |
medium |
высота 32 / 36px |
variant |
field | filter |
field |
поле формы или кнопка панели фильтров |
filter-label |
string | — | обязателен с variant="filter": текст кнопки и её доступное имя |
Слоты
| Слот | Содержимое |
|---|---|
| по умолчанию | элементы <option> и <optgroup>; изменения в них подхватываются |
<option> принимает value, selected, disabled и data-description. <optgroup>
принимает label.
События
change срабатывает, когда человек выбирает другой пункт. Оно не срабатывает, пока он
перемещается по меню, и когда вы задаёте value в коде. Новое значение читайте из
value.
В форме значение отправляется под именем name, а сброс формы возвращает начальное
значение.
CSS
::part(trigger): поле.::part(listbox): меню.
Токены
| Часть | Токены |
|---|---|
| поле | surface/default + border/subtle, radius-8 |
| поле в фокусе | border/accent/focus, утолщается внутрь на focus/border-inset |
| поле с ошибкой | border/error |
| поле только для чтения | surface/subtle + border/subtle |
| отключённое поле | surface/disabled + border/disabled + text/disabled |
| значение / приглашение | text/default / text/placeholder |
| шеврон | icon/secondary (отключённый icon/disabled), icon-size-16 |
| меню | surface/raised + shadow-2, radius-16, отступ space-4 |
| пункт | text/default, radius-12; подсвеченный state/hover |
| выбранный пункт | галочка, icon/accent |
| описание / заголовок группы | text/secondary |
| отключённый пункт | text/disabled |
| фильтр с выбором | state/on + border/selected (под курсором state/on-hover) |
В контрастной теме у меню ещё и рамка 1px border/default. Значения по темам:
Доступность
Встроено:
- Скринридер слышит combobox, как у нативного select: имя, значение, открыт ли список, подсвеченный пункт и какие пункты отключены.
- Пока меню открыто, фокус остаётся на поле. Esc, Tab, клик снаружи и выбор закрывают меню.
- Перемещение по меню не меняет значение. Меняет только выбор.
- Нажатие буквы переходит к подходящему пункту и никогда не вводит текст.
- Меню остаётся на экране при увеличении. Каждая строка не ниже 32px.
- При уменьшенной анимации шеврон переворачивается без анимации.
На вашей стороне:
- Назовите каждый select: подписью Field,
aria-labelилиfilter-label. - Задайте
autocompleteдля личных данных, например страны или месяца рождения. - Пишите ошибки по правилам из раздела «Текст».
| Клавиша | Меню закрыто | Меню открыто |
|---|---|---|
Enter / Space |
открывает меню | выбирает подсвеченный пункт и закрывает |
Down / Up |
открывает меню | двигает подсветку, пропуская отключённые пункты; на краях останавливается |
Home / End |
— | подсвечивает первый / последний пункт |
| буква | открывает и переходит к совпадению | переходит к следующему совпадению |
Alt + Up |
— | выбирает подсвеченный пункт и закрывает |
Esc |
— | закрывает, не меняя значение; диалог вокруг остаётся открытым |
Tab |
переводит к следующему элементу | выбирает подсвеченный пункт и переходит дальше |
Пределы контраста
- Рамка поля: 1.33:1 в светлой теме и 2.00:1 в тёмной, ниже минимума 3:1; в контрастной 4.22:1. В светлой теме край поля едва видно, поэтому подпись нужна всегда.
- Текст приглашения: 3.26:1 в светлой теме, 4.09:1 в тёмной и 4.22:1 в контрастной, ниже минимума 4.5:1 для текста. Не пишите в нём ничего важного.