Carousels — Hero Expressive extension

mandatory

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.

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

  1. *trict extension*— base Hero layout from carousels.kmd unchanged.
  2. *hape morph items*— selected item uses larger radius, peek items smaller.
  3. *pring inertia*— gesture release follows spring decay, NOT linear.
  4. *idth tokens*— large item 6490% viewport; peek 1032%.

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 antipattern: linear decay OR frictionbased (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 widthclass: large 90% + peek 5% (almost only large). Medium/Expanded: large 6470% + 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

  • *1*Mount Hero Expressive: selected item visible center with Pill shape; peek items sides with shape-corner-large.
  • *2*Swipe gesture: radius interpolates continuously during drag.
  • *3*Release with velocity: spring decay; snaps to nearest center.
  • *4*Bounce: subtle overshoot visible (~5dp) before settle in material_expressive.
  • *5*Width tokens: Compact width-class → large 90%; Medium → 64% + 18% peeks.
  • *6*Reduced-motion: no morph + no bounce; instant snap.
  • *7*Keyboard: arrows advance one item.
  • *8*Selected aria-current: assistive tech announces correctly.
  • *9*Material2 preset: falls back to base carousels (no extension).

Source: ../home/koder/dev/koder/meta/docs/stack/specs/components/carousels-expressive.kmd