@renge-ui/react

Components

18 components built on the token system. Proportional. Accessible. Composable. No class names — every style references a Renge CSS variable.

pnpm add @renge-ui/tokens @renge-ui/react
forwardRefinline stylesCSS custom propertiesno class namesprofile-reactive

Stack

Flexbox container. Composes vertical and horizontal layouts using Fibonacci spacing tokens.

Vertical (default)

Item 1
Item 2
Item 3

Horizontal + justify between

LeftCenterRight

Horizontal + align center

<Stack gap="4">
  <div>First</div>
  <div>Second</div>
  <div>Third</div>
</Stack>

<Stack direction="horizontal" justify="between">
  <Text>Left</Text>
  <Text>Right</Text>
</Stack>

{/* Flex wrap via style prop */}
<Stack direction="horizontal" gap="3" style={{ flexWrap: "wrap" }}>
  <Badge>one</Badge>
  <Badge>two</Badge>
  <Badge>three</Badge>
</Stack>
PropTypeDefaultDescription
gap"0" – "10""3"Gap between children — Fibonacci spacing step (e.g. step 4 = 20px).
direction"vertical" | "horizontal""vertical"flex-direction: column or row.
align"start" | "center" | "end" | "stretch""stretch"align-items value.
justify"start" | "center" | "end" | "between" | "around""start"justify-content value.
asElementType"div"Rendered HTML element (div, ul, nav, etc.).

Grid

CSS grid container with Fibonacci gap tokens. Accepts a number of equal columns or a custom template string.

3-column equal grid

1
2
3
4
5
6

Golden ratio split (1fr 1.618fr)

1
φ
<Grid columns={3} gap="3">
  <div>1</div>
  <div>2</div>
  <div>3</div>
</Grid>

{/* Custom template — e.g. golden ratio split */}
<Grid columns="1fr 1.618fr" gap="4">
  <div>Narrow</div>
  <div>Wide (φ)</div>
</Grid>

{/* Per-axis gaps */}
<Grid columns={2} gapX="5" gapY="3">
  ...
</Grid>
PropTypeDefaultDescription
columnsnumber | string1Number of equal columns, or a CSS grid-template-columns string.
rowsnumber | stringRow count or grid-template-rows string.
gap"0" – "6""3"Gap between all cells.
gapX"0" – "6"Column gap — overrides gap.
gapY"0" – "6"Row gap — overrides gap.
align"start" | "center" | "end" | "stretch""stretch"align-items value.
justify"start" | "center" | "end" | "stretch""stretch"justify-items value.

Section

Page section wrapper with max-width constraint and automatic horizontal centering.

Centered with md max-width

maxWidth="md" — 768px, centered
<Section maxWidth="lg" paddingY="8" paddingX="5">
  <Heading>Page content</Heading>
  <Text>Body copy sits inside the max-width container.</Text>
</Section>

{/* Full-bleed with internal constraint */}
<div style={{ background: "var(--renge-color-bg-subtle)" }}>
  <Section maxWidth="xl" paddingY="7">
    <Heading>Wide section</Heading>
  </Section>
</div>
PropTypeDefaultDescription
maxWidth"sm" | "md" | "lg" | "xl" | "full" | "none""lg"sm=640px · md=768px · lg=1024px · xl=1280px · full=100% · none=unset.
paddingX"0" – "8""4"Horizontal padding.
paddingY"0" – "8""6"Vertical padding.
padding"0" – "8"Sets both axes at once. Overrides paddingX and paddingY.
centerbooleantrueApplies margin-inline: auto to center the container.
animationAnimationNameRenge animation token.
asElementType"section"Rendered HTML element.

Heading

Semantic heading using the PHI-derived type scale. Level maps to h1–h6 and sets a proportional default size.

Levels 1–4 with default sizing

Level 1 heading

h13xl

Level 2 heading

h22xl

Level 3 heading

h3xl

Level 4 heading

h4lg

Color variants

Default — var(--renge-color-fg)

Subtle — var(--renge-color-fg-subtle)

Accent — var(--renge-color-accent)

<Heading level={1}>The golden ratio.</Heading>
<Heading level={2} color="accent">Section title</Heading>

