Перейти к содержимому
Плотность
Тема

Ввод

Переключатели

Чекбокс, радио и свитч. Все три построены на нативном input: клавиатура, отправка формы и скринридеры достаются бесплатно.

Компонент
Разметка
<label class="inst-checkbox"><input type="checkbox" checked>Кешировать результат</label>
<label class="inst-radio"><input type="radio" name="mode" checked>Параллельно</label>
<label class="inst-radio"><input type="radio" name="mode">Последовательно</label>
<label class="inst-switch"><input type="checkbox" checked>Автозапуск</label>

Использование

Контрол лежит внутри <label>, поэтому for и id не нужны, а вся подпись становится областью нажатия.

<label class="inst-checkbox">
  <input type="checkbox" checked>
  Кешировать результат
</label>
Что Обязательно Почему
<input> внутри <label> да for и id не нужны, а областью нажатия становится вся подпись — единственный способ выполнить WCAG 2.5.8 при глифе в 15px
Общий name у радиогруппы да Без него варианты не взаимоисключающие, и клавиатурная навигация стрелками не заработает
<fieldset> с <legend> вокруг радиогруппы да Иначе скринридер прочитает варианты, но не вопрос

Своего класса у input нет: он опознаётся по типу и родителю.

Когда использовать

Возьмите другое Когда
Сегментированный контрол 2–4 варианта, и все должны быть видны разом
Селект Больше пяти взаимоисключающих вариантов
Выбираемая карточка У варианта есть описание, а не только подпись

Варианты

Выбор между тремя не вкусовой — он про то, когда применяется значение.

Пример
Разметка
<label class="inst-checkbox"><input type="checkbox" checked>Чекбокс</label>
<label class="inst-radio"><input type="radio" name="v" checked>Радио</label>
<label class="inst-switch"><input type="checkbox" checked>Свитч</label>
Когда Применяется
Чекбокс Независимый флаг. Их может быть выбрано сколько угодно, включая ноль По отправке формы
Радио Один из нескольких взаимоисключающих. Выбран всегда ровно один По отправке формы
Свитч Включение и выключение режима Немедленно, без кнопки «Применить»

Состояния

Пример
Разметка
<label class="inst-checkbox"><input type="checkbox">Обычный</label>
<label class="inst-checkbox"><input type="checkbox" checked>Выбран</label>
<label class="inst-checkbox"><input type="checkbox" disabled>Недоступен</label>
<label class="inst-checkbox"><input type="checkbox" checked disabled>Выбран и недоступен</label>

Промежуточное состояние чекбокса — свойство indeterminate, оно ставится только скриптом и не имеет атрибута в разметке:

el.indeterminate = true;   // «часть вложенных выбрана»

Правила

Так Свитч применяется сразу

Рубильник, который уже сработал. Если состояние меняется в момент нажатия — это свитч.

Не так Свитч с кнопкой «Сохранить»

Он врёт: выглядит как сработавший рубильник, а значение ещё не применено. Если применение по отправке — это чекбокс.

Так Радио в fieldset с legend

Группа получает вопрос, на который отвечают варианты.

Не так Один радио без пары

У взаимоисключающего выбора не бывает одного варианта. Одна опция — это чекбокс или свитч.

Доступность

Клавиатура Space — переключение. Для радио: стрелки перебирают группу, Tab входит и выходит. Всё нативное, кит ничего не перехватывает
Область нажатия Вся подпись, потому что контрол внутри <label>. Это единственный способ выполнить WCAG 2.5.8 при глифе в 15px
Группа радио <fieldset> с <legend> даёт группе имя. Без него скринридер прочитает варианты, но не вопрос
Свитч Нативный чекбокс. role="switch" можно добавить, если приложение хочет, чтобы состояние озвучивалось как «вкл/выкл», а не «отмечено»
Контраст Рамка невыбранного берёт --border-control и держит 3:1: у всех трёх граница и есть контрол. У свитча к дорожке добавляется кольцо по той же причине
Не только цвет Чекбокс несёт галочку, радио — точку, свитч — положение бегунка. Тон вторичен

API

ИмяЗначениеЧто делает
класс
inst-checkboxОбёртка-подпись чекбокса
inst-radioТо же для радио
inst-switchТо же для свитча
токен
--size-check15px
--size-switch-w30px
--size-switch-h18px
--size-thumb14px
--border-controllight-dark(oklch(0 0 0 / 0.46), oklch(1 0 0 / 0.38))
--accent-marklight-dark(var(--a-4), var(--a-3))
--accent-onvar(--n-0)
--tracklight-dark(oklch(0 0 0 / 0.10), oklch(1 0 0 / 0.16))
--radius-xs3px
--radius-full999px
--dur-180ms

Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument