Pular para o conteúdo

Buttons

components specs/components/buttons.kmd

Button system — 7 variants (filled, tonal, outlined, text, elevated, icon, FAB), button groups, segmented buttons. Material parity (`/components/all-buttons`, `/components/buttons`, `/components/button-groups`). Covers anatomy, hierarchy, states, accessibility, and per-preset shape variation.

Quando esta spec se aplica

Triggers primários

Todos os triggers

Corpo da especificação

Spec — Buttons

Facet Visual do Koder Design. Material parity: https://m3.material.io/components/all-buttons.

Covers #049.21 (button groups), #049.22 (segmented), #049.23 (icon button), #049.24 (FAB / extended FAB).

7 button variants

VariantVisualUse
FilledSolid accent bg + accent-on textPrimary action (1 per surface)
TonalSurface-variant bg + textSecondary action, less emphasis than filled
OutlinedTransparent bg + accent border + accent textSecondary, with stronger structure than text
TextNo bg, no border, accent textTertiary action, footer links, dismissive
ElevatedSurface bg + shadow level 1 + accent text"Picked up" button when surrounding flat
Icon24px icon, no label, surface or transparent bgAction without a label (toolbar)
FABRound (radius-full or xl) + accent fill + iconPrimary action shortcut, floats above

Plus 1 derivative: Extended FAB = FAB with text label beside the icon. Same visual treatment, broader.

Anatomy

┌──────────────────────────┐
│  [icon?]  Label  [icon?] │   ← container (radius-sm default)
└──────────────────────────┘
   pad-x       pad-x
  • Container: 40 px height default (32 px small, 56 px large)
  • Label: label-large type role (14/20, weight 500)
  • Optional leading icon: 18 px, 8 px gap to label
  • Optional trailing icon: 18 px, 8 px gap from label
  • Padding: 24 px horizontal (16 px if icon-only or compact)

FAB anatomy:

  • 56×56 px (default) or 96×96 (large) or 40×40 (small)
  • Single icon, no label (extended FAB adds label)
  • Radius: radius-xl (default) or radius-full (per preset)
  • Elevation: level 3 default, level 4 on hover

R1 — Hierarchy per surface

Allowed countVariantRole
At most 1Filled OR ElevatedPrimary action
0..NTonal OR OutlinedSecondary actions
0..NTextTertiary, dismissive
At most 1FABSurface-wide primary action (overrides Filled hierarchy on mobile)

Destructive actions: use Outlined OR Text style with error color token, never Filled red (Filled-red over-emphasizes; the action itself is enough warning).

R2 — Sizes

SizeHeightPad-xLabel role
Small3216label-medium
Default4024label-large
Large5632title-medium

Tap target: minimum 48 px touch area enforced via outer hit-zone expansion even on Small (visible 32 px, hit zone 48 px).

R3 — States

Per interaction/states.kmd:

StateFilledTonalOutlinedTextElevatedIconFAB
Hover+8% overlay+8% overlayaccent 8% bg8% bgelevation +18% bgelevation +1
Focus+ focus ring+ focus ringthicker border + ringaccent bg+ focus ring+ focus ring+ focus ring
Press+12% overlay + ripple+12% + ripple+12% bg + ripple12% bg + rippleelevation 0 + ripple12% bg + rippleelevation 2 + ripple
Disabled38% opacity38% opacity38% opacity38% opacity38% opacity38% opacity38% opacity

R4 — Button groups

Multiple related buttons rendered together as a unit.

┌──────┬──────┬──────┐
│ Day  │ Week │ Month│   ← single rounded container, dividers between
└──────┴──────┴──────┘

Rules:

  • Buttons share visual container (corner radius applies to OUTER container, not each button)
  • Inner dividers 1px solid border
  • All buttons same variant (don't mix filled + outlined in one group)
  • Same height across all buttons in group
  • Equal width (stretch to fill) OR content-sized (per design)

R5 — Segmented button

A button group used for single-select (exclusive choice).

  • Visual: same as button group
  • Selected state: accent-tinted background (accent-tint 12%) + accent text + checkmark icon (Material adds checkmark)
  • One must always be selected; can't all be off
  • role="radiogroup" + role="radio" on each segment (or native radio + label styling)

R6 — Icon-only buttons

  • 40×40 px square (default size), 32×32 small, 56×56 large
  • Single icon centered, 24 px (default)
  • aria-label REQUIRED (no visible label means accessible name must come from aria-label)
  • Tooltip on hover/focus showing the action name (per future tooltips.kmd)

R7 — FAB placement

PositionConvention
Bottom-rightDefault mobile (avoids overlapping bottom-nav-bar)
Bottom-centerWithin a bottom app bar (centered FAB pattern)
Top-right (desktop)Optional on Expanded/Large class

Margin from screen edge: 16 dp (Compact), 24 dp (Medium+). Avoid overlapping content; reserve safe-area space per safe-area.kmd.

R8 — Accessibility

  • Minimum touch target 48×48 px (R2)
  • <button> element (native; not <div onclick>)
  • Visible focus ring (focus-visible, 2 px solid focus color, 2 px offset)
  • aria-label for icon-only
  • aria-pressed for toggle buttons
  • aria-disabled for disabled (still focusable for keyboard announcement)
  • Loading state: aria-busy="true" + visible spinner

R9 — Per-preset variation

Each preset (per themes/ui-style.kmd) varies button shape:

  • material3: radius-sm (8 px)
  • material2: radius-sm (4 px — sharper)
  • windows_95: radius-none (0 px) + 3D bevel borders
  • ios_cupertino: radius-md (14 px — softer)
  • brutalist: radius-none + thick border (3 px)
  • glassmorphism: radius-md + backdrop blur background

Full table: themes/shape.kmd R3.

R10 — Forbidden patterns

  • ❌ More than 1 Filled button per surface
  • ❌ Filled red for destructive (use Outlined+error)
  • ❌ Buttons inside buttons
  • ❌ Variable button heights within a button group
  • ❌ Custom hex colors (must come from accent/error/success tokens)
  • ❌ Tap targets smaller than 48 px effective hit area
  • interaction/states.kmd — state overlay opacities
  • themes/color-roles.kmd — accent + accent-on bindings
  • themes/shape.kmd — radius per preset
  • themes/elevation.kmd — elevated variant + FAB elevation
  • themes/typography.kmd — label-large default role
  • foundations/elements.kmd — Control family

Referências