{/* Override the default size for a level */}
<Heading level={3} size="2xl">Larger h3</Heading>

{/* PHI-derived line heights apply automatically */}
{/* h1/h2 → display (1.236), h3/h4 → heading (1.382) */}
PropTypeDefaultDescription
level1 | 2 | 3 | 4 | 5 | 62Semantic HTML level (h1–h6). Also sets the default size.
size"lg" | "xl" | "2xl" | "3xl" | "4xl"level-mappedOverride the default size. h1→3xl, h2→2xl, h3→xl, h4/5/6→lg.
color"fg" | "fg-subtle" | "accent""fg"Text color semantic token.
animationAnimationNameRenge animation token.

Text

Inline or block text element with full access to the PHI type scale, color tokens, and weight options.

Size scale

The ratio that appears in every living thing.2xl
The ratio that appears in every living thing.xl
The ratio that appears in every living thing.lg
The ratio that appears in every living thing.base
The ratio that appears in every living thing.sm
The ratio that appears in every living thing.xs

Colors + weights

fgfg-subtlefg-mutedaccentsuccesswarningdanger
weight="normal"weight="medium"weight="semibold"weight="bold"
<Text size="lg" color="fg-subtle">Natural proportion.</Text>
<Text as="p" weight="medium" size="base">
  Fibonacci spacing.
</Text>
<Text size="xs" color="accent" weight="semibold">
  PHI = 1.618033...
</Text>

{/* Block-level text */}
<Text as="p" size="base" color="fg-subtle">
  Paragraph text using the base size — 16px, line-height 1.618 (φ).
</Text>
PropTypeDefaultDescription
size"xs" | "sm" | "base" | "lg" | "xl" | "2xl" | "3xl" | "4xl""base"Font size token. Steps derived from PHI: base × φ^n.
color"fg" | "fg-subtle" | "fg-muted" | "accent" | "success" | "warning" | "danger""fg"Text color semantic token.
weight"normal" | "medium" | "semibold" | "bold""normal"Font weight: 400 / 500 / 600 / 700.
align"left" | "center" | "right"Text alignment.
animationAnimationNameRenge animation token.
asElementType"span"Rendered HTML element.

Divider

Horizontal or vertical rule rendered as an <hr>. Uses border color tokens for consistent visual weight.

Horizontal variants

Above — default (border-subtle)
Between sections
Below — stronger border, tighter spacing

Vertical

Left content
Right content
<Divider />
<Divider color="border" spacing="2" />
<Divider orientation="vertical" spacing="4" />
PropTypeDefaultDescription
orientation"horizontal" | "vertical""horizontal"Horizontal: 1px height, full width. Vertical: 1px width, full height.
spacing"0" – "6""3"Margin around the rule (marginBlock or marginInline).
color"border" | "border-subtle""border-subtle"Line color token.

Button

Action element. Every variant, size, and color combination resolves to a CSS variable — no hardcoded values.

Variants

Sizes

Color schemes

Full width + disabled

<Button variant="solid" size="md" colorScheme="accent">
  Continue
</Button>

<Button variant="outline" colorScheme="danger" size="sm">
  Delete
</Button>

<Button variant="ghost" colorScheme="success">
  Confirm
</Button>

{/* Disabled state — native HTML attribute */}
<Button disabled style={{ opacity: 0.4, cursor: "not-allowed" }}>
  Unavailable
</Button>

{/* Extends all native button props */}
<Button onClick={handleSubmit} type="submit" fullWidth>
  Submit form
</Button>
PropTypeDefaultDescription
variant"solid" | "outline" | "ghost""solid"Solid fills with colorScheme bg, outline shows border, ghost is text-only.
size"sm" | "md" | "lg""md"sm: space-1/2 · md: space-2/4 · lg: space-3/5 padding.
colorScheme"accent" | "danger" | "success""accent"Which semantic color set to apply across all variants.
fullWidthbooleanfalseStretches button to 100% container width.
animationAnimationNameRenge animation token applied as CSS animation.
disabledbooleanNative HTML attribute — style opacity via style prop.

Input

Text input with Renge sizing and validation state styling. Focus ring is handled with inline event handlers to stay in-system.

