Button groups — Expressive extension
components specs/components/button-groups-expressive.kmd
Material 3 Expressive extension to base button groups (specs/components/buttons.kmd §Button groups). Adds 5 sizes (XS-XL), connected appearance (no gap + shared corners), shape/motion transformations on hover/press via spring. Strictly extends; baseline buttons.kmd remains valid.
Quando esta spec se aplica
Triggers primários
- Apply Expressive button group styling
Todos os triggers
- Adopt Expressive look on button group surfaces
- Hover/press feedback with shape morph on grouped buttons
Corpo da especificação
Spec — Button groups Expressive
Strict extension to
buttons.kmd§Button groups. Compatible: code using base button groups remains valid; Expressive opt-in per surface OR per preset.
Princípios
- Connected by default — sem gap entre items; visual unified group.
- 5 sizes XS-XL — granular sizing extending baseline 3 sizes.
- Shape morph on press — corner radius pulls toward pressed item.
- Scale on hover — 1.0 → 1.05 via spring (desktop + tablet hover).
- Reduced-motion safe — animations skipped under
prefers-reduced-motion.
R1 — Anatomy (extension)
Base anatomy per buttons.kmd §Button groups. Expressive adds:
normal: ┌──┬──┬──┬──┐
│ A│ B│ C│ D│
└──┴──┴──┴──┘
hover B: ┌──┬────┬──┬──┐ ← B scales 1.05 + neighbors compress
│ A│ B │ C│ D│
└──┴────┴──┴──┘
press C: ┌──┬──┬──┬──┐
│ A│ B│CCC│ D│ ← C grabs visual focus
└──┴──┴──┴──┘
R2 — 5 sizes
| Size | Item height (dp) | Padding L+R | Min item width |
|---|---|---|---|
| XS | 28 | 8 | 48 |
| S | 32 | 10 | 56 |
| M | 40 | 16 | 64 |
| L | 48 | 20 | 72 |
| XL | 56 | 24 | 80 |
R3 — Connected appearance
- No gap entre items (0dp).
- Shared inner border (1dp; color
outline-variant). - Group radius:
shape-corner-smallorshape-corner-medium(per preset; xs/sm in expressive default). - Items at edges share group radius; inner items square.
R4 — Hover state
Hover an item (desktop/mouse OR tablet stylus-hover):
- Scale: 1.0 → 1.05 over 200ms spring
motion-spatial-fast(permotion.kmdR9.1). - Neighbors compress slightly (max 5% width reduction) to make room.
- Group radius shifts toward hovered item.
- Color shift: hovered item background
surface-container-highest.
R5 — Press state
Press item:
- Scale: 1.0 → 0.97 (subtle "click" feel) via spring.
- Group radius "pulls toward" pressed item (radius asymmetric briefly).
- Color:
primary-container(filled style) ORprimarytext (outlined). - Release: spring back to default state.
R6 — Selected state (for toggle groups)
Selected item in toggle group:
- Background:
secondary-container(tonal). - Persistent (not press-flash).
- Shape: filled in corner radius of group.
Multi-select OR single-select per host config.
R7 — Surface bindings
| Surface | API |
|---|---|
| Flutter | Extension of KoderButtonGroup (per buttons.kmd); pass expressive: true flag |
| Web | <koder-button-group expressive> |
| Compose | KoderButtonGroup(expressive = true) |
| SwiftUI | idem |
| CLI / TUI | Flat text; expressive ignored |
R8 — Acessibilidade
- Buttons individually focusable per
buttons.kmd. - Hover scale: visual only — does NOT affect tab order.
- Reduced-motion: hover scale + radius shift disabled; color shift remains.
- Touch target ≥ 28dp per size XS (sizes S+ already meet 32+).
R9 — i18n
Inherits from buttons.kmd. No new keys.
R10 — Per-preset variation
| Preset | Expressive button group |
|---|---|
material3 | Subtle expressive (smaller scale 1.02; weaker shape morph) |
material_expressive | Full expressive (defaults from this spec) |
material2 | Disabled — falls back to baseline buttons.kmd |
terminal_classic | Plain [A][B][C] text — no expressive |
brutalist | No hover scale; no shape morph; sharp corners only |
cyberpunk_neon | Default + glow on hovered/pressed |
minimalist_mono | Hover changes underline only; no scale/morph |
T-suite
- T1 Render 3-item group XS → height 28dp; min width 48dp each.
- T2 Hover item: scale 1.0 → 1.05 via spring; neighbors compress.
- T3 Press item: scale → 0.97; release → springs back.
- T4 Group radius asymmetric during press; reverts on release.
- T5 Selected state: persistent secondary-container fill.
- T6 Reduced-motion: no scale + no shape morph; color shift kept.
- T7 Touch target ≥ 28dp for XS; S+ ≥ 32dp.
- T8 Disable expressive (flag false): falls back to base buttons.kmd behavior.
- T9 A11y: tab order unchanged by scale.
- N1 Material2 preset: expressive ignored (graceful).
Cross-link
- Base:
buttons.kmd§Button groups - Animation:
motion.kmdR9.1 - Shape morph:
shape-library.kmdR2 (corner radius interpolation) - Refs: M3 Button groups Expressive
Referências
specs/components/buttons.kmdspecs/themes/motion.kmdspecs/themes/shape-library.kmd