Get started
Design system
Light, depth, materials, motion and shape: the tokens everything reads.
Bevel looks like one set because every component reads the same few dozen tokens. They live in one stylesheet, bevel.css, which arrives with your first component.
Three layers
- Foundation (
bevel.css): light, depth, materials, motion and shape. The only place raw values live. - Component stylesheet (
wallet.css,annunciator.css…): the component's own palette and geometry, mapped onto the foundation's variables bydata-slot,data-variantanddata-status. - Component (
.tsx): Tailwind classes that only read tokens.
Each layer reads only from the one below it. In practice:
:root {
--annunciator-amber: oklch(0.8 0.16 75); /* a palette value, named once */
}
[data-slot="annunciator-tile"] {
--annunciator-lamp: var(--annunciator-amber);
}<span className="bg-(--annunciator-lamp) rounded-(--bevel-radius-xs)
transition-opacity duration-(--bevel-duration-small)" />Utilities
The foundation turns tokens into a few utilities, so components describe objects, not shadows.
- Depth:
bevel-recessed,bevel-flush,bevel-raised,bevel-pressed,bevel-object. - Materials:
bevel-leather,bevel-plastic,bevel-metal,bevel-paper. Each reads--bevel-materialand--bevel-material-edge, so one utility makes walnut, brass or steel. - Details:
bevel-deboss,bevel-stitch,bevel-fill,bevel-led,bevel-ink,bevel-glass,bevel-ruled.
Rules
- One light source, from above. Highlights on upper edges, shadows below.
- Nested radii are concentric: an inner radius is the outer radius minus the inset between them.
- If a value doesn't exist, add a named token with a comment, not an arbitrary value.
- Don't add
--text-*theme keys: Tailwind's class merging reads unknowntext-*classes as colours.
In the Bevel repo,
pnpm check:tokens enforces this: it fails on raw colours, durations, easings or lengths in components, and on any transition of a layout property.Foundation tokens
Read straight from bevel.css, light mode. Dark mode redefines the light and paper tokens.
Light
| Token | Value | For |
|---|---|---|
| --bevel-highlight | oklch(1 0 0 / 0.22) | |
| --bevel-highlight-strong | oklch(1 0 0 / 0.35) | |
| --bevel-shade | oklch(0 0 0 / 0.32) | |
| --bevel-shade-strong | oklch(0 0 0 / 0.5) | |
| --bevel-cast | oklch(0.25 0.03 50 / 0.22) | |
| --bevel-deboss | 0 -1px 0 oklch(0 0 0 / 0.45), 0 1px 0 oklch(1 0 0 / 0.12) | Stamped into a surface: shaded on the upper inner edge, lit below. |
Material defaults
| Token | Value | For |
|---|---|---|
| --bevel-material | oklch(0.47 0.085 52) | |
| --bevel-material-edge | oklch(0.3 0.06 44) | |
| --bevel-material-recess | oklch(0.2 0.008 260) | neutral dark; materials set their own |
| --bevel-grain | SVG texture | |
| --bevel-grain-size | 180px |
Depth
| Token | Value | For |
|---|---|---|
| --bevel-depth-recessed | (several shadows) | |
| --bevel-depth-flush | (several shadows) | |
| --bevel-depth-raised | (several shadows) | |
| --bevel-depth-pressed | (several shadows) | |
| --bevel-depth-object | (several shadows) | A whole object resting on the page. |
| --bevel-depth-cast-sm | 0 4px 6px var(--bevel-cast) | The shadow under a loose object, for filter: drop-shadow(). |
| --bevel-depth-sheet | (several shadows) | A thin object (a card) lying on another surface. |
Motion
| Token | Value | For |
|---|---|---|
| --bevel-ease-out | cubic-bezier(0.23, 1, 0.32, 1) | |
| --bevel-ease-in-out | cubic-bezier(0.77, 0, 0.175, 1) | |
| --bevel-ease-spring | linear(0, 0.06, 0.202, 0.38, 0.561, 0.723, 0.856, 0.955, 1.023, 1.062, 1.081, 1.083, 1.075, 1.062, 1.047, 1.032, 1.019, 1.009, 1.002, 0.997, 0.994, 0.993, 0.993, 0.994, 1) | Underdamped spring, ~8% overshoot. Pure CSS; pair with --bevel-duration-move or longer. |
| --bevel-duration-press | 100ms | a control giving under a finger |
| --bevel-duration-small | 200ms | hover lifts, tabs, small state changes |
| --bevel-duration-move | 300ms | objects moving: cards, drawers |
| --bevel-duration-ambient | 520ms | whole-scene changes: lighting |
| --bevel-stagger | 30ms | |
| --bevel-lift | 3px | how far an object rises on hover |
| --bevel-perspective | 30rem | viewing distance for parts that turn in 3D (covers, flaps) |
| --bevel-dim | 0.82 | Unchosen items in a group sit back in shadow. |
Shape
| Token | Value | For |
|---|---|---|
| --bevel-radius-xs | 0.25rem | |
| --bevel-radius-sm | 0.5rem | |
| --bevel-radius-md | 0.625rem | |
| --bevel-radius-lg | 1rem | |
| --bevel-radius-xl | 1.5rem | |
| --bevel-stitch-width | 1.5px | |
| --bevel-stitch-inset | 0.375rem | |
| --bevel-amount | 2.25rem | Amounts: the figure, its secondary parts (currency, cents), labels, fine print. |
| --bevel-amount-minor | 1.25rem | |
| --bevel-label | 0.75rem | |
| --bevel-fine | 0.6875rem | |
| --bevel-tracking-label | 0.08em | stamped labels |
| --bevel-tracking-print | 0.06em | printed marks on cards |
Paper and ink
| Token | Value | For |
|---|---|---|
| --bevel-paper | oklch(0.975 0.008 85) | |
| --bevel-paper-foreground | oklch(0.28 0.02 260) | |
| --bevel-paper-muted | oklch(0.48 0.015 260) | |
| --bevel-paper-rule | oklch(0.78 0.04 240 / 0.45) | |
| --bevel-paper-margin | oklch(0.68 0.14 25 / 0.45) | |
| --bevel-fibre | SVG texture | |
| --bevel-ink-texture | SVG texture | Ink soaks unevenly: mostly solid with pale specks. Used as a mask. |
| --bevel-ink-red | oklch(0.52 0.19 27) | |
| --bevel-ink-blue | oklch(0.44 0.14 262) | |
| --bevel-ink-green | oklch(0.5 0.12 155) | |
| --bevel-ink-black | oklch(0.3 0.01 260) | |
| --bevel-ink-amber | oklch(0.55 0.13 65) |
Brass and ivory
| Token | Value | For |
|---|---|---|
| --bevel-brass | oklch(0.76 0.11 82) | |
| --bevel-brass-edge | oklch(0.52 0.08 70) | |
| --bevel-ivory | oklch(0.95 0.025 90) | |
| --bevel-ivory-foreground | oklch(0.25 0.015 60) | |
| --bevel-needle | oklch(0.55 0.2 27) |
Desk stationery
| Token | Value | For |
|---|---|---|
| --bevel-pad | oklch(0.95 0.075 98) | yellow legal pad |
| --bevel-pad-foreground | oklch(0.27 0.03 255) | |
| --bevel-pad-rule | oklch(0.72 0.06 235 / 0.45) | |
| --bevel-pad-margin | oklch(0.62 0.16 25 / 0.55) | |
| --bevel-pen-red | oklch(0.52 0.2 27) | correcting pen |
| --bevel-pen-blue | oklch(0.42 0.15 262) | writing pen |
| --bevel-pencil | oklch(0.55 0.01 260) | not written in ink yet |
| --bevel-sticker | oklch(0.9 0.12 95) | exhibit sticker |
| --bevel-sticker-foreground | oklch(0.26 0.03 70) | |
| --bevel-font-marker | "Permanent Marker", "Marker Felt", "Chalkboard SE", ui-rounded, "Arial Rounded MT Bold", system-ui, sans-serif | Handwriting. Bring a marker font (e.g. Permanent Marker) for the full effect; these are fallbacks. |