Colors

Basalt UI uses warm basalt colored neutrals meeting expressive accents. Our color system uses foundation colors defined once and referenced everywhere—change one value, update your entire interface.

Foundation Palette

Base neutral tones (light/dark) defined once. All semantic tokens reference these values—simple, consistent, maintainable.

Blue + Expressive Colors

Professional blue for actions and links. Expressive colors for errors, success, and warnings. Same values work in light and dark modes.

Always Pair Foreground

Every background has a foreground token for accessible contrast. Use bg-blue text-blue-foreground together.

Foundation Palette

Core neutral tones defined once and reused everywhere. Change --light-2 → updates background across the entire system.

Light Tones

Light mode backgrounds, dark mode text, elevated surfaces

Light 1

--light-1

Cards, popovers, overlays

Light 2

--light-2

Main background (light mode)

Light 3

--light-3

Muted, disabled states

Light 4

--light-4

Borders, inputs

Dark Tones

Dark mode backgrounds, light mode text

Dark 1

--dark-1

Near-black, reserved

Dark 2

--dark-2

Main background (dark mode)

Dark 3

--dark-3

Cards (dark mode)

Dark 4

--dark-4

Borders, muted (dark mode)

Blue Primary

Professional blue accent for actions, links, and interactive elements

Blue

--blue

Primary actions, links, focus

Blue Light

--blue-light

Hover states, highlights

Blue Deep

--blue-deep

Strong emphasis

Expressive Colors

Semantic colors for errors, warnings, success, and special states

Red

--red

Errors, destructive actions

Orange

--orange

Warnings, moderate alerts

Yellow

--yellow

Caution, highlights

Green

--green

Success, confirmations

Purple

--purple

Special features

Why Foundation Colors?

  • DRY: Each OKLCH value defined once, referenced everywhere
  • Consistency: All semantic tokens use same base
  • Maintainability: Change once, update entire system
  • Clarity: Foundation → Semantic → UI hierarchy

Sequential Chart Palette

Constant hue (249°) with progressive lightness and gradually increasing chroma. All adjacent colors exceed WCAG 3:1 contrast.

Sequential Chart Palette

Eight perceptually uniform blue tones for sequential data

Blue 1

--chart-blue-1

Blue 2

--chart-blue-2

Blue 3

--chart-blue-3

Blue 4

--chart-blue-4

Blue 5

--chart-blue-5

Blue 6

--chart-blue-6

Blue 7

--chart-blue-7

Blue 8

--chart-blue-8

Use Cases

  • Sequential data: temperature scales, density maps, intensity visualization
  • Gradient backgrounds: from subtle (blue-1) to prominent (blue-8)
  • Perceptually uniform: equal perceived steps between colors

Semantic Color Tokens

Meaningful names for UI elements that reference the foundation palette. These automatically switch between light and dark modes.

Background
--background

Main page background

Foreground
--foreground

Primary text color

Primary
--primary

Actions, links, focus

Secondary
--secondary

Alternative actions

Accent
--accent

Hover states

Destructive
--destructive

Errors, delete actions

Muted
--muted

Disabled states

Card
--card

Card surfaces

Border
--border

Borders, dividers

Text Color Pairing

Every background color has a corresponding foreground token ensuring accessible contrast.

Light Text (White)

  • bg-primary text-primary-foreground
  • bg-blue text-blue-foreground
  • bg-red text-red-foreground
  • bg-purple text-purple-foreground

Dark Text

  • bg-background text-foreground
  • bg-orange text-orange-foreground
  • bg-yellow text-yellow-foreground
  • bg-green text-green-foreground

Best Practices

  • Always use foreground tokens for automatic dark mode support
  • All pairs meet WCAG AA standards (4.5:1 for text)

Usage Guidelines

Do
  • Use semantic color tokens (bg-primary, text-muted-foreground)
  • Rely on automatic dark mode switching via .dark class
  • Use blue (primary) for interactive elements and links
  • Use expressive colors for semantic states (red = error, green = success)
  • Always pair background colors with their foreground tokens
Don't
  • Don't use arbitrary color values (bg-[#f3f3f3])
  • Don't use HSL or RGB colors (breaks OKLCH benefits)
  • Don't use red for non-error states
  • Don't manually handle dark mode (system does it automatically)
  • Don't use text-white or hardcoded colors - use foreground tokens

Implementation

CSS Variables
.component {
  background: var(--background);
  color: var(--foreground);
  border: 1px solid var(--border);
}

.button {
  background: var(--primary);
  color: var(--primary-foreground);
}

.button:hover {
  background: var(--accent);
  color: var(--accent-foreground);
}
Tailwind Classes
<!-- Main layout -->
<div class="bg-background text-foreground">

<!-- Primary button -->
<button class="bg-primary text-primary-foreground">
  Click me
</button>

<!-- Card surface -->
<div class="bg-card text-card-foreground border-border">
  Card content
</div>

<!-- Error state -->
<div class="bg-destructive text-destructive-foreground">
  Error message
</div>

OKLCH Color Space

L (Lightness)

0-1 scale. Changes correspond to perceived brightness—no unexpected gray zones.

C (Chroma)

Saturation matching human perception. Consistent across different hues.

H (Hue)

Color angle (0-360). 249° = blue, 15° = red, 84° = yellow, 131° = green.

Why OKLCH?

  • Perceptually uniform—gradients stay clean and predictable
  • Better accessibility—easier to maintain proper contrast ratios
  • Consistent saturation across hues