Bevel

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

  1. Foundation (bevel.css): light, depth, materials, motion and shape. The only place raw values live.
  2. Component stylesheet (wallet.css, annunciator.css…): the component's own palette and geometry, mapped onto the foundation's variables by data-slot, data-variant and data-status.
  3. Component (.tsx): Tailwind classes that only read tokens.

Each layer reads only from the one below it. In practice:

annunciator.css
:root {
  --annunciator-amber: oklch(0.8 0.16 75); /* a palette value, named once */
}
[data-slot="annunciator-tile"] {
  --annunciator-lamp: var(--annunciator-amber);
}
annunciator.tsx
<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-material and --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 unknown text-* 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

TokenValue
--bevel-highlightoklch(1 0 0 / 0.22)
--bevel-highlight-strongoklch(1 0 0 / 0.35)
--bevel-shadeoklch(0 0 0 / 0.32)
--bevel-shade-strongoklch(0 0 0 / 0.5)
--bevel-castoklch(0.25 0.03 50 / 0.22)
--bevel-deboss0 -1px 0 oklch(0 0 0 / 0.45), 0 1px 0 oklch(1 0 0 / 0.12)

Material defaults

TokenValue
--bevel-materialoklch(0.47 0.085 52)
--bevel-material-edgeoklch(0.3 0.06 44)
--bevel-material-recessoklch(0.2 0.008 260)
--bevel-grainSVG texture
--bevel-grain-size180px

Depth

TokenValue
--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)
--bevel-depth-cast-sm0 4px 6px var(--bevel-cast)
--bevel-depth-sheet(several shadows)

Motion

TokenValue
--bevel-ease-outcubic-bezier(0.23, 1, 0.32, 1)
--bevel-ease-in-outcubic-bezier(0.77, 0, 0.175, 1)
--bevel-ease-springlinear(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)
--bevel-duration-press100ms
--bevel-duration-small200ms
--bevel-duration-move300ms
--bevel-duration-ambient520ms
--bevel-stagger30ms
--bevel-lift3px
--bevel-perspective30rem
--bevel-dim0.82

Shape

TokenValue
--bevel-radius-xs0.25rem
--bevel-radius-sm0.5rem
--bevel-radius-md0.625rem
--bevel-radius-lg1rem
--bevel-radius-xl1.5rem
--bevel-stitch-width1.5px
--bevel-stitch-inset0.375rem
--bevel-amount2.25rem
--bevel-amount-minor1.25rem
--bevel-label0.75rem
--bevel-fine0.6875rem
--bevel-tracking-label0.08em
--bevel-tracking-print0.06em

Paper and ink

TokenValue
--bevel-paperoklch(0.975 0.008 85)
--bevel-paper-foregroundoklch(0.28 0.02 260)
--bevel-paper-mutedoklch(0.48 0.015 260)
--bevel-paper-ruleoklch(0.78 0.04 240 / 0.45)
--bevel-paper-marginoklch(0.68 0.14 25 / 0.45)
--bevel-fibreSVG texture
--bevel-ink-textureSVG texture
--bevel-ink-redoklch(0.52 0.19 27)
--bevel-ink-blueoklch(0.44 0.14 262)
--bevel-ink-greenoklch(0.5 0.12 155)
--bevel-ink-blackoklch(0.3 0.01 260)
--bevel-ink-amberoklch(0.55 0.13 65)

Brass and ivory

TokenValue
--bevel-brassoklch(0.76 0.11 82)
--bevel-brass-edgeoklch(0.52 0.08 70)
--bevel-ivoryoklch(0.95 0.025 90)
--bevel-ivory-foregroundoklch(0.25 0.015 60)
--bevel-needleoklch(0.55 0.2 27)

Desk stationery

TokenValue
--bevel-padoklch(0.95 0.075 98)
--bevel-pad-foregroundoklch(0.27 0.03 255)
--bevel-pad-ruleoklch(0.72 0.06 235 / 0.45)
--bevel-pad-marginoklch(0.62 0.16 25 / 0.55)
--bevel-pen-redoklch(0.52 0.2 27)
--bevel-pen-blueoklch(0.42 0.15 262)
--bevel-penciloklch(0.55 0.01 260)
--bevel-stickeroklch(0.9 0.12 95)
--bevel-sticker-foregroundoklch(0.26 0.03 70)
--bevel-font-marker"Permanent Marker", "Marker Felt", "Chalkboard SE", ui-rounded, "Arial Rounded MT Bold", system-ui, sans-serif
NextTheming