States

Sizes

<Input placeholder="Enter value" size="md" />
<Input state="error" placeholder="Invalid input" fullWidth />
<Input state="success" defaultValue="Confirmed" fullWidth />

{/* Controlled */}
<Input
  value={value}
  onChange={(e) => setValue(e.target.value)}
  placeholder="Controlled input"
  fullWidth
/>
The native HTML size attribute (a number controlling character width) is excluded to avoid collision with Renge's size prop. Use style={{ width: "..." }} or fullWidth for sizing.
PropTypeDefaultDescription
size"sm" | "md" | "lg""md"Controls padding and font size.
state"default" | "error" | "success""default"Sets border color to the corresponding semantic token.
fullWidthbooleanfalseStretches input to 100% container width.

FormField

Wraps any input with a label, optional helper text, and error text. Error overrides helper when both are present.

States

We'll never share your email.
Username is already taken.
Read-only. Regenerate from settings.
<FormField
  label="Email"
  htmlFor="email"
  helperText="We'll never share this."
>
  <Input id="email" type="email" fullWidth />
</FormField>

<FormField
  label="Username"
  htmlFor="username"
  required
  errorText="Username already taken."
>
  <Input id="username" state="error" fullWidth />
</FormField>
PropTypeDefaultDescription
labelstringLabel text rendered in a <label> element.
htmlForstringLinks the label to an input via its id.
helperTextstringMuted hint text below the input.
errorTextstringDanger-colored error text. Overrides helperText when both are set.
requiredbooleanAppends a red asterisk to the label.

Card

Surface container with three visual variants. Padding and radius are token-driven.

Variants

ElevatedShadow on bg
OutlinedBorder visible
Filledbg-subtle surface

Padding scale

padding="2"
padding="4"
padding="6"
<Card variant="elevated" padding="5" radius="3">
  <Heading level={3}>Card title</Heading>
  <Text color="fg-subtle">Supporting copy goes here.</Text>
</Card>

<Card variant="outlined" padding="4">
  <Stack gap="3">
    <Badge variant="success">Active</Badge>
    <Heading level={3}>Status card</Heading>
  </Stack>
</Card>
PropTypeDefaultDescription
variant"elevated" | "outlined" | "filled""elevated"elevated: drop shadow · outlined: border · filled: bg-subtle background.
padding"0" – "6""4"Internal padding using Fibonacci spacing tokens.
radius"none" | "1" – "5" | "full""3"Border radius token (radius-3 = 12px by default).
animationAnimationNameRenge animation token.

Badge

Compact inline label for status, category, or count. Six semantic variants map directly to the color token system.

Variants

neutralaccentsuccesswarningdangerinfo

Sizes

sm — compactmd — defaultlg — prominent
<Badge variant="success">Published</Badge>
<Badge variant="warning" size="sm">Beta</Badge>
<Badge variant="danger">Deprecated</Badge>
<Badge variant="info">New</Badge>
<Badge variant="accent" size="lg">Featured</Badge>
PropTypeDefaultDescription
variant"neutral" | "accent" | "success" | "warning" | "danger" | "info""neutral"Determines background and text color via semantic token pairs (e.g. success-subtle + success).
size"sm" | "md" | "lg""md"Controls padding and font size.

Chip

Dismissible tag with the same semantic color variants as Badge. Provide onDismiss to render a close button.

Variants

neutralaccentsuccesswarningdanger

Dismissible (live demo)

Design systemPHIFibonacciProportional
{/* Static */}
<Chip variant="accent">Design system</Chip>

{/* Dismissible */}
<Chip variant="neutral" onDismiss={() => removeTag(id)}>
  Removable
</Chip>

{/* Dynamic tag list */}
{tags.map(tag => (
  <Chip
    key={tag.id}
    variant="accent"
    onDismiss={() => removeTag(tag.id)}
  >
    {tag.label}
  </Chip>
))}
PropTypeDefaultDescription
variant"neutral" | "accent" | "success" | "warning" | "danger" | "info""neutral"Color semantic — same token mapping as Badge.
onDismiss() => voidWhen provided, renders a × button. Call your own state removal logic here.

Avatar

