@beauhawkinson/plinth
v1.0.0
Published
Stepped 3D cards that lift and breathe under the cursor — a React component built to feel physical, not snappy.
Maintainers
Readme
@beauhawkinson/plinth
A React component for rendering interactive 3D card stacks. Handles the spatial math — perspective, step offsets, face transforms, hover physics — and exposes styling hooks so each face can look however you like.
Install
npm install @beauhawkinson/plinth motionUsage
import { Plinth } from "@beauhawkinson/plinth";
export default function Example() {
return <Plinth count={6} />;
}Default styles are bundled with the component and inject automatically when it mounts — no separate CSS import needed.
Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| count | number | 12 | Number of cards in the stack |
| cardWidth | number | 384 | Card face width in px |
| cardHeight | number | 160 | Card face height in px |
| rotateX | number | -12 | X-axis tilt in degrees |
| rotateY | number | -45 | Y-axis tilt in degrees |
| perspective | number | 1200 | CSS perspective distance in px |
| depth | number | auto | Pillar depth — derived from cardHeight when unset |
| peek | number | auto | How much of each card shows behind the next |
| rise | number | auto | Vertical offset between adjacent cards |
| liftAmount | number | auto | Distance a card travels up on hover |
| hover | HoverConfig | — | Spring + scale + falloff config |
| faceStyles | FaceStyles | {} | Per-face className overrides |
| className | string | — | Class applied to the outer container |
HoverConfig
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| spring | SpringOptions | { stiffness: 200, damping: 30, mass: 0.2 } | Motion spring for lift and scale |
| scaleDip | number | -0.2 | Scale change applied broadly across the stack |
| scaleBoost | number | 1.618 | Extra scale on the hovered card |
| falloff | number | 1.618 | Broad influence radius decay |
| narrowFalloff | number | 1.618 | Tighter falloff used for the lift effect |
Styling
Two approaches, use either or both:
1. faceStyles prop — pass Tailwind (or any) class names per face. Merges with the bundled defaults:
<Plinth
faceStyles={{
front: "bg-zinc-900 text-zinc-50",
top: "bg-zinc-800",
left: "bg-zinc-700",
right: "bg-zinc-700",
}}
/>2. data-face CSS selectors — scope your overrides via a wrapper className:
.my-stack [data-face="front"] { background: oklch(0.88 0.14 94); }
.my-stack [data-face="top"] { background: oklch(0.85 0.16 94); }<Plinth className="my-stack" />The bundled stylesheet uses two CSS variables — --plum (borders) and --soot (shadow tint) — which you can override on :root to retheme the defaults globally.
Monorepo
src/ — library source (published to npm)
apps/website/ — docs and demo site (beauhawkinson.us)
apps/playground/ — local sandbox for testingpnpm install
pnpm dev # run the docs site with live library
pnpm build:lib # build the library to dist/
pnpm build # build library + docs site
pnpm typecheck
pnpm lintLicense
MIT
