@renge-ui/tokens
The proportions made programmable.
15+ token categories derived from natural mathematics. CSS custom properties, JavaScript objects, Tailwind preset, and framework adapters. Zero dependencies. WCAG 2.1 AA certified.
pnpm add @renge-ui/tokensGetting Started
Three ways to consume.
Tokens are available as CSS custom properties, JavaScript objects, or Tailwind utilities. Pick the interface that fits your workflow.
CSS Custom Properties
Import the stylesheet. Every token becomes a CSS variable ready to use.
import '@renge-ui/tokens/renge.css';
/* In your CSS */
.card {
padding: var(--renge-space-4);
border-radius: var(--renge-radius-2);
background: var(--renge-color-bg-subtle);
border: 1px solid var(--renge-color-border);
}JavaScript / TypeScript
Fully typed token objects for programmatic access.
import { rengeVars } from '@renge-ui/tokens';
const cardStyles = {
padding: rengeVars.space[4],
borderRadius: rengeVars.radius[2],
background: rengeVars.color.bgSubtle,
border: `1px solid ${rengeVars.color.border}`,
};Tailwind CSS
Plugin automatically registers all tokens as utilities.
/* globals.css */
@import "tailwindcss";
@plugin "@renge-ui/tailwind/plugin";
<!-- HTML -->
<div class="p-renge-4 rounded-renge-2 bg-renge-bg-subtle border border-renge-border">
Fully proportional design, zero hardcoding.
</div>Spacing
Fibonacci × 4px
Each spacing step is a Fibonacci number multiplied by 4px (the base unit). 11 values from 4px to 220px create a naturally proportional scale.
All spacing values
| Class | Value / Derivation | CSS output |
|---|---|---|
| --renge-space-1 | 4px | 1 × 4px |
| --renge-space-2 | 8px | 2 × 4px |
| --renge-space-3 | 12px | 3 × 4px |
| --renge-space-4 | 20px | 5 × 4px |
| --renge-space-5 | 32px | 8 × 4px |
| --renge-space-6 | 52px | 13 × 4px |
| --renge-space-7 | 84px | 21 × 4px |
| --renge-space-8 | 136px | 34 × 4px |
| --renge-space-9 | 220px | 55 × 4px |
Usage example
/* Padding — all directions or individual sides */
.box {
padding: var(--renge-space-4); /* 20px all sides */
padding-left: var(--renge-space-5); /* 32px left only */
}
/* Margin */
.card {
margin: var(--renge-space-3);
margin-bottom: var(--renge-space-6); /* Increased bottom gap */
}
/* Gap in flexbox/grid */
.grid {
display: grid;
gap: var(--renge-space-5); /* 32px between all items */
grid-template-columns: repeat(3, 1fr);
}
/* Tailwind: prefix token names with p-, m-, gap-, etc. */
<div class="p-renge-4 m-renge-3 gap-renge-5">...</div>Tip: Use consistent spacing values to build visual rhythm. The Fibonacci scale naturally creates a sense of balance. If you need something between space-4 (20px) and space-5 (32px), consider the intended visual weight — often space-4 is sufficient.
Typography
PHI ratio scale
Eight font sizes derived from the golden ratio. Each size is exactly {PHI.toFixed(4)} times the previous, creating a proportionally harmonious hierarchy.
Font sizes (base 16px)
| Class | Value / Derivation | CSS output |
|---|---|---|
| --renge-font-size-xs | 10px | 16 × φ⁻⁰·⁵ ≈ 10px |
| --renge-font-size-sm | 13px | 16 × φ⁻⁰·²⁵ ≈ 13px |
| --renge-font-size-base | 16px | base (1.0) |
| --renge-font-size-lg | 26px | 16 × φ ≈ 26px |
| --renge-font-size-xl | 42px | 16 × φ² ≈ 42px |
| --renge-font-size-2xl | 68px | 16 × φ³ ≈ 68px |
| --renge-font-size-3xl | 110px | 16 × φ⁴ ≈ 110px |
| --renge-font-size-4xl | 177px | 16 × φ⁵ ≈ 177px |
Line height scale
| Class | Value / Derivation | CSS output |
|---|---|---|
| --renge-line-height-xs | 1.2 | Tight, for labels and captions |
| --renge-line-height-sm | 1.4 | Compact, for small text |
| --renge-line-height-base | 1.6 | Standard, for body text |
| --renge-line-height-lg | 1.8 | Generous, for long-form content |
| --renge-line-height-xl | 2.0 | Spacious, for visual comfort |
Letter spacing
| Class | Value / Derivation | CSS output |
|---|---|---|
| --renge-letter-spacing-tight | -0.02em | Headings, display text |
| --renge-letter-spacing-normal | 0em | Body text (default) |
| --renge-letter-spacing-wide | 0.05em | Small caps, emphasis |
| --renge-letter-spacing-ultra | 0.2em | Labels, all-caps UI text |
Usage example
/* Display heading */
h1 {
font-size: var(--renge-font-size-3xl); /* 110px */
line-height: var(--renge-line-height-xs); /* 1.2 tight */
letter-spacing: var(--renge-letter-spacing-tight);
}
/* Body text */
p {
font-size: var(--renge-font-size-base); /* 16px */
line-height: var(--renge-line-height-base); /* 1.6 */
}
/* Label or caption */
.label {
font-size: var(--renge-font-size-sm); /* 13px */
text-transform: uppercase;
letter-spacing: var(--renge-letter-spacing-ultra);
}
/* Tailwind: text-renge-xs, text-renge-sm, leading-renge-base, tracking-renge-wide */
<h1 class="text-renge-3xl leading-renge-xs">Heading</h1>
<p class="text-renge-base leading-renge-base">Paragraph</p>Pro tip: Combine font-size with matching line-height for visual harmony. The progression from xs to 4xl maintains consistent visual weight relative to line length. Never use line-height alone; always pair with appropriate font-size.
Color Profiles
Six complete worlds
Six color systems, each with light and dark variants, all WCAG 2.1 AA certified. Switch profiles at runtime with no rebuild required.
Available profiles
| Class | Value / Derivation | CSS output |
|---|---|---|
| ocean | Cool periwinkle to deep indigo | data-profile="ocean" |
| earth | Warm parchment to deep soil | data-profile="earth" |
| twilight | Soft periwinkle to inky indigo | data-profile="twilight" |
| fire | Soft cream to deep red-brown | data-profile="fire" |
| void | Cool near-black to deep navy | data-profile="void" |
| leaf | Light sage to forest green | data-profile="leaf" |
Semantic color tokens
All colors are semantic — they adapt to the active profile and dark mode automatically.
| Class | Value / Derivation | CSS output |
|---|---|---|
| --renge-color-bg | Document background | Adapts to profile + mode |
| --renge-color-bg-subtle | Subtle background layer | Slightly elevated from bg |
| --renge-color-bg-muted | Muted background | Further elevated |
| --renge-color-fg | Foreground (text) | Primary text color |
| --renge-color-fg-subtle | Subtle foreground | Secondary text |
| --renge-color-fg-muted | Muted foreground | Tertiary text |
| --renge-color-accent | Primary accent | CTA, highlights |
| --renge-color-accent-hover | Hover state accent | Darkened accent |
| --renge-color-border | Border color | Default border |
| --renge-color-border-subtle | Subtle border | Minimal emphasis |
| --renge-color-border-focus | Focus ring color | Keyboard focus |
| --renge-color-success | Success status | WCAG AA compliant |
| --renge-color-warning | Warning status | WCAG AA compliant |
| --renge-color-danger | Danger/error status | WCAG AA compliant |
Usage example
<!-- HTML: Set profile on root element -->
<html data-profile="ocean" data-mode="light">
...
</html>
/* All colors reference the active profile */
.card {
background: var(--renge-color-bg-subtle);
border: 1px solid var(--renge-color-border-subtle);
color: var(--renge-color-fg);
}
.button {
background: var(--renge-color-accent);
color: var(--renge-color-fg-inverse);
}
.button:hover {
background: var(--renge-color-accent-hover);
}
/* Switch profiles at runtime (no rebuild) */
<script>
document.documentElement.dataset.profile = "twilight";
document.documentElement.dataset.mode = "dark";
</script>
/* Tailwind: bg-renge-bg, text-renge-fg, border-renge-border, etc. */
<div class="bg-renge-bg-subtle border border-renge-border-subtle p-renge-4">
<p class="text-renge-fg">Content</p>
<button class="bg-renge-accent text-renge-fg-inverse">Action</button>
</div>Border Radius
Fibonacci scale
Five radius values (plus full pill radius) derived from Fibonacci × base unit. Used for cards, buttons, inputs, and other rounded elements.
| Class | Value / Derivation | CSS output |
|---|---|---|
| --renge-radius-0 | 0px | Sharp corners |
| --renge-radius-1 | 4px | Subtle rounding (1 × 4) |
| --renge-radius-2 | 8px | Buttons, inputs (2 × 4) |
| --renge-radius-3 | 12px | Cards, surfaces (3 × 4) |
| --renge-radius-4 | 20px | Large surfaces (5 × 4) |
| --renge-radius-5 | 32px | XL surfaces (8 × 4) |
| --renge-radius-full | 9999px | Pill shape, circles |
Usage example
/* Button: subtle rounding */
button {
border-radius: var(--renge-radius-2); /* 8px */
}
/* Card: more prominent rounding */
.card {
border-radius: var(--renge-radius-3); /* 12px */
}
/* Badge or pill */
.badge {
border-radius: var(--renge-radius-full);
}
/* Avatar circle */
img {
border-radius: 50%; /* or var(--renge-radius-full) for square images */
}
/* Tailwind: rounded-renge-1, rounded-renge-2, rounded-renge-full */
<button class="rounded-renge-2">Button</button>
<div class="rounded-renge-3">Card</div>
<div class="rounded-renge-full">Pill</div>Z-Index
Stacking context
Semantic z-index values that prevent stacking conflicts. Each tier is for a specific UI layer.
| Class | Value / Derivation | CSS output |
|---|---|---|
| --renge-z-dropdown | 100 | Select, datalist, popover |
| --renge-z-sticky | 200 | Sticky headers, scroll-fix elements |
| --renge-z-fixed | 300 | Fixed nav, sidebars |
| --renge-z-modal | 400 | Modal backdrop + dialog |
| --renge-z-toast | 500 | Toast notifications (topmost) |
Usage example
/* Dropdown menu */
.dropdown {
position: absolute;
z-index: var(--renge-z-dropdown); /* 100 */
}
/* Sticky navbar */
nav {
position: sticky;
z-index: var(--renge-z-sticky); /* 200 */
}
/* Fixed sidebar */
aside {
position: fixed;
z-index: var(--renge-z-fixed); /* 300 */
}
/* Modal backdrop */
.modal-backdrop {
z-index: var(--renge-z-modal); /* 400 */
}
.modal-dialog {
z-index: calc(var(--renge-z-modal) + 1); /* 401 */
}
/* Toast notification */
.toast {
position: fixed;
z-index: var(--renge-z-toast); /* 500 */
}Motion
Duration and easing
Fibonacci-based durations (100–5500ms) and 10+ easing curves. Create consistent, natural-feeling animations.
Duration scale (Fibonacci × 100ms)
| Class | Value / Derivation | CSS output |
|---|---|---|
| --renge-duration-1 | 100ms | Snappy microinteractions |
| --renge-duration-2 | 100ms | Quick feedback |
| --renge-duration-3 | 200ms | Standard transitions |
| --renge-duration-4 | 300ms | Deliberate animations |
| --renge-duration-5 | 500ms | Slower, layered effects |
| --renge-duration-6 | 800ms | Extended motion |
| --renge-duration-7 | 1300ms | Long sequences |
| --renge-duration-8 | 2100ms | Extended sequences |
| --renge-duration-9 | 3400ms | Very long motion |
| --renge-duration-10 | 5500ms | Languorous effects |
Easing curves
| Class | Value / Derivation | CSS output |
|---|---|---|
| --renge-easing-linear | linear | No acceleration |
| --renge-easing-ease-in | cubic-bezier(0.618, 0, 1, 1) | Slow start |
| --renge-easing-ease-out | cubic-bezier(0, 0, 0.382, 1) | Slow end |
| --renge-easing-ease-in-out | cubic-bezier(0.618, 0, 0.382, 1) | Both |
| --renge-easing-spring | cubic-bezier(0.34, 1.56, 0.64, 1) | Springy overshoot |
| --renge-easing-bounce | cubic-bezier(0.68, -0.55, 0.265, 1.55) | Bouncy |
| --renge-easing-back-in | cubic-bezier(0.6, -0.28, 0.735, 0.045) | Pull back entrance |
| --renge-easing-back-out | cubic-bezier(0.175, 0.885, 0.32, 1.275) | Pull back exit |
| --renge-easing-elastic-in | cubic-bezier(0.68, -0.55, 0.265, 1.55) | Elastic entrance |
| --renge-easing-elastic-out | cubic-bezier(0.68, -0.55, 0.265, 1.55) | Elastic exit |
Usage example
/* Button hover — quick and snappy */
button {
transition: background-color var(--renge-duration-2) var(--renge-easing-ease-out);
}
/* Smooth color transition */
.card {
transition: all var(--renge-duration-3) var(--renge-easing-ease-in-out);
}
/* Animated entrance */
.modal {
animation: slideIn var(--renge-duration-4) var(--renge-easing-ease-out);
}
/* Springy, playful interaction */
.button:active {
animation: bounce var(--renge-duration-3) var(--renge-easing-spring);
}
/* Tailwind: duration-renge-2, ease-renge-ease-out, etc. */
<button class="transition-colors duration-renge-2 ease-renge-ease-out hover:bg-renge-accent">
Hover me
</button>Other Categories
Complete reference
Additional token categories for shadows, dimensions, and layout constraints.
Shadows & Elevation
10 elevation levels with WCAG-compliant opacity. Higher values create stronger depth perception.
/* 10 shadow levels */
--renge-shadow-1: 0 1px 2px rgba(0,0,0,0.05);
--renge-shadow-2: 0 2px 4px rgba(0,0,0,0.08);
/* ... through ... */
--renge-shadow-10: 0 20px 25px rgba(0,0,0,0.2);
/* Usage */
.elevated {
box-shadow: var(--renge-shadow-5);
}
.card {
box-shadow: var(--renge-shadow-3);
}
.modal-backdrop {
box-shadow: var(--renge-shadow-8);
}Dimensions (Width & Height)
Fixed sizes for common UI elements. Fibonacci-based progression.
/* Avatar size */
--renge-size-avatar-sm: 24px;
--renge-size-avatar: 32px;
--renge-size-avatar-lg: 52px;
/* Icon sizes */
--renge-size-icon-sm: 16px;
--renge-size-icon: 20px;
--renge-size-icon-lg: 24px;
/* Usage */
.avatar {
width: var(--renge-size-avatar);
height: var(--renge-size-avatar);
}
img.icon {
width: var(--renge-size-icon);
}Container (Max-width breakpoints)
5 max-width values for responsive containers. Derived from φ⁴ progression.
| Class | Value / Derivation | CSS output |
|---|---|---|
| --renge-container-sm | 524px | φ² × 200 |
| --renge-container-md | 847px | φ³ × 200 |
| --renge-container-lg | 1371px | φ⁴ × 200 |
| --renge-container-xl | 2218px | φ⁵ × 200 |
Integration
Works everywhere.
Tokens integrate with React, Vue, Svelte, or vanilla JavaScript.
React
Use useRengeTheme() hook or RengeProvider wrapper for dynamic theme switching.
import { RengeProvider, useRengeTheme } from '@renge-ui/react';
function App() {
return (
<RengeProvider config={{ profile: 'ocean' }}>
<ThemeSwitcher />
</RengeProvider>
);
}
function ThemeSwitcher() {
const { profile, switchProfile } = useRengeTheme();
return (
<button onClick={() => switchProfile('twilight')}>
Switch to Twilight
</button>
);
}Vue 3
Access profile/mode via useRengeTheme() composable.
import { useRengeTheme } from '@renge-ui/vue';
export default {
setup() {
const { profile, mode, switchProfile } = useRengeTheme();
return { profile, mode, switchProfile };
}
};Svelte
Reactive stores for theme management.
import { profile, mode, switchProfile } from '@renge-ui/svelte';
<button on:click={() => switchProfile('earth')}>
Switch to Earth (currently: {$profile})
</button>