08

View transitions

Three techniques on one router: nested crossfade boundaries (the sidebar chrome is pinned and never flickers), the traveling nav indicator — FLIP with zero keyframes — and a shared-element morph into a detail route. Click any card.

startViewTransitionview-transition-name::view-transition-group

Only GEOMETRY may bounce. The group animation (position/size travel) rides the spring; ::view-transition-old/new — the opacity crossfade — stays calm and flat. A spring on opacity reads as flicker, not physics.

Fleet units

the card morphs into the detail hero — same view-transition-name on both routes

Why the sidebar never flickers

nested boundaries, one discipline

root                 → slow-tier calm crossfade (whole page)
motion-content       → BASE-tier fade — dense data swaps read snappier
motion-chrome        → animation: none — identical pixels, zero flicker
nav-indicator        → group springs (ζ.48); old/new don't fade at all

/* the indicator name exists on the ACTIVE item ONLY — a duplicate
   view-transition-name makes the browser silently skip the ENTIRE
   transition. One name, one element, per capture. */
{active && <span style={{ viewTransitionName: "nav-indicator" }} />}