A humanist design system built with OKLCH colors, variable-font typography, and WCAG 2.1 AA accessibility baked in.
npm install @candor-design/tokensCandor uses Roboto Flex as its UI typeface. The easiest way to load it is via Fontsource:
npm install @fontsource-variable/roboto-flex@import '@fontsource-variable/roboto-flex/index.css';Note:
@fontsource-variable/roboto-flexregisters the font as'Roboto Flex Variable'. Candor's--font-sanstoken lists this name first so it resolves correctly. If you load the font another way (Google Fonts CDN, self-hosted), ensure the font-face name matches or override--font-sansaccordingly.
Link the stylesheet and use the custom properties directly:
<link rel="stylesheet" href="node_modules/@candor-design/tokens/tokens/candor-tokens.css">.button {
background: var(--color-action-primary);
color: var(--color-text-on-action);
font-family: var(--font-family-base);
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--radius-md);
}@import url('@candor-design/tokens/tokens/candor-tokens.css');@import '@candor-design/tokens/tokens/candor-tokens.css';The bundler resolves the bare specifier and inlines the file at build time. This is not Sass @use — @use is for importing Sass modules (.scss source files with variables and mixins). candor-tokens.css is pre-compiled CSS with no Sass members to import.
<link rel="stylesheet" href="node_modules/@candor-design/tokens/tokens/candor-tokens.min.css">import tokens from '@candor-design/tokens/tokens/candor-tokens.json';
tokens.root['--color-action-primary']; // oklch(0.27 0.06 245.34)
tokens.dark['--color-action-primary']; // oklch(0.79 0.12 245)Five OKLCH color families, each with 10 tonal steps (50–900):
| Family | Role |
|---|---|
--navy-* |
Primary action, headings, inverse surfaces |
--burgundy-* |
Secondary action, accents |
--azure-* |
Links, focus rings, interactive highlights |
--purple-* |
Code highlights, visited links, decorative |
--gray-* |
Text, borders, backgrounds |
Semantic aliases map primitive ramps to roles:
/* Backgrounds */
--color-bg-page
--color-bg-surface
--color-bg-elevated
--color-bg-inverse
/* Text */
--color-text-default /* 12.6:1 on page — primary body text */
--color-text-subtle /* 4.6:1 on page — secondary text */
--color-text-on-action /* white on primary/secondary buttons */
/* Action */
--color-action-primary
--color-action-primary-hover
--color-action-secondary
--color-action-secondary-hover
--color-action-destructive
--color-action-destructive-text
/* Status */
--color-status-error
--color-status-error-bg
--color-status-error-text
--color-status-success
--color-status-success-bg
--color-status-success-text
--color-status-warning
--color-status-warning-bg
--color-status-warning-text
/* Other */
--color-link
--color-link-visited
--color-focus
--color-border-default
--color-border-controlAll semantic color pairs are contrast-validated to WCAG 2.1 AA (4.5:1 text, 3:1 UI components).
Dark mode activates automatically via prefers-color-scheme: dark, or can be forced with a data-theme attribute:
<!-- Force dark -->
<html data-theme="dark">
<!-- Force light (overrides OS preference) -->
<html data-theme="light">Only color tokens change between modes. Spacing, typography, and shape tokens are invariant.
--font-family-base /* Roboto Flex — variable font, UI workhorse */
--font-family-display /* Roboto Flex — headings */
--font-family-accessible /* Atkinson Hyperlegible — form labels, error messages, critical UI */
--font-family-mono /* Roboto Mono */
--font-family-serif /* Noto Serif */
--font-family-reading /* Noto Sans — long-form content */Type scale (Major Third, 1.25 ratio):
--font-size-sm /* 14px — system floor for readable text */
--font-size-base /* 16px */
--font-size-lg /* 20px */
--font-size-xl /* 25px */
--font-size-2xl /* 31px */
--font-size-3xl /* 39px */
--font-size-h1 /* 39px */
--font-size-h2 /* 31px */
--font-size-h3 /* 25px */
--font-size-h4 /* 20px */
--font-size-h5 /* 16px */
--font-size-h6 /* 14px */8px grid:
--spacing-xs /* 8px */
--spacing-sm /* 16px */
--spacing-md /* 24px */
--spacing-lg /* 32px */
--spacing-xl /* 48px */
--spacing-2xl /* 64px */
--spacing-3xl /* 96px */--radius-sm /* 4px */
--radius-md /* 8px */
--radius-lg /* 16px */
--radius-full /* 9999px */
--border-width-thin /* 1px */
--border-width-medium /* 2px */
--border-width-thick /* 4px */
--focus-ring-width /* 2px */
--focus-ring-offset /* 2px */Candor is a humanist design system. Every decision — OKLCH colors, variable-font typography, perceptual spacing — is oriented toward human vision and reading experience, not machine defaults.
OKLCH colors use a perceptually uniform color space, so lightness values reliably map to visual weight across hues. This makes it practical to derive accessible color pairs programmatically and to build predictable tonal scales.
Roboto Flex is a variable font with an optical size axis (opsz) that automatically adjusts stroke contrast at different sizes — creating natural typographic hierarchy without artificial weight jumps.
Atkinson Hyperlegible is reserved for critical UI text (form labels, error messages, status indicators) where legibility under stress matters most.
This repository contains the full design system, including the Angular + Storybook component library that the tokens power.
- Node.js 20.16+, 22.19+, or 24+
- npm
git clone https://github.com/pawn002/candor.git
cd candor
npm installnpm run build:tokensOutputs to tokens/:
candor-tokens.css— expanded CSS with commentscandor-tokens.min.css— minified for productioncandor-tokens.json— structured JSON (root+darkkeys)
npm run storybookOpens at http://localhost:6006
npm run test:playwright # Visual regression + a11y tests
npm test # Angular unit testsISC