User avatar with image or initials fallback. Sizes follow the Fibonacci sequence × 4px.

Sizes — Fibonacci × 4px

RG
20px
RG
32px
RG
52px
RG
84px
RG
136px

Shapes + image

PH
circle
FB
square
Renge
image
{/* Initials fallback */}
<Avatar initials="RG" size="3" />

{/* Image with initials fallback */}
<Avatar
  src="/user.jpg"
  alt="Profile photo"
  initials="RG"
  size="4"
/>

{/* Square shape */}
<Avatar initials="FB" shape="square" size="3" />
Avatar sizes are Fibonacci numbers × 4px: 20 · 32 · 52 · 84 · 136. Consecutive ratios converge toward φ — each size is ≈1.618× the previous.
PropTypeDefaultDescription
srcstringImage URL. Takes priority over initials if provided.
altstringImage alt text and aria-label for the avatar.
initialsstringUp to 2 characters, displayed when src is absent or fails to load.
size"1" | "2" | "3" | "4" | "5""3"20 / 32 / 52 / 84 / 136 px — Fibonacci[3–7] × 4.
shape"circle" | "square""circle"circle: full border-radius · square: radius-3 (12px).

Stat

Key metric display. Trend badges are color-coded via success/danger tokens. Value renders at 3xl — designed to be read at a glance.

Metrics

Golden ratio
φ
PHI (exact)
1.618
(1 + √5) / 2
Fibonacci step 10
89 +34
from step 9 (55)
Duration 4
13ms -2ms
vs last build
Tests passing
106 +1
<Stat value="φ" label="Golden ratio" />

<Stat
  value="89"
  label="Fibonacci step"
  trend="up"
  trendValue="+34"
  caption="from step 9"
/>

<Stat
  value="0ms"
  label="Build time delta"
  trend="neutral"
  trendValue="no change"
/>
PropTypeDefaultDescription
valuestring | numberPrimary metric — rendered at font-size-3xl.
labelstringSmall label above the value.
trend"up" | "down" | "neutral"up=success · down=danger · neutral=fg-muted. Requires trendValue to render the badge.
trendValuestringChange amount shown in the trend badge (e.g. '+34', '-2ms').
captionstringMuted caption rendered below the value row.

Alert

Contextual banner with left-border accent and semantic status. Renders with role="alert" for screen reader compatibility.

All statuses

PHI is irrationalThe golden ratio cannot be expressed as a simple fraction.
Build succeededAll 106 tests passed. Zero regressions.
High varianceVariance above 0.1 may affect visual consistency across themes.
Token not found--renge-color-unknown is undefined in this profile.

Without title

Informational message without a title.
Variance is set to 0.08 — slight organic drift is active.
<Alert status="info" title="Note">
  Informational context.
</Alert>

<Alert status="success" title="Deployed">
  Production build complete.
</Alert>

<Alert status="danger" title="Error">
  Something went wrong.
</Alert>

{/* No title — body only */}
<Alert status="warning">
  Approaching rate limit.
</Alert>
PropTypeDefaultDescription
status"info" | "success" | "warning" | "danger""info"Sets left-border color and background using semantic token pairs.
titlestringBold heading inside the alert. Optional — body renders alone if omitted.

Spinner

Animated loading indicator. The CSS keyframe (rengeSpinnerSpin) is injected once at module load — no runtime overhead per instance.

Sizes

sm · 16px
md · 24px
lg · 32px

Colors

accent
fg
fg-muted
<Spinner size="md" color="accent" label="Loading tokens" />
<Spinner size="sm" color="fg-muted" />

{/* In a button */}
<Button variant="outline" disabled>
  <Stack direction="horizontal" gap="2" align="center">
    <Spinner size="sm" color="accent" />
    <span>Saving...</span>
  </Stack>
</Button>
PropTypeDefaultDescription
size"sm" | "md" | "lg""md"16 / 24 / 32 px diameter.
color"accent" | "fg" | "fg-muted""accent"Spinner ring color token.
labelstring"Loading"aria-label for screen readers.

Progress

Linear progress bar. Value is clamped 0–100. Track and fill colors reference semantic tokens.

PHI-derived values

