Radio
Permite selecionar exatamente uma opção entre alternativas visíveis e relacionadas.
Design
Preview funcional
Executado com HTML e CSS estáveis do DS, sem runtime JavaScript do componente.
Carregando preview funcional…
Anatomia
1 Label (
2 Input (
3 Dot — pseudo-elemento CSS, visível quando selecionado.
4 Grupo (
5 Legend (
.ds-radio-label) — envolve radio + texto, estende área de clique.2 Input (
.ds-radio) — <input type="radio"> nativo estilizado.3 Dot — pseudo-elemento CSS, visível quando selecionado.
4 Grupo (
.ds-radio-group) — <fieldset> envolvendo radios relacionados.5 Legend (
.ds-radio-group__legend) — título do grupo, fornece contexto para leitores de tela.
Grupo de Radio
Tamanhos
Grupo com erro
Desabilitado
Estados
| State | CSS trigger | Visual change | Token |
|---|---|---|---|
| Unselected | --- | Neutral control fill and border | component.radio.control.fill.unselected.default, component.radio.control.border-color.unselected.default |
| Unselected hover | :hover | Darker neutral control border/fill | component.radio.control.fill.unselected.hover, component.radio.control.border-color.unselected.hover |
| Selected | :checked | Primary control fill with dot | component.radio.control.fill.selected.default, component.radio.dot.fill.selected.default |
| Selected hover | :checked:hover | Darker primary control fill | component.radio.control.fill.selected.hover, component.radio.dot.fill.selected.hover |
| Focus | :focus-visible | 2px outline ring | component.radio.focus-ring.radius.default + component.focus-ring.* |
| Error group | .ds-radio-group--error | Error border on controls and message below group | component.radio.control.border-color.unselected.error, semantic.feedback.error.content-default |
| Disabled | [disabled] | Muted control, dot and label | component.radio.control.fill.*.disabled, semantic.content.disabled |
Propriedades Figma
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
Show Label | Boolean | true | Exibe ou oculta o label do controle |
Label | Text | "Rótulo" | Texto do label (label/md) |
Show Description | Boolean | false | Exibe texto descritivo abaixo do label |
Description | Text | "Texto descritivo" | Texto multiline de descrição (body/sm) |
Show Helper Text | Boolean | false | Exibe texto auxiliar abaixo da description |
Helper Text | Text | "Texto auxiliar" | Anotação em caption/sm (content/secondary) |
Uso
Quando usar
- Exatamente uma opção deve ser escolhida entre duas a sete alternativas visíveis.
- Comparar as alternativas antes de escolher ajuda a tomar a decisão.
Quando não usar
- Zero, uma ou várias opções podem ser escolhidas; use Checkbox.
- Há muitas alternativas ou pouco espaço; use Select.
Implementação
- Status
- Estável
- Distribuição
- Pacote npm
Instalação
npm install ds-tispnpm add ds-tisyarn add ds-tisbun add ds-tisImportações
import 'ds-tis/css'Markup
<fieldset class="ds-radio-group">
<legend class="ds-radio-group__legend">Preferência de contato</legend>
<label class="ds-radio-label">
<input class="ds-radio" type="radio" name="contact" value="email" checked />
<span class="ds-radio__content">
<span class="ds-radio__label">E-mail</span>
</span>
</label>
</fieldset>Contrato da implementação Web
Mapeamento de tokens
Mesmos tokens do Checkbox exceto border-radius: 50% (círculo) em vez de foundation.radius.4.
| Propriedade | Token Component | Variável CSS |
|---|---|---|
| control size (sm/md/lg) | component.radio.control.size.* | --ds-radio-control-size-* |
| control fill | component.radio.control.fill.*.* | --ds-radio-control-fill-* |
| control border | component.radio.control.border-color.*.* | --ds-radio-control-border-color-* |
| dot size/fill | component.radio.dot.{size,fill}.* | --ds-radio-dot-* |
| target height | component.radio.target.height.* | --ds-radio-target-height-* |
| focus ring | component.radio.focus-ring.radius.default + component.focus-ring.* | --ds-focus-ring-* + --ds-radio-focus-ring-radius-default |
| label/helper/description/error | component.form-field.* | --ds-form-field-* |
Classes CSS
| Classe | Descrição |
|---|---|
ds-radio | Radio button nativo estilizado |
ds-radio-label | Wrapper do label (envolve radio + texto) |
ds-radio-group | Container fieldset para um grupo de radios |
ds-radio-group__legend | Legend/título do grupo |
ds-radio--sm | Tamanho pequeno (16px) |
ds-radio--lg | Tamanho grande (24px) |
ds-radio-group--error | Estado de erro para o grupo |
ds-radio-group__error | Texto de mensagem de erro do grupo |
ds-radio__content | Frame vertical com label, description e helper text |
ds-radio__label | Texto do label dentro do content frame (label/md) |
ds-radio__description | Texto descritivo multiline (body/sm, content/default) |
ds-radio__helper | Texto auxiliar (caption/sm, content/secondary) |
Acessibilidade
Interação por teclado
| Tecla | Ação |
|---|---|
Tab | Move o foco para dentro do grupo de radio (tab stop único) ou para fora |
Arrow Up / Arrow Left | Seleciona a opção anterior no grupo |
Arrow Down / Arrow Right | Seleciona a próxima opção no grupo |
Um grupo de radio se comporta como um tab stop único. Teclas de seta navegam entre opções dentro do grupo, e a seleção se move com o foco.
Accessibility
| Critério WCAG | Requisito | Status |
|---|---|---|
| 1.3.1 Info and Relationships (A) | Grupo em <fieldset> + <legend> | ✓ |
| 2.4.11 Focus Appearance (AA) | Focus ring visível via :focus-visible | ✓ |
| 2.5.8 Target Size min (AA) | Label estende a área de clique além do radio | ✓ |
| 4.1.2 Name, Role, Value (A) | <input type="radio"> nativo fornece role + estado automaticamente | ✓ |
| 3.3.1 Error Identification (A) | Erro do grupo comunicado via ds-radio-group--error | ✓ |
Notas de implementação
Sempre envolva grupos de radio em um <fieldset> com um <legend> para fornecer contexto de grupo aos leitores de tela. Usa <input type="radio"> nativo para navegação por teclado integrada -- teclas de seta movem entre opções dentro de um grupo, Tab entra e sai do grupo. Focus ring é visível no foco por teclado via :focus-visible.
Label invisível — exige ARIA explícito
Quando Show Label = false e Show Description = true, vincule o <input> à descrição via aria-labelledby="id-da-description". Se nenhum dos dois estiver visível, use aria-label diretamente no <input>. O Helper Text deve sempre ser vinculado via aria-describedby="id-do-helper".
Responsabilidade da saída
Preserve a semântica do elemento nativo, nomes acessíveis, comportamento de teclado e foco visível.
Evidência de validação
Coberta pelo Storybook estável, testes do runtime público quando aplicável, cenários de teclado, responsividade e Axe.