Colors v2
A tiered color system for meaning and tone.
Revel's design system uses a two-tier color architecture. Primitive colors hold the raw hex values for each scale, and semantic tokens map those primitives to roles like surface, text, border, and icon. Components consume only the semantic tokens, so swapping a theme or rebalancing a palette never requires touching component code.
Principles
Intentional
Employ color carefully and strategically to convey important information and focus the eye. By using color judiciously, we create a system that can be used for long periods of time without causing visual exhaustion.
Color roles
Revel's palette is split into six roles — surface, text, primary, status, borders, and icons. Each role exposes a small set of variants (base, hover, muted, inverse, etc.) so the system stays predictable across components.
Derivative
Semantic tokens reference primitives instead of holding raw hex values. This keeps related shades in sync — changing one primitive re-paints every surface that derives from it without hunting for hard-coded values.
Accessible
Status and text combinations are tuned to meet WCAG 2.1 AA (4.5:1 for body text, 3:1 for large text). The dark theme rebinds the lightness end of each scale so contrast stays consistent in both modes.
The two tiers
| Tier | Prefix | Example |
|---|---|---|
| Primitive | --r-color-{family}-{step} | --r-color-neutral-100 |
| Semantic | --r-{role}[-variant] | --r-surface-hover |
The dark theme rebinds every semantic token to a different primitive — components never need to know which mode they're in.
Primitives
The raw color scales semantic tokens draw from. The slate-tinted neutral ramp powers every background, surface, text, border, and icon token — extra 150 / 250 / 350 / 650 / 750 / 850 steps give the dark end enough granularity for layered dark-mode surfaces. Primary is the brand ramp (500 anchors the light theme, 400 anchors the dark theme). The four status ramps map to success (green), warning (amber), danger (red), and info (sky). Hover any chip to reveal its token name and hex.
--r-color-neutral-0#FFFFFF--r-color-neutral-50#F8FAFC--r-color-neutral-100#F1F5F9--r-color-neutral-150#E8EDF4--r-color-neutral-200#E0E6EF--r-color-neutral-250#D7DEE8--r-color-neutral-300#CBD5E1--r-color-neutral-350#AFBCCC--r-color-neutral-400#94A3B8--r-color-neutral-500#64748B--r-color-neutral-600#475569--r-color-neutral-650#3D4A5F--r-color-neutral-700#334155--r-color-neutral-750#28344A--r-color-neutral-800#182137--r-color-neutral-850#0C1424--r-color-neutral-900#020617--r-color-primary-50#E1EBFF--r-color-primary-100#A5C6FF--r-color-primary-200#76A0FF--r-color-primary-300#4878EE--r-color-primary-400#2A55E4--r-color-primary-500#0044D4--r-color-primary-600#0036AA--r-color-primary-700#00297F--r-color-primary-800#001B55--r-color-primary-900#000D2A--r-color-success-50#F0FDF4--r-color-success-100#DCFCE7--r-color-success-200#BBF7D0--r-color-success-300#86EFAC--r-color-success-400#4ADE80--r-color-success-500#22C55E--r-color-success-600#16A34A--r-color-success-700#15803D--r-color-success-800#166534--r-color-success-900#052E16--r-color-warning-50#FFFBEB--r-color-warning-100#FEF3C7--r-color-warning-200#FDE68A--r-color-warning-300#FCD34D--r-color-warning-400#FBBF24--r-color-warning-500#F59E0B--r-color-warning-600#D97706--r-color-warning-700#B45309--r-color-warning-800#92400E--r-color-warning-900#451A03--r-color-danger-50#FEF2F2--r-color-danger-100#FEE2E2--r-color-danger-200#FECACA--r-color-danger-300#FCA5A5--r-color-danger-400#F87171--r-color-danger-500#EF4444--r-color-danger-600#DC2626--r-color-danger-700#B91C1C--r-color-danger-800#991B1B--r-color-danger-900#450A0A--r-color-info-50#F0F9FF--r-color-info-100#E0F2FE--r-color-info-200#BAE6FD--r-color-info-300#7DD3FC--r-color-info-400#38BDF8--r-color-info-500#0EA5E9--r-color-info-600#0284C7--r-color-info-700#0369A1--r-color-info-800#075985--r-color-info-900#082F49Color system
Surface
Surfaces are the primary UI elements employed in applications: pages, modals, tables, headers, and cards. They sit above the background and host content. Background tokens are documented alongside surface tokens because they share the same layering vocabulary.
--r-background--r-color-neutral-100#F1F5F9--r-background-hover--r-color-neutral-200#E0E6EF--r-surface--r-color-neutral-0#FFFFFF--r-surface-hover--r-color-neutral-100#F1F5F9--r-surface-selected--r-color-neutral-150#E8EDF4--r-surface-sunken--r-color-neutral-50#F8FAFC--r-surface-sunken-hover--r-color-neutral-150#E8EDF4--r-surface-sunken-selected--r-color-neutral-200#E0E6EF--r-surface-disabled--r-color-neutral-100#F1F5F9--r-surface-inverse--r-color-neutral-800#182137Text
Text tokens cover typography. Each variant is contrast-tested against the surface tokens it's expected to sit on.
--r-text--r-color-neutral-800#182137--r-text-muted--r-color-neutral-600#475569--r-text-disabled--r-color-neutral-500#64748B--r-text-placeholder--r-color-neutral-500#64748B--r-text-link--r-color-primary-500#0044D4--r-text-link-hover--r-color-primary-700#00297F--r-text-on-color--r-color-neutral-0#FFFFFF--r-text-primary--r-color-primary-500#0044D4Primary
Primary tokens anchor interactive elements: buttons, key icons, active navigation, and selected states.
--r-primary--r-color-primary-500#0044D4--r-primary-hover--r-color-primary-600#0036AA--r-primary-muted--r-color-primary-50#E1EBFFStatus
Each status family (success, warning, danger, info) ships with matched variants across surface, text, icon, and border, so a status concept can be expressed as a filled surface, a muted backdrop, body text, or a border without breaking visual relationships.
Success
Confirmations, completed actions, and healthy state.
--r-surface-success--r-color-success-700#15803D--r-surface-success-hover--r-color-success-800#166534--r-surface-success-muted--r-color-success-100#DCFCE7--r-text-success--r-color-success-800#166534--r-icon-success--r-color-success-800#166534--r-border-success--r-color-success-700#15803DWarning
Caution, attention required, and pending state.
--r-surface-warning--r-color-warning-700#B45309--r-surface-warning-hover--r-color-warning-800#92400E--r-surface-warning-muted--r-color-warning-100#FEF3C7--r-text-warning--r-color-warning-700#B45309--r-icon-warning--r-color-warning-700#B45309--r-border-warning--r-color-warning-700#B45309Danger
Errors, destructive actions, and blocked state.
--r-surface-danger--r-color-danger-600#DC2626--r-surface-danger-hover--r-color-danger-700#B91C1C--r-surface-danger-muted--r-color-danger-100#FEE2E2--r-text-danger--r-color-danger-700#B91C1C--r-icon-danger--r-color-danger-700#B91C1C--r-border-danger--r-color-danger-700#B91C1CInfo
Neutral notifications, tips, and informational state.
--r-surface-info--r-color-info-700#0369A1--r-surface-info-hover--r-color-info-800#075985--r-surface-info-muted--r-color-info-100#E0F2FE--r-text-info--r-color-info-800#075985--r-icon-info--r-color-info-800#075985--r-border-info--r-color-info-700#0369A1Borders
Borders outline component boundaries, divide regions of a layout, or signal a form control's interactive surface. The neutral family runs from muted (a soft divider) to stronger (the highest-contrast outline used by radios and checkboxes).
--r-border--r-color-neutral-250#D7DEE8--r-border-muted--r-color-neutral-150#E8EDF4--r-border-strong--r-color-neutral-350#AFBCCC--r-border-stronger--r-color-neutral-400#94A3B8--r-border-disabled--r-color-neutral-250#D7DEE8--r-border-inverse--r-color-neutral-900#020617--r-border-primary--r-color-primary-500#0044D4Status borders (--r-border-success, --r-border-warning, --r-border-danger, --r-border-info) are documented in Status.
Icons
Icons inherit color from a small set of tokens that mirror the text family. When an icon sits on top of a colored fill — a primary button or a status badge — use --r-icon-on-color instead of the default.
--r-icon--r-color-neutral-700#334155--r-icon-muted--r-color-neutral-500#64748B--r-icon-on-color--r-color-neutral-0#FFFFFF--r-icon-primary--r-color-primary-500#0044D4Status icons (--r-icon-success, --r-icon-warning, --r-icon-danger, --r-icon-info) are documented in Status.
Focus and overlay
Two additional semantic tokens sit outside the role families:
--r-focus—primary-400— outline ring for:focus-visiblestates.--r-overlay—neutral-900at 50% (#02061780) — modal and dialog scrim.