61.8% — 1/φ
38.2% — 1/φ²
80% — warning
20% — danger, no radius
<Progress value={61.8} color="accent" />
<Progress value={100} color="success" size="lg" />
<Progress value={30} color="danger" radius="none" />

{/* Controlled */}
<Progress
  value={uploadProgress}
  color="accent"
  size="md"
  label="Upload progress"
/>
PropTypeDefaultDescription
valuenumber0–100 fill percentage. Values outside range are clamped.
color"accent" | "success" | "warning" | "danger""accent"Fill color semantic token.
size"sm" | "md" | "lg""md"Track height: 4 / 8 / 12 px.
radius"none" | "full""full"Track border radius.
labelstringaria-label for accessibility.

Token API

@renge-ui/tokens exports two ways to consume tokens: createRengeTheme() for generating CSS, and rengeVars for typed CSS variable references.

Every component in this library references CSS custom properties — never hardcoded values. Switch profiles by swapping which theme block is injected. No component re-renders required.

createRengeTheme(config?)

Generates a complete token set from mathematical first principles. Returns CSS ready to inject and a JS vars map.

import { createRengeTheme } from "@renge-ui/tokens";

const theme = createRengeTheme({
  profile:    "ocean",   // 'ocean' | 'earth' | 'twilight' | 'fire' | 'void' | 'leaf'
  mode:       "light",   // 'light' | 'dark'
  baseUnit:   4,         // Spacing multiplier in px — try 6 for denser UIs
  typeBase:   16,        // Root font size in px
  scaleRatio: 1.618,     // Typography scale ratio (φ = golden ratio)
  variance:   0,         // 0–1 tolerance drift (0 = exact math, deterministic)
  selector:   ":root",   // CSS selector to wrap the variables in
});

// theme.css   — full :root { --renge-* ... } string, ready to inject
// theme.vars  — Record<string, string> of every --renge-* variable
// theme.config — resolved config with all defaults applied

rengeVars

A statically typed object of CSS variable references. No runtime dependency — use it anywhere you need a var(--renge-*) string with IDE autocomplete.

import { rengeVars } from "@renge-ui/tokens";

// Color (22 semantic tokens, profile-reactive)
rengeVars.color.bg            // "var(--renge-color-bg)"
rengeVars.color.bgSubtle      // "var(--renge-color-bg-subtle)"
rengeVars.color.fg            // "var(--renge-color-fg)"
rengeVars.color.accent        // "var(--renge-color-accent)"
rengeVars.color.danger        // "var(--renge-color-danger)"
rengeVars.color.borderFocus   // "var(--renge-color-border-focus)"

// Spacing (Fibonacci × baseUnit, steps 0–10)
rengeVars.space[0]   // "var(--renge-space-0)"  → 0px
rengeVars.space[3]   // "var(--renge-space-3)"  → 12px (Fib[3] × 4)
rengeVars.space[5]   // "var(--renge-space-5)"  → 32px

// Typography (PHI scale, 8 steps)
rengeVars.fontSize.base  // "var(--renge-font-size-base)"
rengeVars.fontSize.lg    // "var(--renge-font-size-lg)"
rengeVars.lineHeight.base // "var(--renge-line-height-base)"

// Motion (Fibonacci × 100ms, steps 0–9)
rengeVars.duration[2]    // "var(--renge-duration-2)"  → 200ms
rengeVars.duration[5]    // "var(--renge-duration-5)"  → 800ms
rengeVars.easing.out     // "var(--renge-easing-ease-out)"
rengeVars.easing.spring  // "var(--renge-easing-spring)"

// Radius (Fibonacci × baseUnit, steps none/1–5/full)
rengeVars.radius[2]      // "var(--renge-radius-2)"   → 8px
rengeVars.radius.full    // "var(--renge-radius-full)" → pill

Integrating with another system

Use rengeVars to map Renge tokens to your own CSS variable names. This is the recommended pattern for adopting Renge alongside an existing design system.

import { createRengeTheme, rengeVars } from "@renge-ui/tokens";

const theme = createRengeTheme({ profile: "earth", mode: "light" });

