Colors and themes
Choose theme-aware surface, content, action, and status roles before working with palette values.
Choose a semantic role
Start with meaning, not a color value.
- Surface: surface and muted surface establish neutral layers. Hover, selected, and pressed add Rack Blue only when interaction needs emphasis.
- Content: text, muted text, placeholder, border, and inverse roles keep foregrounds tied to their context.
- Action: primary, hover, pressed, and on-primary form one action set.
- Status: info, success, warning, and danger each provide content, surface, interaction, border, and on-color roles.
Theme structure
Set data-theme="tinyrack-light" or data-theme="tinyrack-dark" on an ancestor. Both selectors define the same semantic variables, so descendants keep their intent when the theme changes.
<html data-theme="tinyrack-light">
Use resting, hover, and pressed roles as a set. Do not derive dark colors from the light theme or use a foreground on an unrelated fill.
Dark-theme resting boundaries use Neutral 800 #262626 for border, controlBorder, and controlTrack. Hovered, pressed, and dragged controls can use borderStrong at Neutral 700 #404040 for interaction emphasis. Both remain visually restrained and neither meets the WCAG 3:1 non-text contrast threshold against the default dark surface by itself. Keep focus, status, text, and surface cues intact when the boundary is essential.
Override the default action safely
Tinyrack uses Rack Blue for its default action. Add a separate product accent selector only when a product needs another identity. Override all four roles so rest, hover, pressed, and foreground contrast remain one contract.
[data-accent="product-violet"] {
--tinyrack-primary: #6d28d9;
--tinyrack-primary-hover: #5b21b6;
--tinyrack-primary-pressed: #4c1d95;
--tinyrack-on-primary: #ffffff;
}
<main data-theme="tinyrack-dark" data-accent="product-violet">
Misuse to avoid
- Do not use palette values directly in product UI; they do not adapt to themes.
- Do not use status colors only for decoration or interchange warning and danger.
- Do not override only
primary; incomplete state sets create inconsistent interaction feedback. - Do not place
on-*colors on a different background role.
Functional reference
| Role | Light | Dark |
|---|---|---|
surface | #ffffff | #0a0a0a |
surfaceMuted | #f5f5f5 | #171717 |
surfaceHover | #eff6ff | #172554 |
surfaceSelected | #dbeafe | #1e3a8a |
surfacePressed | #bfdbfe | #1e40af |
text | #171717 | #fafafa |
textMuted | #525252 | #a3a3a3 |
textPlaceholder | #737373 | #a3a3a3 |
border | #d4d4d4 | #262626 |
borderStrong | #a3a3a3 | #404040 |
controlBorder | #d4d4d4 | #262626 |
controlTrack | #d4d4d4 | #262626 |
focus | #2563eb | #60a5fa |
surfaceInverse | #171717 | #fafafa |
textInverse | #fafafa | #171717 |
borderInverse | #a3a3a3 | #737373 |
skeletonFill | #d4d4d4 | #404040 |
skeletonHighlight | #f5f5f5 | #525252 |
primary | #1d4ed8 | #60a5fa |
primaryHover | #1e40af | #93c5fd |
primaryPressed | #1e3a8a | #bfdbfe |
onPrimary | #ffffff | #172554 |
info | #1d4ed8 | #93c5fd |
infoHover | #1e40af | #bfdbfe |
infoPressed | #1e3a8a | #dbeafe |
infoSurface | #eff6ff | #172554 |
infoSurfaceSubtle | #eff6ff | #262d34 |
infoSurfaceHover | #dbeafe | #1e3a8a |
infoSurfacePressed | #bfdbfe | #1e40af |
infoBorder | #2563eb | #60a5fa |
onInfo | #ffffff | #172554 |
success | #15803d | #86efac |
successHover | #166534 | #bbf7d0 |
successPressed | #14532d | #dcfce7 |
successSurface | #f0fdf4 | #052e16 |
successSurfaceSubtle | #f0fdf4 | #25322a |
successSurfaceHover | #dcfce7 | #14532d |
successSurfacePressed | #bbf7d0 | #166534 |
successBorder | #16a34a | #4ade80 |
onSuccess | #ffffff | #052e16 |
warning | #92400e | #fcd34d |
warningHover | #78350f | #fde68a |
warningPressed | #451a03 | #fef3c7 |
warningSurface | #fffbeb | #451a03 |
warningSurfaceSubtle | #fffbeb | #342e1e |
warningSurfaceHover | #fef3c7 | #78350f |
warningSurfacePressed | #fde68a | #92400e |
warningBorder | #d97706 | #fbbf24 |
onWarning | #ffffff | #451a03 |
danger | #b91c1c | #f87171 |
dangerHover | #991b1b | #fca5a5 |
dangerPressed | #7f1d1d | #fecaca |
dangerSurface | #fef2f2 | #450a0a |
dangerSurfaceSubtle | #fef2f2 | #332222 |
dangerSurfaceHover | #fee2e2 | #7f1d1d |
dangerSurfacePressed | #fecaca | #991b1b |
dangerBorder | #dc2626 | #f87171 |
onDanger | #ffffff | #450a0a |
scrim | #0000008f | #000000b8 |
Implementation
@import "@tinyrack/ui/core.css";
.rack-status {
color: var(--tinyrack-info);
background: var(--tinyrack-info-surface-subtle);
border-color: var(--tinyrack-info-border);
}
See the Tailwind color mappings for prefixed utilities.
Author-only base palette reference
Base ramps are exported for token authors and tooling. They are intentionally absent from the runtime CSS and Tailwind bridge.
neutral
| Step | Value |
|---|---|
| 50 | #fafafa |
| 100 | #f5f5f5 |
| 300 | #d4d4d4 |
| 400 | #a3a3a3 |
| 500 | #737373 |
| 600 | #525252 |
| 700 | #404040 |
| 800 | #262626 |
| 900 | #171717 |
| 950 | #0a0a0a |
blue
| Step | Value |
|---|---|
| 50 | #eff6ff |
| 100 | #dbeafe |
| 200 | #bfdbfe |
| 300 | #93c5fd |
| 400 | #60a5fa |
| 600 | #2563eb |
| 700 | #1d4ed8 |
| 800 | #1e40af |
| 900 | #1e3a8a |
| 950 | #172554 |
green
| Step | Value |
|---|---|
| 50 | #f0fdf4 |
| 100 | #dcfce7 |
| 200 | #bbf7d0 |
| 300 | #86efac |
| 400 | #4ade80 |
| 600 | #16a34a |
| 700 | #15803d |
| 800 | #166534 |
| 900 | #14532d |
| 950 | #052e16 |
amber
| Step | Value |
|---|---|
| 50 | #fffbeb |
| 100 | #fef3c7 |
| 200 | #fde68a |
| 300 | #fcd34d |
| 400 | #fbbf24 |
| 600 | #d97706 |
| 800 | #92400e |
| 900 | #78350f |
| 950 | #451a03 |
red
| Step | Value |
|---|---|
| 50 | #fef2f2 |
| 100 | #fee2e2 |
| 200 | #fecaca |
| 300 | #fca5a5 |
| 400 | #f87171 |
| 600 | #dc2626 |
| 700 | #b91c1c |
| 800 | #991b1b |
| 900 | #7f1d1d |
| 950 | #450a0a |