Skip to main content
A Singapore Government Agency Website

Colour

Colour tells people which product they're in and what needs their attention. Each product keeps its own primary; neutrals and status colours stay shared.

In the catalogue

Product primaries

Each product defines its own primary in its DESIGN.md. Draw it from a Radix colour scale, so states, tints, and dark-mode variants are already defined. A surface that lives inside a host product uses the host's primary rather than carrying its own.

What stays shared across all products: neutrals (Radix gray/slate), functional colours (success/warning/danger from Radix grass/amber/red, COL-2), typography, illustration style, and spacing. A product changes its accent, never its character.

The Radix scales

Each Radix colour ships as a 12-step scale with defined roles: backgrounds, component states, borders, solid fills, and text. Picking from Radix means every product's hover, pressed, and disabled states are consistent by construction.

1
2
3
4
5
6
7
8
9
10
11
12
1–2 App and subtle backgrounds
3–5 Component states: normal, hover, active
6–8 Borders and separators
9–10 Solid fills, primary actions
11–12 Text: low-contrast and high-contrast
Radix indigo — an example product primary at step 9.
1
2
3
4
5
6
7
8
9
10
11
12
1–2 App and subtle backgrounds
3–5 Component states: normal, hover, active
6–8 Borders and separators
9–10 Solid fills, primary actions
11–12 Text: low-contrast and high-contrast
Radix orange — a warmer example, primary at step 9.

Shared neutrals

Neutrals stay shared across every product: gray for general UI, slate where a cooler tone reads better.

1
2
3
4
5
6
7
8
9
10
11
12
1–2 App and subtle backgrounds
3–5 Component states: normal, hover, active
6–8 Borders and separators
9–10 Solid fills, primary actions
11–12 Text: low-contrast and high-contrast
1
2
3
4
5
6
7
8
9
10
11
12
1–2 App and subtle backgrounds
3–5 Component states: normal, hover, active
6–8 Borders and separators
9–10 Solid fills, primary actions
11–12 Text: low-contrast and high-contrast

Functional colours

Functional colours always come from the shared Radix scales: grass for success, amber for warning, and red for danger. Never pick one ad hoc (COL-2).

Radix grass · step 9 · #46a758
On track
Radix amber · step 9 · #ffc53d
Needs review
Radix red · step 9 · #e5484d
Overdue

The warning text token is darkened past Radix amber-11 on purpose. Amber-11 caps at roughly 4.6:1 even on white, so it fails AA on the tinted warning background. The darkened value clears 6.1:1 instead.

Semantic tokens

Tokens describe purpose, not appearance, so a colour can change without touching a single component.

TokenRole
--backgroundThe page canvas.
--surfacePanels and cards sitting on the page.
--foregroundPrimary text ink.
--muted-foregroundSecondary text — darkened from zinc-500 to clear AA on the muted fill.
--borderHairline dividers and default component borders.
--mutedActive fill and code background.
--accentHover fill.
--border-strongHover border.
--prose-bodyBody text ink inside long-form content.
--ringFocus ring colour.
TokenRole
--successSuccess text — Radix grass-11.
--success-9Success solid fill — Radix grass-9.
--success-subtleSuccess badge background.
--success-mutedSuccess badge border.
--warningWarning text — darkened past Radix amber-11 to clear AA on a tinted background.
--warning-9Warning solid fill — Radix amber-9.
--warning-subtleWarning badge background.
--warning-mutedWarning badge border.
--dangerDanger text — Radix red-11.
--danger-9Danger solid fill — Radix red-9.
--danger-subtleDanger badge background.
--danger-mutedDanger badge border.

Usage

tsx

// Semantic Tailwind classes — the default
<div className="bg-surface text-foreground border border-border" />
<span className="text-success bg-success-subtle" />

// CSS-variable escape hatch, when no class fits
<div style={{ background: "var(--muted)" }} />

Best practices

  • DoUse the product's own primary for primary actions and brand moments (COL-1).
  • DoTake success, warning, and danger colours from the shared Radix scales (COL-2).
  • DoPair colour with a text label — never signal with colour alone.
  • Don'tHardcode a hex value in a component; use a semantic token instead (TOK-1).
  • Don'tUse purple or violet gradients, cyan-on-dark, glow accents, or gradient text (SLP-1, SLP-2).