#360
Shared element
A plan cover that morphs from a list tile into the detail card through the View Transitions API, with a plain crossfade when the API is missing.
Hand this to your AI. It names the exact library parts, timings and accessibility promises of this demo.
Build the "Shared element" pattern (@codeatlasdev/ui demo #360, motion/transitions) in my app.
Call get_demo({ ids: ["#360"] }) first and keep its structure. It needs @codeatlasdev/[email protected].
Use: Opening a product, plan, photo or message from a list into its detail view without a jump cut.
Keep these library parts, with the props and tokens the demo uses:
- Button, Card, MotionStage, MotionCtx from "@codeatlasdev/ui"
Behaviour to keep:
- `MotionStage` with `label="Shared element: a plan cover grows into the detail view"` and `loop={2800}`
- The cover in the tile and the cover in the detail both carry `view-transition-name: se-cover`
- `doc.startViewTransition(() => flushSync(() => (open = next)))` swaps the view; without the API the new view runs `animation: se-fade 240ms`
- `::view-transition-group(se-cover)` uses `animation-duration: 420ms` and `animation-timing-function: cubic-bezier(0.2, 0, 0, 1)`
- Under reduced motion the detail is shown and no transition runs
Exact motion (do not approximate):
- position and size of the shared cover (view-transition-name: se-cover): 420ms, cubic-bezier(0.2, 0, 0, 1)
- opacity (crossfade fallback): 240ms, cubic-bezier(0.2, 0, 0, 1)
Reduced motion: the demo handles it; keep that branch.
Keyboard: operable; keep the focus order and key handling.
Change only the copy and the data. Use the theme tokens (--ca-*), never raw colours. Library parts
- Button
@codeatlasdev/ui - Card
@codeatlasdev/ui - MotionStage
@codeatlasdev/ui
How it is built
- `MotionStage` with `label="Shared element: a plan cover grows into the detail view"` and `loop={2800}`
- The cover in the tile and the cover in the detail both carry `view-transition-name: se-cover`
- `doc.startViewTransition(() => flushSync(() => (open = next)))` swaps the view; without the API the new view runs `animation: se-fade 240ms`
- `::view-transition-group(se-cover)` uses `animation-duration: 420ms` and `animation-timing-function: cubic-bezier(0.2, 0, 0, 1)`
- Under reduced motion the detail is shown and no transition runs
Related
Loading source.