Zazz Design Framework
Reference

Colors

Theme tokens, brand scales, grayscale, and status colors. Values and usage.

Zazz colors come in four layers: theme, brand scales, grayscale, and status. Every color is declared in OKLCH for perceptually consistent stepping and mode transitions.

Using colors

Reference any color through its CSS variable:

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

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

With Zazz utilities installed, every theme color has a matching utility class (set up the same way Tailwind would expose them): bg-primary, text-foreground, border-border, and so on.

Theme tokens

Theme tokens like --background, --primary, and --destructive resolve to specific scale values based on the active mode. The complete table of theme tokens with light and dark mappings lives on Foundations → Theme.

Brand scales

The raw color scales that brand theme tokens point into. Replace these per project to rebrand without touching any component. See Foundations → Corporate.

Each scale below has its own hex input. Adjust the base color and Generate to open a fresh 11-step palette in Tints.dev. Or edit all four defaults at once in a single editor.

A first-class theme builder is on the roadmap. For now, generate via Tints.dev and paste the OKLCH output into your variables file.

Primary

50--primary-50
100--primary-100
200--primary-200
300--primary-300
400--primary-400
500--primary-500
600--primary-600
700--primary-700
800--primary-800
900--primary-900
950--primary-950
:root {
  /* Primary; base #4D44E4 */
  --primary-50: oklch(0.984 0.007 286.46);
  --primary-100: oklch(0.94 0.025 288.37);
  --primary-200: oklch(0.85 0.068 285.81);
  --primary-300: oklch(0.765 0.108 284.76);
  --primary-400: oklch(0.674 0.154 283.18);
  --primary-500: oklch(0.593 0.193 280.79);
  --primary-600: oklch(0.511 0.23 276.97);
  --primary-700: oklch(0.421 0.234 273.27);
  --primary-800: oklch(0.32 0.179 273.06);
  --primary-900: oklch(0.229 0.127 273.39);
  --primary-950: oklch(0.158 0.088 274.05);
}

Secondary

50--secondary-50
100--secondary-100
200--secondary-200
300--secondary-300
400--secondary-400
500--secondary-500
600--secondary-600
700--secondary-700
800--secondary-800
900--secondary-900
950--secondary-950
:root {
  /* Secondary; base #DE4917 */
  --secondary-50: oklch(0.984 0.008 27.43);
  --secondary-100: oklch(0.95 0.023 24.19);
  --secondary-200: oklch(0.878 0.061 25.87);
  --secondary-300: oklch(0.814 0.101 27.69);
  --secondary-400: oklch(0.749 0.146 30.02);
  --secondary-500: oklch(0.687 0.198 34.85);
  --secondary-600: oklch(0.61 0.194 36.8);
  --secondary-700: oklch(0.5 0.159 36.84);
  --secondary-800: oklch(0.383 0.121 36.98);
  --secondary-900: oklch(0.276 0.088 36.22);
  --secondary-950: oklch(0.215 0.068 37.62);
}

Tertiary

50--tertiary-50
100--tertiary-100
200--tertiary-200
300--tertiary-300
400--tertiary-400
500--tertiary-500
600--tertiary-600
700--tertiary-700
800--tertiary-800
900--tertiary-900
950--tertiary-950
:root {
  /* Tertiary; base #E5375B */
  --tertiary-50: oklch(0.984 0.006 17.54);
  --tertiary-100: oklch(0.942 0.023 11.04);
  --tertiary-200: oklch(0.861 0.062 11.02);
  --tertiary-300: oklch(0.772 0.11 12.13);
  --tertiary-400: oklch(0.693 0.163 13.04);
  --tertiary-500: oklch(0.613 0.208 14.68);
  --tertiary-600: oklch(0.523 0.177 14.77);
  --tertiary-700: oklch(0.432 0.147 14.69);
  --tertiary-800: oklch(0.334 0.114 14.76);
  --tertiary-900: oklch(0.244 0.083 14.99);
  --tertiary-950: oklch(0.197 0.068 15.17);
}

Grayscale

Neutrals plus the shade and tint scales derived from them. See Foundations → Grayscale.

Neutral

white--white
50--neutral-50
100--neutral-100
200--neutral-200
300--neutral-300
400--neutral-400
500--neutral-500
600--neutral-600
700--neutral-700
800--neutral-800
900--neutral-900
950--neutral-950
black--black
:root {
  /* Neutral; base #888890 */
  --white: white;
  --neutral-50: oklch(0.9911 0 0);
  --neutral-100: oklch(0.9581 0 0);
  --neutral-200: oklch(0.871 0.004 286.58);
  --neutral-300: oklch(0.794 0.007 286.38);
  --neutral-400: oklch(0.708 0.009 286.28);
  --neutral-500: oklch(0.629 0.012 286.12);
  --neutral-600: oklch(0.535 0.015 285.91);
  --neutral-700: oklch(0.442 0.015 285.82);
  --neutral-800: oklch(0.336 0.014 285.66);
  --neutral-900: oklch(0.241 0.009 285.7);
  --neutral-950: oklch(0.198 0.008 285.68);
  --black: black;
}

