Starter Docs
UI

Theming

One file themes every Rabtx component. It uses shadcn/ui's token names, so a shadcn theme and the Rabtx theme are interchangeable.

The one file

Everything visual comes from packages/rabtx/src/styles/theme.css. It is laid out like a shadcn theme:

  • :root holds the light values and .dark the dark ones, as background / foreground pairs: --primary is a surface, --primary-foreground is the text and icons on it.
  • @theme inline maps every token into Tailwind, so bg-primary, text-muted-foreground, border-input and rounded-lg work and stay live when a variable changes.
  • --radius is the one corner radius. Tailwind's rounded-sm to rounded-4xl and the Rabtx radius tiers are derived from it.

Components read nothing else: no colors, radii or shadows are written into a component. Change a value in this file and the web app, these docs and every component installed from the registry follow.

Customising

The whole theme. Edit theme.css. To swap in a theme from the shadcn themes page or tweakcn, paste its :root and .dark blocks over the shadcn tokens; the Rabtx tokens below keep working.

Part of a page. Set tokens on any ancestor. Everything inside follows.

<section className="[--primary:var(--success)] [--radius:0.25rem]">
  <Button>Approve</Button>
</section>

One component. Pass Tailwind classes. Components put their own styles in the components layer, so your utilities win: <Button className="rounded-md">.

A subtree only. Add the class rabtx to apply the theme to one element and its children; it follows a .dark ancestor, or pin it with rabtx light or rabtx dark. The web app and this site use that to embed Rabtx next to their own themes.

In a shadcn project. Components from the registry read your existing shadcn theme. Add the Rabtx theme on top with npx shadcn@latest add @rabtx/theme; without it, the Rabtx-only tokens (status tones, field depth and the rest) are derived from your shadcn colors.

Why there are no per-component variables

Earlier versions had a layer of component variables (--rx-btn-primary-bg, --rx-select-panel and so on) on top of the tokens. They are gone: every component reads the semantic tokens directly, which is what makes one file restyle everything and lets a shadcn theme drop straight in. To change one component, set a semantic token on it or an ancestor, or pass classes. Each component page lists the tokens it reads under Theming.

Modes

Set on any ancestor, never as a component prop.

ModeValuesEffect
class="dark"present or notThe .dark values
data-depthfloating (default), flatflat drops the raised edges, sheens and shadows
data-radiussharp, default, roundOverrides the radius tiers
data-motionon (default), offoff stops every transition; reduced motion in the OS does too
data-sizesm, md (default), lgResizes the default control. An explicit size on one component still wins.
--motion-msa number of millisecondsOne duration for every spring. The curves stay.

The UI switch at the top of these pages sets theme, radius, primary color, size and --motion-ms on one canvas. Depth stays floating there.

Tokens

Read from theme.css when this page is built, with live swatches in light and dark.

Base

TokenLightDark
--radius
0.5rem
same

The control font (buttons, selects)

TokenLightDark
--font-sans
"SF Pro Text", "SF Pro", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter, sans-serif
same

shadcn semantic colors

TokenLightDark
--background
#ffffff
#161616
--foreground
#292929
#ebebeb
--card
#ffffff
#212121
--card-foreground
#292929
#ebebeb
--popover
#ffffff
#212121
--popover-foreground
#292929
#ebebeb
--primary
#2d7cf6
#2d7cf6
--primary-foreground
#ffffff
#ffffff
--secondary
#f5f5f5
#1d1d1d
--secondary-foreground
#292929
#ebebeb
--muted
#f2f2f2
#303030
--muted-foreground
#5d5d5d
#a3a3a3
--accent
rgb(41 41 41 / 0.06)
rgb(235 235 235 / 0.06)
--accent-foreground
#292929
#ebebeb
--destructive
#e5484d
#f0686d
--border
#f2f2f2
#303030
--input
#e3e3e3
#3d3d3d
--ring
#2d7cf6
#6aa4fa
--chart-1
#2d7cf6
#4a8ff7
--chart-2
#30a46c
#30a46c
--chart-3
#f0803c
#f0803c
--chart-4
#8e5cf0
#8e5cf0
--chart-5
#e5484d
#f0686d
--sidebar
#ffffff
#161616
--sidebar-foreground
#292929
#ebebeb
--sidebar-primary
#2d7cf6
#2d7cf6
--sidebar-primary-foreground
#ffffff
#ffffff
--sidebar-accent
rgb(41 41 41 / 0.06)
rgb(235 235 235 / 0.06)
--sidebar-accent-foreground
#292929
#ebebeb
--sidebar-border
#f2f2f2
#303030
--sidebar-ring
#2d7cf6
#6aa4fa

Rabtx

TokenLightDark
--subtle-foreground
#9e9e9e
#7f7f7f
--disabled-foreground
#a3a3a3
#5f5f5f

Rabtx

TokenLightDark
--success
#30a46c
#30a46c
--warning
#f0803c
#f0803c
--violet
#8e5cf0
#8e5cf0
--tint-ink
#000000
#ffffff

Rabtx depth

TokenLightDark
--field
#f5f5f5
#1b1b1b
--field-disabled
#fafafa
#161616
--field-edge-top
rgb(0 0 0 / 0.14)
rgb(0 0 0 / 0.55)
--field-edge-bottom
rgb(0 0 0 / 0.05)
rgb(255 255 255 / 0.07)
--field-shade
rgb(0 0 0 / 0.04)
rgb(0 0 0 / 0.25)

Rabtx depth

TokenLightDark
--surface-ring
rgb(0 0 0 / 0.1)
rgb(0 0 0 / 0.6)
--surface-edge-top
#ffffff
rgb(255 255 255 / 0.14)
--surface-edge-bottom
rgb(0 0 0 / 0.08)
rgb(0 0 0 / 0.4)
--surface-sheen
rgb(255 255 255 / 0.5)
rgb(255 255 255 / 0.05)
--surface-shade
rgb(0 0 0 / 0.03)
rgb(0 0 0 / 0.16)

Rabtx shadows.

TokenLightDark
--shadow-popover
0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)
same
--shadow-raised
0 8px 22px rgb(0 0 0 / 0.16)
same

Rabtx radius tiers, all derived from --radius, so Round never over-rounds a box and clips text

TokenLightDark
--radius-button
999px
same
--radius-item
var(--radius)
same
--radius-control
var(--radius)
same
--radius-box
calc(var(--radius) * 1.5)
same
--radius-badge
calc(var(--radius) * 0.5)
same
--radius-check
calc(var(--radius) * 0.5)
same

Rabtx motion

TokenLightDark
--motion-ease
cubic-bezier(0.25, 1, 0.5, 1)
same

Springs (generated from src/motion/springs.ts; each also has a -duration)

TokenLightDark
--spring-press
linear(…), 279ms
same
--spring-swap
linear(…), 432ms
same
--spring-check
linear(…), 306ms
same
--spring-label
linear(…), 244ms
same
--spring-magnetic
linear(…), 300ms
same
--spring-unfold
linear(…), 249ms
same
--spring-tabs
linear(…), 672ms
same
--spring-panel
linear(…), 520ms
same
--spring-toast
linear(…), 315ms
same
--spring-switch
linear(…), 527ms
same
--spring-glide
linear(…), 424ms
same
--spring-expand
linear(…), 891ms
same

On this page