#386
Card tilt with glare
A payment card that leans up to 10 degrees toward the pointer on a spring while a soft glare slides across its surface.
Hand this to your AI. It names the exact library parts, timings and accessibility promises of this demo.
Build the "Card tilt with glare" pattern (@codeatlasdev/ui demo #386, motion/hero-ambient) in my app.
Call get_demo({ ids: ["#386"] }) first and keep its structure. It needs @codeatlasdev/[email protected].
Use: Product cards, pricing tiers, credit cards and badges that should feel like physical objects on hover.
Keep these library parts, with the props and tokens the demo uses:
- MotionStage, MotionCtx from "@codeatlasdev/ui"
Behaviour to keep:
- `const MAX = 10`: the card leans at most 10 degrees (`ry.target = nx * MAX`, `rx.target = -ny * MAX`)
- Two springs: `new Spring(0, { stiffness: 0.12, damping: 0.55 })` for `rx` and for `ry`
- `transform: rotateX(var(--rx)) rotateY(var(--ry))` inside a `perspective: 700px` parent; the glare is `radial-gradient(circle at var(--gx) var(--gy), rgb(255 255 255 / 0.38), transparent 55%)`
- Disabled on touch: `matchMedia('(hover: hover) and (pointer: fine)')` sets `fine`, and `@media (hover: none), (pointer: coarse)` removes the transform
- Autoplay sweeps `sweep` every `loop={1500}`; under reduced motion the card is flat (`--rx:{m.reduced || !fine ? 0 : rx.current}deg`)
Exact motion (do not approximate):
- transform: rotateX, rotateY; glare position: spring, spring, spring { stiffness: 0.12, damping: 0.55 }
Reduced motion: the demo handles it; keep that branch.
Keyboard: not an interactive control.
Change only the copy and the data. Use the theme tokens (--ca-*), never raw colours. Library parts
- MotionStage
@codeatlasdev/ui
How it is built
- `const MAX = 10`: the card leans at most 10 degrees (`ry.target = nx * MAX`, `rx.target = -ny * MAX`)
- Two springs: `new Spring(0, { stiffness: 0.12, damping: 0.55 })` for `rx` and for `ry`
- `transform: rotateX(var(--rx)) rotateY(var(--ry))` inside a `perspective: 700px` parent; the glare is `radial-gradient(circle at var(--gx) var(--gy), rgb(255 255 255 / 0.38), transparent 55%)`
- Disabled on touch: `matchMedia('(hover: hover) and (pointer: fine)')` sets `fine`, and `@media (hover: none), (pointer: coarse)` removes the transform
- Autoplay sweeps `sweep` every `loop={1500}`; under reduced motion the card is flat (`--rx:{m.reduced || !fine ? 0 : rx.current}deg`)
Related
Loading source.