Button groups — Expressive extension
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.
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
- *onnected by default*— sem gap entre items; visual unified group.
- * sizes XS-XL*— granular sizing extending baseline 3 sizes.
- *hape morph on press*— corner radius pulls toward pressed item.
- *cale on hover*— 1.0 → 1.05 via spring (desktop + tablet hover).
- *educed
motion safe*— animations skipped under `prefersreduced-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.
Multiselect OR singleselect 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
- *1*Render 3-item group XS → height 28dp; min width 48dp each.
- *2*Hover item: scale 1.0 → 1.05 via spring; neighbors compress.
- *3*Press item: scale → 0.97; release → springs back.
- *4*Group radius asymmetric during press; reverts on release.
- *5*Selected state: persistent secondary-container fill.
- *6*Reduced-motion: no scale + no shape morph; color shift kept.
- *7*Touch target ≥ 28dp for XS; S+ ≥ 32dp.
- *8*Disable expressive (flag false): falls back to base buttons.kmd behavior.
- *9*A11y: tab order unchanged by scale.
- *1*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