// Map semantic Renge tokens → your system's variable names
const aliases: [string, string][] = [
  // Backgrounds
  ["--color-bg-primary",   rengeVars.color.bg],
  ["--color-bg-secondary", rengeVars.color.bgSubtle],
  ["--color-surface",      rengeVars.color.bgMuted],
  // Foreground
  ["--color-text",         rengeVars.color.fg],
  ["--color-text-muted",   rengeVars.color.fgSubtle],
  // Interactive
  ["--color-primary",      rengeVars.color.accent],
  ["--color-primary-hover",rengeVars.color.accentHover],
  // Status
  ["--color-error",        rengeVars.color.danger],
  ["--color-success",      rengeVars.color.success],
  ["--color-warning",      rengeVars.color.warning],
  // Spacing bridge
  ["--space-sm",           rengeVars.space[2]],
  ["--space-md",           rengeVars.space[4]],
  ["--space-lg",           rengeVars.space[5]],
];

const aliasCSS = `:root {
${aliases.map(([k, v]) => `  ${k}: ${v};`).join("\n")}
}`;

// Inject Renge base vars first, then your aliases on top
document.head.insertAdjacentHTML("beforeend",
  `<style>${theme.css}\n${aliasCSS}</style>`
);

All 22 semantic color tokens

rengeVars keyCSS variableRole
color.bg--renge-color-bgPage background
color.bgSubtle--renge-color-bg-subtleSlightly elevated surface
color.bgMuted--renge-color-bg-mutedMuted surface
color.bgInverse--renge-color-bg-inverseInverted background
color.fg--renge-color-fgPrimary text
color.fgSubtle--renge-color-fg-subtleSecondary text
color.fgMuted--renge-color-fg-mutedPlaceholder / disabled
color.fgInverse--renge-color-fg-inverseText on inverse bg
color.border--renge-color-borderDefault divider
color.borderSubtle--renge-color-border-subtleHairline divider
color.borderFocus--renge-color-border-focusKeyboard focus ring
color.accent--renge-color-accentPrimary interactive
color.accentHover--renge-color-accent-hoverHover state
color.accentSubtle--renge-color-accent-subtleTinted background
color.success--renge-color-successPositive outcome
color.successSubtle--renge-color-success-subtleSuccess tint bg
color.warning--renge-color-warningCaution
color.warningSubtle--renge-color-warning-subtleWarning tint bg
color.danger--renge-color-dangerError / destructive
color.dangerSubtle--renge-color-danger-subtleDanger tint bg
color.info--renge-color-infoInformational
color.infoSubtle--renge-color-info-subtleInfo tint bg

Animations

15 named animations derived from the token system. Apply via the animation prop on any component that accepts it.

Available tokens

vortex-reveal
helix-rise
sacred-fade
spiral-in
morph-fade-in
bloom
pulse
vibrate
wave
breathe
fall
float
float-wave
pulse-color-shift
swelling

Live examples

breathe

floatpulse
bloom
{/* On any component that accepts animation prop */}
<Heading level={2} animation="breathe">
  Living proportion.
</Heading>

<Badge variant="accent" animation="pulse">
  New
</Badge>

<Card animation="bloom">
  <Text>Enters with bloom effect</Text>
</Card>

{/* Via CSS variable directly */}
<div style={{ animation: "var(--renge-animation-float)" }}>
  Floats gently.
</div>
Animation CSS variables are injected into the document by createRengeTheme(). All 15 @keyframes blocks are included in the theme output — no separate import needed. Durations reference Fibonacci-derived --renge-duration-* tokens.

Patterns

Common composition patterns using @renge-ui/react components.

Status card

Build status

Passing
Tests106 / 106

Last run 2 minutes ago

Form with validation

Used for login and notifications.
Must be at least 12 characters.

Metric grid

Scale ratio
φ
Fibonacci 10
89 +34
Tests
106 +1
{/* Every component uses only CSS custom properties */}
{/* Switch profiles and all colors update instantly */}
import { createRengeTheme } from "@renge-ui/tokens";

const theme = createRengeTheme({ profile: "twilight" });
// Inject theme.css and all components adapt — no re-render.
All 18 components use only var(--renge-*) CSS custom properties. Switch color profiles by injecting a new theme block — no component re-renders required.
Scale6.0