Select
Adapter React independente em que Ark UI fornece as parts e Zag mantém valor, typeahead, foco e teclado.
Design
Preview funcional
Executado pelo adapter independente Ark UI com comportamento Zag.
Anatomia
.ds-select) — container com borda, radius.2 Ícone (opcional,
.ds-select__icon) — ícone à esquerda, decorativo.3 Campo (
.ds-select__field) — elemento nativo <select>.4 Seta (
.ds-select__arrow) — chevron customizado, pointer-events: none.5 Mensagem de erro (
.ds-field__error) — externa, via Form Field.6 Texto auxiliar (
.ds-field__helper) — externo, via Form Field.7 Label (
.ds-field__label) — externo, via Form Field.
Padrão
Tamanhos
| Size | Height | Font | Padding | Touch target |
|---|---|---|---|---|
Small (--sm) | 32px (component.select.height.sm) | component.select.text.font-size.sm | component.select.padding-x.sm / component.field.padding-y.sm | 32px — meets WCAG 2.5.8 min (24px) |
Medium (--md) | 40px (component.select.height.md) | component.select.text.font-size.md | component.select.padding-x.md / component.field.padding-y.md | 40px |
Large (--lg) | 48px (component.select.height.lg) | component.select.text.font-size.lg | component.select.padding-x.lg / component.field.padding-y.lg | 48px — meets AAA 44px target |
Com ícone
Estados
No Figma, State representa apenas estados visuais exclusivos: Default, Hover, Focus e Disabled. Filled, Error e Read-only são propriedades separadas; Error combina com Default/Hover/Focus, e Read-only combina com Default/Focus.
Error
Disabled
Readonly
| Figma property | Value / CSS trigger | Visual change | Token |
|---|---|---|---|
| State | Default | Neutral border | component.field.border-color.default |
| State | Hover / :hover | Darker border | component.field.border-color.hover |
| State | Focus / :focus-visible | 2px outline ring, component radius | component.field.border-color.focus, component.focus-ring.*, component.select.focus-ring.radius.default |
| State | Disabled / [disabled] | Muted bg + content, no pointer events | component.field.bg.disabled, component.field.value.color.disabled, component.field.placeholder.color.disabled |
| Error | True / .ds-select--error or .ds-field--error .ds-select | Red border and error focus ring | component.field.border-color.error, component.focus-ring.color.error |
| Error + State | True + Hover / .ds-select--error:hover | Darker red border | component.field.border-color.error-hover |
| Read-only | True / .ds-select--readonly + [disabled] | Readonly bg and content treatment; native select has no real readonly focus | component.field.bg.readonly, component.field.value.color.readonly |
Propriedades Figma
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
Show Label | Boolean | true | Exibe ou oculta o label row (incluindo asterisco de obrigatório) |
Label | Text | "Rótulo" | Texto do label (label/md) |
Required | Boolean | false | Exibe o asterisco * em feedback/error/content/default ao lado do label |
Show Helper Text | Boolean | true | Exibe ou oculta o texto auxiliar abaixo do controle |
Helper Text | Text | "Texto auxiliar" | Anotação em caption/sm (content/secondary) |
Uso
Quando usar
Boas práticas
<option value="" disabled selected>Choose a country</option>.Diretrizes de conteúdo
| Regra | Exemplo |
|---|---|
| Placeholder: "Choose a..." or "Select a..." in sentence case | "Choose a country" -- not "CHOOSE A COUNTRY" or "Country" |
| Option text should be concise and consistent | "Brazil", "United States" -- not "The Federative Republic of Brazil" |
| Don't mix option types | All countries, or all languages -- not countries mixed with regions |
| Use sentence case for options | "Credit card" -- not "Credit Card" or "CREDIT CARD" |
Always pair with a <label> | <label for="country">Country</label> |
Relacionados
Quando escolher esta saída
Adote este adapter em projetos que escolheram Ark UI e Zag como arquitetura comportamental. Não o importe dentro da saída shadcn/Base UI.
Implementação
- Status
- Beta
- Distribuição
- Adapter de source
Source do adapter
packages/react/src/ark/select.jsx
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@tis/react/ark/select'Acessibilidade
Interação por teclado
| Tecla | Ação |
|---|---|
Tab | Move o foco para o select |
Space / Enter | Abre o dropdown (nativo do navegador) |
Arrow Up / Arrow Down | Navega entre as opções |
Escape | Fecha o dropdown |
| Any letter | Pula para a primeira opção que começa com aquela letra |
Todas as interações de teclado são tratadas nativamente pelo elemento <select>. Nenhum JavaScript customizado é necessário. Selects desabilitados são removidos da ordem de tabulação automaticamente.
Accessibility
| Critério WCAG | Requisito | Status |
|---|---|---|
| 2.4.11 Focus Appearance (AA) | Focus ring 2px + 2px gap, contrast >= 3:1 against adjacent colors | ✓ |
| 2.5.8 Target Size min (AA) | Smallest size (32px) exceeds 24px minimum | ✓ |
| 2.5.5 Target Size (AAA) | Large (48px) meets 44px touch target | ✓ |
| 1.4.3 Contrast (AA) | Text and arrow contrast >= 4.5:1 against background. Disabled exempt. | ✓ |
| 4.1.2 Name, Role, Value (A) | Use native <select> element. Associate with <label> via for/id. | ✓ |
| 1.3.1 Info and Relationships (A) | Error states use aria-invalid="true" and aria-describedby. | ✓ |
| 1.4.1 Use of Color (A) | Error state has visible red border + text message, not just color. | ✓ |
.ds-select__arrow) usa pointer-events: none -- é puramente decorativa e não interfere com interação de clique ou teclado.O
<select> nativo não possui atributo readonly. O DS usa disabled combinado com a classe ds-select--readonly para diferenciação visual. Diferente de disabled, readonly deve comunicar visualmente que o valor está definido mas não é editável.
Required = true, adicione aria-required="true" no <select> — o asterisco visual (.ds-field__required) é decorativo (aria-hidden="true"). Quando Show Label = false, use aria-label no <select>. O Helper Text deve ser vinculado via aria-describedby.
Responsabilidade da saída
Preserve a semântica Ark/Zag e valide Escape, interação externa, relações ARIA e retorno de foco.
Evidência de validação
Coberta pelo Storybook da saída independente e por verificações de browser, responsividade, teclado, Axe e bundle.