Tilt card
A card that leans toward your pointer as if you'd pressed that side down. It moves on springs, so it has weight: it overshoots a little and settles. The light moves with the tilt, the shadow slides away from the edge that comes up, and anything printed at its own depth shifts against the face.
Installation
npx @neelshha/ui@latest add tilt-cardUsage
import { TiltCard } from "@/components/ui/tilt-card";
<TiltCard foil className="member-card">
<p className="member-name">Ada Lovelace</p>
</TiltCard>
/* The name floats above the face. */
.member-name {
transform: translateZ(1rem);
}Give it a size with a class. The card fills it. Only the card inside tips; the frame holds still, so the edge under the pointer doesn't slide away from it. For layers at their own depth, give a child a translateZ, and transform-style: preserve-3d on anything between.
Glare
Without foil, only a sheen follows the tilt. A bigger max tips it further.
Night Drive
Side A · 9 tracks
<TiltCard max={14} className="cover">
<CoverArt />
</TiltCard>Driven
at tips the card toward any point you give it: a phone's gyroscope, a script, or the pointer anywhere in a bigger box, like this one.
const [at, setAt] = useState(null);
<div
onPointerMove={(event) => {
const box = event.currentTarget.getBoundingClientRect();
setAt({
x: ((event.clientX - box.left) / box.width) * 2 - 1,
y: ((event.clientY - box.top) / box.height) * 2 - 1,
});
}}
onPointerLeave={() => setAt(null)}
>
<TiltCard foil at={at}>…</TiltCard>
</div>Keyboard
It isn't a control, so it takes no focus of its own. When a link or button on it gets keyboard focus, the card lifts toward you without tipping.
API
Other props go to the outer div. On a touch screen it tips where a finger lands and settles when it lifts, and a vertical swipe still scrolls the page. --ns-tilt-perspective and --ns-tilt-rise set how deep it looks. With reduced motion the card stays flat and only the light comes up.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | What's printed on the card. A child with its own translateZ floats above the face. | |
max | number | 10 | How far the card tips at its edges, in degrees. |
glare | boolean | true | A sheen where the light catches the face. |
foil | boolean | false | Rainbow bands that slide across the face as it tips, like the foil on a trading card. Strongest on a dark face. |
at | { x: number; y: number } | null | Tips the card toward a point instead of following the pointer, from -1 to 1 across and down. null lays it flat. |