Button
Buttons disparam ações. A API cobre estilos de ênfase, tamanhos, suporte a ícones, estado de carregamento e layout full-width.Buttons trigger actions. The API covers emphasis styles, sizes, icon support, loading state, and full-width layout.
Quando usarWhen to use
<a>). Não use buttons para ações inline de texto ou quando o peso visual competiria com a ação principal da página.The action is navigation to another page or URL — use a link (<a>) instead. Don't use buttons for inline text actions or when the visual weight would compete with the page's primary action.
| EstiloStyle | Usar paraUse for | ÊnfaseEmphasis |
|---|---|---|
| Brand | Ação principal da página. Um por seção, idealmente um por página.Primary action on the page. One per section, ideally one per page. | MáximaHighest |
| Toned | Ações secundárias que precisam de visibilidade mas não devem competir com Brand.Secondary actions that need visibility but shouldn't compete with Brand. | MédiaMedium |
| Outline | Ações secundárias ou terciárias. Combina bem ao lado de um button Brand.Secondary or tertiary actions. Pairs well next to a Brand button. | MédiaMedium |
| Ghost | Ações terciárias, ações de toolbar ou buttons de fechar/dispensar.Tertiary actions, toolbar actions, or close/dismiss buttons. | BaixaLow |
| Success | Confirmar um resultado positivo: aprovar, concluir, publicar.Confirming a positive outcome: approve, complete, publish. | ContextualContextual |
| Danger | Ações destrutivas: excluir, remover, revogar. Sempre requer confirmação.Destructive actions: delete, remove, revoke. Always requires confirmation. | ContextualContextual |
AnatomiaAnatomy
2 Icon (opcional) — frame/ícone 20px no sm e 24px no md/lg.
3 Label (
.ds-button__label) — tipografia e cor via Component tokens.4 Padding raiz — sm 8×8px, md 10×12px, lg 12×16px.
5 Padding do label — 4px adicionais no Label Frame para equilíbrio óptico.1 Container — background, radius, height, and min-width via Component tokens.
2 Icon (optional) — 20px frame/icon on sm and 24px on md/lg.
3 Label (
.ds-button__label) — typography and color via Component tokens.4 Root padding — sm 8×8px, md 10×12px, lg 12×16px.
5 Label padding — additional 4px on the Label Frame for optical balance.
EstilosStyles
TamanhosSizes
| Size | AlturaHeight | FonteFont | Padding | Touch target |
|---|---|---|---|---|
Small (--sm) | 32px (component.button.height.sm) | component.button.label.font-size.sm | 8×8px (component.button.padding-y.sm × padding-x.sm) | 32px — meets WCAG 2.5.8 min (24px) |
Medium (--md) | 40px (component.button.height.md) | component.button.label.font-size.md | 10×12px (component.button.padding-y.md × padding-x.md) | 40px |
Large (--lg) | 48px (component.button.height.lg) | component.button.label.font-size.lg | 12×16px (component.button.padding-y.lg × padding-x.lg) | 48px — meets AAA 44px target |
EstadosStates
Estados são controlados via pseudo-classes CSS (:hover, :active, :focus-visible, [disabled]), não classes modificadoras.States are handled via CSS pseudo-classes (:hover, :active, :focus-visible, [disabled]), not modifier classes.
| EstadoState | CSS trigger | Mudança visualVisual change | Token |
|---|---|---|---|
| Default | — | Preenchimento primárioPrimary fill | component.button.bg.brand.default |
| Hover | :hover | Preenchimento mais escuroDarker fill | component.button.bg.brand.hover |
| Pressed | :active | Preenchimento mais escuro aindaDarkest fill | component.button.bg.brand.pressed |
| Focus | :focus-visible | Ring de 2px com afastamento de 2px e cores do estado focus2px ring with 2px offset and focus-state colors | component.button.bg.brand.focus, component.button.content.color.brand.focus, component.button.focus-ring.* |
| Disabled | [disabled] | Bg + conteúdo atenuados, sem pointer eventsMuted bg + content, no pointer events | component.button.bg.brand.disabled, component.button.content.color.brand.disabled |
Com íconeWith icon
Somente íconeIcon only
CarregamentoLoading
Largura totalFull width
Boas práticasBest practices
Diretrizes de conteúdoContent guidelines
| RegraRule | ExemploExample |
|---|---|
| Use verbo + substantivo para clarezaUse verb + noun for clarity | "Save changes", "Add item", "Delete project" — não apenas "Submit" ou "OK""Save changes", "Add item", "Delete project" — not just "Submit" or "OK" |
| Use sentence caseUse sentence case | "Save changes" — não "Save Changes" ou "SAVE CHANGES""Save changes" — not "Save Changes" or "SAVE CHANGES" |
| Mantenha labels curtos (1–3 palavras)Keep labels short (1–3 words) | "Export CSV" — não "Click here to export your data as CSV""Export CSV" — not "Click here to export your data as CSV" |
| Seja específico sobre ações destrutivasBe specific about destructive actions | "Delete account" — não "Delete" ou "Remove""Delete account" — not "Delete" or "Remove" |
| Evite labels genéricosAvoid generic labels | "Confirm order" — não "Click here" ou "Yes""Confirm order" — not "Click here" or "Yes" |
Buttons somente-ícone precisam de aria-labelIcon-only buttons need aria-label | aria-label="Close dialog" — descreve a ação, não o íconearia-label="Close dialog" — describes the action, not the icon |
Mapeamento de tokensToken mapping
Tokens consumidos pela variante Brand. Outras variantes seguem o mesmo padrão usando seus respectivos grupos de cor.Tokens consumed by the Brand variant. Other variants follow the same pattern using their respective color groups.
| PropriedadeProperty | Token (Component) | Variável CSSCSS variable |
|---|---|---|
| height (sm) | component.button.height.sm | --ds-button-height-sm |
| height (md) | component.button.height.md | --ds-button-height-md |
| height (lg) | component.button.height.lg | --ds-button-height-lg |
| min-width (sm/md/lg) | component.button.min-width.{sm,md,lg} | --ds-button-min-width-* |
| padding-x (sm/md/lg) | component.button.padding-x.{sm,md,lg} | --ds-button-padding-x-* |
| padding-y (sm/md/lg) | component.button.padding-y.{sm,md,lg} | --ds-button-padding-y-* |
| gap (sm/md/lg) | component.button.gap.{sm,md,lg} | --ds-button-gap-* |
| radius / border-width | component.button.radius.default, component.button.border-width.default | --ds-button-radius-default, --ds-button-border-width-default |
| bg por estilo/estado | component.button.bg.{brand,toned,outline,ghost,success,danger}.* | --ds-button-bg-* |
| border color Outline | component.button.border-color.outline.* | --ds-button-border-color-outline-* |
| text/icon color | component.button.content.color.{style}.{state} | --ds-button-content-color-* |
| label typography | component.button.label.{font-size,line-height,font-weight,letter-spacing}.* | --ds-button-label-* |
| icon frame/size | component.button.icon.size.{sm,md,lg}, component.button.icon.stroke-width.{sm,md,lg} | --ds-button-icon-* |
| icon-only | component.button.icon-only-{width,padding}.{sm,md,lg} | --ds-button-icon-only-* |
| focus ring | component.button.focus-ring.radius.default, component.focus-ring.{width,color.default,color.success,color.error} | --ds-focus-ring-* + --ds-button-focus-ring-radius-default |
Variante TonedToned variant
--ds-toned-background-default, --ds-toned-background-hover, --ds-toned-background-active) em vez de preenchimentos opacos. Isso difere dos padrões Subtle/Muted que usam tokens de background opacos. A abordagem translúcida permite que o button Toned se adapte naturalmente a qualquer cor de superfície abaixo dele, mantendo um tint de marca consistente.The Toned variant uses translucent overlay backgrounds (--ds-toned-background-default, --ds-toned-background-hover, --ds-toned-background-active) instead of opaque fills. This differs from Subtle/Muted patterns which use opaque background tokens. The translucent approach lets the Toned button adapt naturally to any surface color beneath it while maintaining a consistent brand tint.
Classes CSSCSS classes
| ClasseClass | DescriçãoDescription |
|---|---|
ds-button | Classe base do buttonBase button class |
ds-button--brand | Preenchido com cor da marcaFilled with brand color |
ds-button--toned | Background da marca com alpha transparenteAlpha-tinted brand background |
ds-button--outline | Borda neutra, sem preenchimento de marcaNeutral border, no brand fill |
ds-button--ghost | Texto da marca, sem background ou bordaBrand text, no background or border |
ds-button--success | Preenchido com cor de sucesso/verdeFilled with success/green color |
ds-button--danger | Preenchido com cor de erro/vermelhoFilled with error/red color |
ds-button--sm | Tamanho pequeno (altura 32px)Small size (32px height) |
ds-button--md | Tamanho médio (40px, padrão — pode ser omitido)Medium size (40px, default — can be omitted) |
ds-button--lg | Tamanho grande (altura 48px)Large size (48px height) |
ds-button--icon-only | Button quadrado para uso somente-íconeSquare button for icon-only use |
ds-button--full | Button de largura total (100%)Full-width button (100%) |
ds-button--loading | Estado de carregamento — oculta label, mostra spinnerLoading state — hides label, shows spinner |
ds-button__label | Label de texto (elemento filho)Text label (child element) |
ds-button__spinner | Container do spinner (elemento filho, usado com --loading)Spinner container (child element, used with --loading) |
Interação por tecladoKeyboard interaction
| TeclaKey | AçãoAction |
|---|---|
Tab | Move o foco para o button (ou além dele se desabilitado)Moves focus to the button (or past it if disabled) |
Enter | Ativa o buttonActivates the button |
Space | Ativa o botãoActivates the button |
Buttons desabilitados ([disabled]) são removidos da ordem de tabulação automaticamente pelo navegador. Buttons em carregamento também devem definir aria-disabled="true" para prevenir interação enquanto preservam a ordem de tabulação.Disabled buttons ([disabled]) are removed from tab order automatically by the browser. Loading buttons should also set aria-disabled="true" to prevent interaction while preserving tab order.
AcessibilidadeAccessibility
| Critério WCAGWCAG criterion | RequisitoRequirement | Status |
|---|---|---|
| 2.4.11 Focus Appearance (AA) | Focus ring 2px + gap de 2px, contraste ≥ 3:1 contra cores adjacentesFocus ring 2px + 2px gap, contrast ≥ 3:1 against adjacent colors | ✓ |
| 2.5.8 Target Size min (AA) | Menor tamanho (32px) excede o mínimo de 24pxSmallest size (32px) exceeds 24px minimum | ✓ |
| 2.5.5 Target Size (AAA) | Tamanho grande (48px) atende ao alvo de toque de 44pxLarge size (48px) meets 44px touch target | ✓ |
| 1.4.3 Contrast (AA) | Texto branco sobre Brand/Danger fill ≥ 4.5:1. Desabilitado isento.White text on Brand/Danger fill ≥ 4.5:1. Disabled exempt. | ✓ |
| 4.1.2 Name, Role, Value (A) | Use o elemento <button>. Somente-ícone requer aria-label.Use <button> element. Icon-only requires aria-label. | ✓ |
| 1.4.1 Use of Color (A) | Estado focado tem ring visível. Desabilitado tem texto esmaecido + opacidade reduzida.Focused state has visible ring. Disabled has dimmed text + reduced opacity. | ✓ |
aria-label — obrigatório em buttons somente-ícone.aria-disabled="true" + aria-busy="true" — definido em buttons em carregamento.disabled — use o atributo nativo para buttons realmente desabilitados (removidos da ordem de tabulação).aria-label — required on icon-only buttons.aria-disabled="true" + aria-busy="true" — set on loading buttons.disabled — use the native attribute for truly disabled buttons (removed from tab order).
Figma
O componente Figma expõe as propriedades abaixo no painel. Booleans de visibilidade ficam imediatamente acima do slot que controlam.The Figma component exposes the properties below in the panel. Visibility booleans sit immediately above the slot they control.
| PropriedadeProperty | TipoType | PadrãoDefault | OpçõesOptions |
|---|---|---|---|
| EstiloStyle | Variant | Brand | Brand, Toned, Outline, Ghost, Success, Danger |
| TamanhoSize | Variant | Medium | Small (32px), Medium (40px), Large (48px) |
| EstadoState | Variant | Default | Default, Hover, Pressed, Focused, Disabled |
| Icon Only | Variant | false | Default (com label), Icon Only (quadrado)Default (with label), Icon Only (square) |
| Loading | Boolean | false | true, false |
| Show Left Icon | Boolean | false | Alterna a visibilidade do frame de ícone esquerdoToggles visibility for the left icon frame |
| Left Icon | Instance swap | Placeholder | Define o componente de ícone esquerdoSets the left icon component |
| Show Right Icon | Boolean | false | Alterna a visibilidade do frame de ícone direitoToggles visibility for the right icon frame |
| Right Icon | Instance swap | Placeholder | Define o componente de ícone direitoSets the right icon component |