Design System

Select

Menus Select permitem que usuários escolham uma opção de uma lista dropdown. Usa um padrão de wrapper com <select> nativo e um indicador de seta customizado.Select menus allow users to choose one option from a dropdown list. Uses a wrapper pattern with native <select> and a custom arrow indicator.

Quando usarWhen to use

Use Select quandoUse Select when
O usuário deve escolher exatamente uma opção de uma lista predefinida de 5 ou mais itens.The user must choose exactly one option from a predefined list of 5 or more items.
Não use Select quandoDon't use Select when
Menos de 5 opções — use Radio. Múltiplas seleções permitidas — use grupo de Checkbox. Usuário precisa buscar ou filtrar — use combobox (componente futuro).Fewer than 5 options — use Radio instead. Multiple selections allowed — use Checkbox group. User needs to search or filter — use combobox (future component).

AnatomiaAnatomy

language
1 2 3 4
1 Wrapper (.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.
1 Wrapper (.ds-select) — container with border, radius.
2 Icon (optional, .ds-select__icon) — leading icon, decorative.
3 Field (.ds-select__field) — native <select> element.
4 Arrow (.ds-select__arrow) — custom chevron, pointer-events: none.

PadrãoDefault

<div class="ds-select">
  <select class="ds-select__field">
    <option value="" disabled selected>Choose an option</option>
    <option value="1">Option One</option>
    <option value="2">Option Two</option>
    <option value="3">Option Three</option>
  </select>
  <span class="ds-select__arrow"></span>
</div>

TamanhosSizes

<div class="ds-select ds-select--sm">
  <select class="ds-select__field">...</select>
  <span class="ds-select__arrow"></span>
</div>

<div class="ds-select ds-select--md">
  <select class="ds-select__field">...</select>
  <span class="ds-select__arrow"></span>
</div>

<div class="ds-select ds-select--lg">
  <select class="ds-select__field">...</select>
  <span class="ds-select__arrow"></span>
</div>
SizeHeightFontPaddingTouch target
Small (--sm)32px (semantic.size.control.sm)semantic.typography.control.font-size.smsemantic.space.control.padding-x.sm32px — meets WCAG 2.5.8 min (24px)
Medium (--md)40px (semantic.size.control.md)semantic.typography.control.font-size.mdsemantic.space.control.padding-x.md40px
Large (--lg)48px (semantic.size.control.lg)semantic.typography.control.font-size.lgsemantic.space.control.padding-x.lg48px — meets AAA 44px target

Com íconeWith icon

language
<div class="ds-select">
  <span class="ds-select__icon material-symbols-outlined">language</span>
  <select class="ds-select__field">
    <option>English</option>
    <option>Portuguese</option>
    <option>Spanish</option>
  </select>
  <span class="ds-select__arrow"></span>
</div>

EstadosStates

Estados são controlados via pseudo-classes CSS (:hover, :focus-visible, [disabled]) e classes modificadoras para erro e somente leitura.States are handled via CSS pseudo-classes (:hover, :focus-visible, [disabled]) and modifier classes for error and readonly.

Error

Please select a country.
<div class="ds-field ds-field--error">
  <label class="ds-field__label" for="country">Country<span class="ds-field__required">*</span></label>
  <div class="ds-select ds-select--error">
    <select class="ds-select__field" id="country" aria-invalid="true" aria-describedby="country-error">
      <option value="" disabled selected>Select a country</option>
      <option>Brazil</option>
    </select>
    <span class="ds-select__arrow"></span>
  </div>
  <span class="ds-field__error" id="country-error">Please select a country.</span>
</div>

Disabled

<div class="ds-select">
  <select class="ds-select__field" disabled>
    <option>Disabled option</option>
  </select>
  <span class="ds-select__arrow"></span>
</div>

Readonly

<!-- Native select has no readonly; use disabled + ds-select--readonly for styling -->
<div class="ds-select ds-select--readonly">
  <select class="ds-select__field" disabled>
    <option>Read-only value</option>
  </select>
  <span class="ds-select__arrow"></span>
</div>
StateCSS triggerVisual changeToken
Default---Neutral bordersemantic.border.default
Hover:hoverDarker bordersemantic.border.control-hover
Focused:focus-visible2px outline ring, 2px offsetsemantic.focus.ring.*
Error.ds-select--errorRed bordersemantic.feedback.error.bg-default
Disabled[disabled]Muted bg + fg, no pointer eventssemantic.background.disabled
Readonly.ds-select--readonly + [disabled]No border change, full opacity textsemantic.background.disabled

Boas práticasBest practices

Faça
Inclua uma opção placeholder desabilitada: <option value="" disabled selected>Choose a country</option>.Include a disabled placeholder option: <option value="" disabled selected>Choose a country</option>.
Não faça
Pré-selecionar uma opção real a menos que seja um padrão genuíno.Pre-select a real option unless it's a genuine default.
Faça
Ordene as opções logicamente -- alfabeticamente para países, por frequência para escolhas comuns.Order options logically -- alphabetical for countries, by frequency for common choices.
Não faça
Não use select para escolhas booleanas -- use Toggle ou Checkbox.Don't use a select for boolean choices -- use Toggle or Checkbox.

Diretrizes de conteúdoContent guidelines

RegraRuleExemploExample
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 typesAll 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>

Mapeamento de tokensToken mapping

Mesmo conjunto de tokens do Input. O indicador de seta herda a cor do texto via currentColor.Same token set as Input. The arrow indicator inherits text color via currentColor.

PropriedadePropertyToken (semantic)Variável CSSCSS variable
backgroundsemantic.surface.default--ds-surface-default
border (default)semantic.border.default--ds-border-default
border (hover)semantic.border.control-hover--ds-border-control-hover
border (error)semantic.feedback.error.bg-default--ds-feedback-error-background-default
text colorsemantic.content.default--ds-content-default
placeholder colorsemantic.content.tertiary--ds-content-tertiary
arrow colorInherits via currentColor---
background (disabled)semantic.background.disabled--ds-background-disabled
text (disabled)semantic.content.disabled--ds-content-disabled
border-radiussemantic.radius.component--ds-radius-md
focus ringsemantic.focus.ring.*--ds-focus-ring-width, --ds-focus-ring-offset, --ds-focus-ring-color
height (sm)semantic.size.control.sm--ds-size-lg (32px)
height (md)semantic.size.control.md--ds-size-xl (40px)
height (lg)semantic.size.control.lg--ds-size-2xl (48px)
padding-x (sm)semantic.space.control.padding-x.sm--ds-space-md
padding-x (md)semantic.space.control.padding-x.md--ds-space-lg
padding-x (lg)semantic.space.control.padding-x.lg--ds-space-xl
font-size (sm)semantic.typography.control.font-size.sm--ds-control-font-size-sm
font-size (md)semantic.typography.control.font-size.md--ds-control-font-size-md
font-size (lg)semantic.typography.control.font-size.lg--ds-control-font-size-lg

Classes CSSCSS classes

ClasseClassDescriçãoDescription
ds-selectElemento wrapper do selectWrapper element for the select
ds-select__fieldO elemento nativo <select>The native <select> element
ds-select__arrowIndicador de seta dropdown customizadoCustom dropdown arrow indicator
ds-select__iconÍcone à esquerda dentro do wrapperLeading icon inside the wrapper
ds-select--smTamanho pequeno (altura 32px)Small size (32px height)
ds-select--mdTamanho médio (altura 40px, padrão)Medium size (40px height, default)
ds-select--lgTamanho grande (altura 48px)Large size (48px height)
ds-select--errorEstado de erro com borda vermelhaError state with red border
ds-select--disabledEstado desabilitado (ou use o nativo disabled)Disabled state (or use native disabled)
ds-select--readonlyEstado visual somente leitura (combine com o nativo disabled)Readonly visual state (combine with native disabled)
ds-field__label-rowLinha horizontal com label e asterisco de obrigatórioHorizontal row with label and required asterisk
ds-field__requiredAsterisco * em feedback/error/default (decorativo, aria-hidden)Asterisk * in feedback/error/default (decorative, aria-hidden)
ds-field--no-labelOculta o label row quando Show Label = falseHides the label row when Show Label = false
ds-field--no-helperOculta o helper text quando Show Helper Text = falseHides helper text when Show Helper Text = false

Propriedades FigmaFigma properties

PropriedadePropertyTipoTypePadrãoDefaultDescriçãoDescription
Show LabelBooleantrueExibe ou oculta o label row (incluindo asterisco de obrigatório)Shows or hides the label row (including required asterisk)
LabelText"Rótulo"Texto do label (label/md)Label text (label/md)
RequiredBooleanfalseExibe o asterisco * em feedback/error/default ao lado do labelShows * in feedback/error/default next to the label
Show Helper TextBooleantrueExibe ou oculta o texto auxiliar abaixo do controleShows or hides the helper text below the control
Helper TextText"Texto auxiliar"Anotação em caption/sm (content/secondary)Caption/sm annotation (content/secondary)

Interação por tecladoKeyboard interaction

TeclaKeyAçãoAction
TabMove o foco para o selectMoves focus to the select
Space / EnterAbre o dropdown (nativo do navegador)Opens the dropdown (browser-native)
Arrow Up / Arrow DownNavega entre as opçõesNavigates options
EscapeFecha o dropdownCloses dropdown
Any letterPula para a primeira opção que começa com aquela letraJumps to first option starting with that letter

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.All keyboard interactions are handled natively by the <select> element. No custom JavaScript is required. Disabled selects are removed from tab order automatically.

AccessibilityAccessibility

Critério WCAGWCAG criterionRequisitoRequirementStatus
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 (34px) exceeds 24px minimum
2.5.5 Target Size (AAA)Medium (47px) and Large (58px) meet 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.
Notas de implementaçãoImplementation notes
A seta customizada (.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.
The custom arrow (.ds-select__arrow) uses pointer-events: none -- it is purely decorative and does not interfere with click or keyboard interaction.

Native <select> has no readonly attribute. The DS uses disabled combined with the ds-select--readonly class for visual differentiation. Unlike disabled, readonly should visually communicate that the value is set but not editable.
Required e label invisívelRequired and invisible label
Quando 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.When Required = true, add aria-required="true" to the <select> — the visual asterisk (.ds-field__required) is decorative (aria-hidden="true"). When Show Label = false, use aria-label on the <select>. Helper Text should be linked via aria-describedby.

RelacionadosRelated