roundel/contrast
Every export of roundel/contrast, with its signature and doc comment: channels, luminance, contrast, reportTheme, AA, AAA and 2 more, plus 2 types.
The WCAG 2.2 contrast maths (R5).
It was copied from burgee/contrast under Y1 — "sixty lines duplicated beats a dependency
arrow pointing the wrong way" — on the condition that the two copies share a test-vector
file. That condition was met half way for five days: this copy was pinned to
contrast-vectors.json and burgee's was not, which is the worse arrangement, because the
pinned copy cannot drift and the unpinned one can while keeping a green suite.
#194 settled it differently and better: the arrow was reversed, so there is one
implementation and burgee/contrast imports this one. The vectors remain as a reference —
values computed outside this file, which is the only kind that can catch a wrong constant —
and scripts/shared-vectors-lock.test.ts keeps them read rather than kept.
fly() uses it to refuse a truecolor token that would not read against the declared
ground. Nothing here is asked about the 16- and 256-colour palettes: those are the
user's terminal theme, and a number there would be invented.
import { channels, luminance, contrast, … } from 'roundel/contrast';Functions
channels
#abc and #aabbcc both parse, to sRGB channels in 0..1. Anything else is a mistake worth throwing on.
function channels(hex: string): [number, number, number];| Parameter | Type |
|---|---|
hex | string |
Returns [number, number, number]
contrast
The WCAG contrast ratio between two colours. Order does not matter.
function contrast(a: string, b: string): number;| Parameter | Type |
|---|---|
a | string |
b | string |
Returns number
luminance
WCAG relative luminance.
function luminance(hex: string): number;| Parameter | Type |
|---|---|
hex | string |
Returns number
reportTheme
One line per finding, aligned, for a terminal or a failing test. Mirrors
burgee/contrast's report — the same shape in both packages, because somebody reading a
theme audit and a brand audit on the same day should not have to learn two layouts.
Passing rows are printed too. A report that lists only failures cannot tell "nothing is wrong" from "nothing was checked", and the second is the state this package was in for the 256-colour level until 2026-09-13.
function reportTheme(findings: readonly ThemeFinding[]): string;| Parameter | Type |
|---|---|
findings | readonly ThemeFinding[] |
Returns string
Constants
AA
The floors WCAG 2.2 sets, as ratios.
const AA: {
/** Body text against its background. */
readonly TEXT: 4.5;
/** Large text, UI components, and meaningful parts of a graphic. */
readonly GRAPHIC: 3;
};AAA
The stricter conformance level, for a caller who needs it: low-vision users, a CLI run on a projector, a terminal in daylight, or an organisation whose accessibility policy says AAA and does not care that this is a terminal.
Not the default, and not because AA is good enough. At 7:1 the 256-colour palette runs out of room fast — a great many perfectly reasonable brand colours have no readable substitute in the cube at that floor — so defaulting to AAA would refuse themes that work for almost everyone on almost every terminal. It is the caller's call, which is the only place that judgement can honestly sit.
const AAA: {
/** Body text against its background. */
readonly TEXT: 7;
/** Large text, UI components, and meaningful parts of a graphic. */
readonly GRAPHIC: 4.5;
};floors
The floors for a conformance level, so a caller names a standard rather than a number.
const floors: (level?: Conformance) => typeof AA | typeof AAA;round2
const round2: (value: number) => number;Interfaces
ThemeFinding
One token's verdict at one colour level, in the words somebody fixing it would use.
interface ThemeFinding {
/** The token name — `error`, `ok`, `command`. */
token: string;
/** `truecolor` or `256`. Never `16`: those values are the user's terminal theme. */
at: 'truecolor' | '256';
/** What the terminal is actually sent at this level, which is not always the hex written. */
colour: string;
ground: string;
ratio: number;
required: number;
passes: boolean;
}Types
Conformance
Which WCAG conformance level a theme is held to. AA unless a caller asks for more.
type Conformance = 'AA' | 'AAA';roundel/theme
Every export of roundel/theme, with its signature and doc comment: rgb256, toOklab, audit, fly, plus 3 types.
roundel/chalk
Every export of roundel/chalk, with its signature and doc comment: modifierNames, foregroundColorNames, backgroundColorNames, underlineColorNames, colorNames, supportsColor and 3 more, plus 16 types.