Shade

Darkened overlays derived from --neutral-950. Each step is the neutral at a specific alpha. Apply over a light surface for a "darken-it" effect.

50--shade-50
100--shade-100
200--shade-200
300--shade-300
400--shade-400
500--shade-500
600--shade-600
700--shade-700
800--shade-800
900--shade-900
950--shade-950
:root {
  /* Shade; derived from --neutral-950 */
  --shade-none: oklch(from var(--neutral-950) l c h / 0);
  --shade-50: oklch(from var(--neutral-950) l c h / 0.05);
  --shade-100: oklch(from var(--neutral-950) l c h / 0.1);
  --shade-200: oklch(from var(--neutral-950) l c h / 0.2);
  --shade-300: oklch(from var(--neutral-950) l c h / 0.3);
  --shade-400: oklch(from var(--neutral-950) l c h / 0.4);
  --shade-500: oklch(from var(--neutral-950) l c h / 0.5);
  --shade-600: oklch(from var(--neutral-950) l c h / 0.6);
  --shade-700: oklch(from var(--neutral-950) l c h / 0.7);
  --shade-800: oklch(from var(--neutral-950) l c h / 0.8);
  --shade-900: oklch(from var(--neutral-950) l c h / 0.9);
  --shade-950: oklch(from var(--neutral-950) l c h / 0.95);
  --shade-full: oklch(from var(--neutral-950) l c h / 1);
}

Tint

Faded overlays derived from --white. Apply over a dark surface for a "lighten-it" effect.

50--tint-50
100--tint-100
200--tint-200
300--tint-300
400--tint-400
500--tint-500
600--tint-600
700--tint-700
800--tint-800
900--tint-900
950--tint-950
:root {
  /* Tint; derived from --white */
  --tint-none: oklch(from var(--white) l c h / 0);
  --tint-50: oklch(from var(--white) l c h / 0.05);
  --tint-100: oklch(from var(--white) l c h / 0.1);
  --tint-200: oklch(from var(--white) l c h / 0.2);
  --tint-300: oklch(from var(--white) l c h / 0.3);
  --tint-400: oklch(from var(--white) l c h / 0.4);
  --tint-500: oklch(from var(--white) l c h / 0.5);
  --tint-600: oklch(from var(--white) l c h / 0.6);
  --tint-700: oklch(from var(--white) l c h / 0.7);
  --tint-800: oklch(from var(--white) l c h / 0.8);
  --tint-900: oklch(from var(--white) l c h / 0.9);
  --tint-950: oklch(from var(--white) l c h / 0.95);
  --tint-full: oklch(from var(--white) l c h / 1);
}

Status

Status tokens cover info, success, warning, and destructive. Status colors step darker in dark mode, opposite to brand. See Foundations → Theme → Status.

Light mode

--info
--success
--warning
--destructive

Dark mode

--info
--success
--warning
--destructive
:root {
  /* Status: light mode */
  --info: oklch(0.5876 0.1389 241.97);
  --success: oklch(0.596 0.1274 163.23);
  --warning: oklch(0.6658 0.1574 58.32);
  --destructive: oklch(0.5771 0.2152 27.33);
}

:is(.dark, .dark *) {
  /* Status: dark mode (steps darker, opposite of brand) */
  --info: oklch(0.5 0.1193 242.75);
  --success: oklch(0.5081 0.1049 165.61);
  --warning: oklch(0.5553 0.1455 49);
  --destructive: oklch(0.5054 0.1905 27.52);
}

Customizing colors

Override any color by re-declaring the variable. Re-target a theme token to point at a different scale step, or replace a corporate scale entirely:

:root {
  /* Re-target theme tokens */
  --primary: var(--secondary-600);
  --destructive: oklch(0.55 0.2 15);

  /* Replace a corporate scale */
  --primary-50: oklch(0.97 0.02 200);
  --primary-100: oklch(0.92 0.05 200);
  /* ... through 950 */
}

See Practices → Customization for the full override patterns, including scoped overrides for sub-apps and rebrand workflows.

Using a custom value

For one-off colors that don't warrant a scale, declare them directly in your component CSS using OKLCH:

.holiday-banner {
  background: oklch(0.6 0.18 145); /* festive green */
  color: var(--white);
}

OKLCH keeps the value in the same color space as the rest of Zazz, so mixing and stepping behave predictably if you decide to scale the color into a full token later.

On this page