Forms · Selection · Stable
Radio / Radiobutton
Три варианта компонента: Radio — базовый круг с меткой, может использоваться отдельно или в RadioGroup; Radiobutton / Ghost — Radio с подписью (caption) и иконкой-подсказкой; Radiobutton / Container — Ghost в интерактивном контейнере с hover/pressed фоном. Все варианты поддерживают SM и MD размеры.
Вариант
SM — 20px круг
MD — 24px круг
Radio
Базовый круг · может использоваться отдельно · SM · MD
Состояние
SM — 20px
MD — 24px
Примечание
Состояния
Default · Hover · Checked · Disabled · Error
Состояние
Default
Checked
Описание
Группа (RadioGroup)
Вертикальная · Горизонтальная · Ошибка
Radiobutton / Ghost
Radio + Caption + Icon Help · SM · MD
Состояние
SM — 20px
MD — 24px
Описание
Default
Нейтральная рамка, фон surface
Hover
Рамка stroke-neutral-hover, фон nba-20 (в тёмной — nba-40)
Checked
Фон neutral-fill, точка видна
Checked + Hover
Фон neutral-fill-hover
Disabled
Opacity 0.4, cursor not-allowed
Error
Рамка 2px neg-default
Error Checked
Фон neg-default, точка видна
Radiobutton / Container
Ghost в интерактивном контейнере · Hover/Pressed фон · SM · MD
Состояние
SM — 20px
MD — 24px
Описание
Default
Нет фона контейнера, прозрачный
Hover
Контейнер nba-20, кружок nba-20 (в тёмной оба nba-40)
Pressed
Контейнер nba-40 (в тёмной — nba-50), кружок как на hover
Checked
Фон neutral-fill, нет фона контейнера
Checked + Hover
Контейнер nba-20 (в тёмной — nba-40), кружок neutral-fill-hover
Disabled
Opacity 0.4, cursor not-allowed
Error
Рамка 2px neg-default
Error Checked
Фон neg-default, точка видна
Radio
valuereq
string
—
Значение кнопки. Передаётся в onChange при выборе.
labelreq
ReactNode
—
Текст метки рядом с кнопкой. Обязателен для доступности.
name
string
—
Имя группы. Одинаково для всех кнопок RadioGroup. Управляет native radio group semantics.
checked
boolean
false
Управляет выбранным состоянием. Используется совместно с onChange.
onChange
(value: string) => void
—
Вызывается при выборе кнопки. Получает строковое значение value.
description
string
—
Подсказка под меткой. Отображается вторым рядом меньшим шрифтом.
size
'sm' | 'md'
'md'
Размер. SM — 20px круг, MD — 24px круг. Оба размера: 16px шрифт.
disabled
boolean
false
Блокирует взаимодействие. Opacity 0.4, cursor not-allowed.
error
boolean
false
Состояние ошибки: рамка 2px neg-default. Обычно управляется через RadioGroup.
Radiobutton (Ghost + Container)
valuereq
string
—
Значение кнопки. Передаётся в onChange при выборе.
labelreq
string
—
Основной текст метки (16px/500).
caption
string
—
Подпись под меткой (12px/400). Опциональна.
iconHelp
boolean
false
Показывает иконку circle-help из Lucide рядом с меткой.
variant
'ghost' | 'container'
'ghost'
Ghost — без фона контейнера. Container — добавляет padding, radius и hover/pressed фон.
size
'sm' | 'md'
'md'
SM — радио 20px, отступы 8px. MD — радио 24px, отступы 10px.
checked
boolean
false
Выбранное состояние. Controlled.
error
boolean
false
Рамка 2px neg-default на радио-кружке.
disabled
boolean
false
Opacity 0.4, cursor not-allowed.
onChange
(value: string) => void
—
Вызывается при выборе.
RadioGroup
namereq
string
—
Уникальное имя группы. Все дочерние Radio получают это имя.
optionsreq
RadioOption[]
—
Массив { value, label, description?, disabled? }. Каждый элемент — одна кнопка.
label
string
—
Подпись группы. Рендерится как <legend> внутри <fieldset>.
value
string
—
Текущее выбранное значение (controlled). При совпадении с option.value — кнопка checked.
onChange
(value: string) => void
—
Вызывается при смене выбора. Получает value выбранной опции.
orientation
'vertical' | 'horizontal'
'vertical'
Направление расположения кнопок. Horizontal — до 4 коротких опций.
size
'sm' | 'md'
'md'
Размер всех кнопок в группе.
error
string
—
Текст ошибки. Переводит все кнопки в error-state и показывает сообщение снизу.
required
boolean
false
Помечает поле обязательным — добавляет aria-required на группу.
disabled
boolean
false
Блокирует всю группу. Каждая кнопка переходит в disabled-состояние.
Доступность
WCAG 2.2 AA · ARIA · Keyboard
ARIA
Разметка
- Группа рендерится как
<fieldset> + <legend> — нативная семантика радиогруппы
- Каждый элемент —
<input type="radio"> с <label> через htmlFor
- При ошибке:
aria-describedby на input → id сообщения об ошибке
- Обязательное поле:
aria-required="true" на <fieldset>
- Заблокированная опция: атрибут
disabled на <input>
Клавиатура
Навигация
Tab — вход в группу (на первую кнопку)
↑ / ← — предыдущий вариант (выбор + фокус)
↓ / → — следующий вариант (выбор + фокус)
Tab повторно — выход из группы на следующий контрол
- Фокус и выбор перемещаются одновременно (roving tabindex)
WCAG 2.2 AA
Контраст и размер
- Текст метки: ≥ 4.5:1 против фона страницы
- Touch target: MD ≥ 40px, SM ≥ 32px по вертикали
- Состояние ошибки: рамка 2px — не только цвет (WCAG 1.4.1)
- Checked-точка: text-invert на neutral-fill — контраст ≥ 7:1
- Не использовать только цвет для индикации выбора
Focus Ring
Фокус
- Outline 2px, цвет
--ds-info-800 (#5475F8)
- Offset 1px — виден на любом фоне
- Применяется к кругу контрола, не ко всей метке
- Виден при навигации с клавиатуры (
:focus-visible)
- Скрывается при клике мышью — не мешает визуально
Работа с клавиатурой
Tab · ↑ ↓ ← → · Space
Tab
Фокус на первую кнопку группы. Повторный Tab — переход к следующему контролу страницы.
↑
←
Предыдущий вариант в группе. Фокус и выбор перемещаются одновременно.
↓
→
Следующий вариант в группе. Фокус и выбор перемещаются одновременно.
Space
Выбрать вариант в фокусе (нативное поведение radio).
RadioGroup рендерится как нативный <fieldset> + <legend>. Браузер обеспечивает корректную навигацию стрелками между input[type=radio] одной группы автоматически.
Правила использования
Когда · Чего избегать
Типичные ошибки
Чего избегать
- Больше 7 опций — используйте Select (выпадающий список)
- Одиночная радиокнопка вне RadioGroup — всегда в группе
- Множественный выбор — для этого есть Checkbox
- Опциональное поле без варианта «Не указывать» / «Нет»
- Горизонтальное расположение длинных лейблов
- Radio вместо Toggle — для вкл/выкл одного параметра используйте Switch
State Explorer
Интерактивный тест состояний — переключай и смотри