Carousels — Hero Expressive extension
components specs/components/carousels-expressive.kmd
Material 3 Expressive extension to base Hero carousel (specs/components/ carousels.kmd). Adds shape morphing between selected/peek items (square ↔ pill ↔ squircle) and gesture inertia driven by spring physics (motion.kmd R9.1). Connected to shape-library.kmd morph contract.
When this spec applies
Primary triggers
- Add Hero Expressive variant to a carousel surface
All triggers
- Apply Expressive look on Hero carousel surfaces
- Implement hero feed (Vista, Reel) with Expressive variant
Specification body
Spec — Carousels Hero Expressive
Strict extension to
carousels.kmd§Hero layout. Adds shape morph + spring-driven inertia. Base spec remains valid; Expressive opt-in per surface OR per preset.
Princípios
- Strict extension — base Hero layout from
carousels.kmdunchanged. - Shape morph items — selected item uses larger radius, peek items smaller.
- Spring inertia — gesture release follows spring decay, NOT linear.
- Width tokens — large item 64-90% viewport; peek 10-32%.
R1 — Anatomy (extension)
Base Hero per carousels.kmd. Expressive adds:
┌──┐ ┌──────────────────┐ ┌──┐
│ ◐│ │ ◯ │ │◐ │
│ │ │ ⬢⬡⬢ │ │ │ ← peek items (Cookie-7-ish) + selected (Pill-ish)
│ ◐│ │ ◯ │ │◐ │
└──┘ └──────────────────┘ └──┘
During swipe, shapes morph in real-time (corner radius interpolates).
R2 — Shape tokens
| Position | Default shape (per shape-library.kmd) | Corner radius |
|---|---|---|
| Selected (center large) | Pill or shape-corner-extra-large | 32dp+ |
| Peek (sides) | shape-corner-large | 16-24dp |
| Mid-transition | interpolated linear | varies |
During swipe gesture:
- Position 0% (center): selected shape full radius.
- Position 50% (mid-swipe): item halfway out, radius interpolates toward peek.
- Position 100% (off-screen): peek shape OR fully gone.
R3 — Spring inertia
Release gesture (swipe-release):
- Velocity captured; preserved into spring
motion-spatial-default. - Spring decay: snap to nearest item center (large OR peek).
- Bounce: subtle overshoot (max ±5dp) by default; configurable per preset.
Forbidden anti-pattern: linear decay OR friction-based (felt "slidey").
R4 — Width tokens
| Token | Range | Use |
|---|---|---|
hero-item-large | 64-90% viewport | Selected center |
hero-item-peek | 10-32% viewport | Sides |
hero-gap | 8-16dp | Between items |
Compact width-class: large 90% + peek 5% (almost only large). Medium/Expanded: large 64-70% + peek 18% each side.
R5 — Per-preset variation
| Preset | Hero Expressive style |
|---|---|
material3 | Subtle (radius delta 16dp; minimal bounce) |
material_expressive | Full (radius delta 32dp; bounce ±5dp) |
material2 | Disabled — falls back to baseline carousels |
terminal_classic | n/a (no carousels in terminal) |
brutalist | Sharp corners only; no morph; no bounce (instant snap) |
cyberpunk_neon | Default + glow on selected |
minimalist_mono | No radius variation; only width difference |
R6 — Surface bindings
| Surface | API |
|---|---|
| Flutter | Extension of KoderCarousel (per carousels.kmd); KoderCarousel(variant: hero, expressive: true) |
| Web | <koder-carousel variant="hero" expressive> |
| Compose | KoderCarousel(variant = Hero, expressive = true) |
| SwiftUI | idem |
| CLI / TUI | n/a |
R7 — Acessibilidade
- Items:
role="listitem"per base spec. - Selected:
aria-current="true". - Swipe alternative: arrow keys advance one item at a time.
- Reduced-motion: no shape morph; no bounce; snap direct (instant transition).
- Touch target: each item ≥ 48dp tap area.
R8 — Reduced-motion
- Shape morph: disabled (static shapes per position).
- Spring inertia: replaced by linear snap (no overshoot, no bounce).
- Item swap: instant.
R9 — i18n
Inherits from carousels.kmd. No new keys.
T-suite
- T1 Mount Hero Expressive: selected item visible center with
Pillshape; peek items sides withshape-corner-large. - T2 Swipe gesture: radius interpolates continuously during drag.
- T3 Release with velocity: spring decay; snaps to nearest center.
- T4 Bounce: subtle overshoot visible (~5dp) before settle in
material_expressive. - T5 Width tokens: Compact width-class → large 90%; Medium → 64% + 18% peeks.
- T6 Reduced-motion: no morph + no bounce; instant snap.
- T7 Keyboard: arrows advance one item.
- T8 Selected aria-current: assistive tech announces correctly.
- T9 Material2 preset: falls back to base carousels (no extension).
Cross-link
- Base:
carousels.kmd§Hero - Shape morph:
shape-library.kmdR2 - Motion:
motion.kmdR9.1 - Layout:
app-layout/window-size-classes.kmd(width tokens) - Refs: M3 Carousel guidelines (Expressive Hero)
References
specs/components/carousels.kmdspecs/themes/motion.kmdspecs/themes/shape-library.kmd