Open source · Design Systems

Theme Contrast Palette

Check light, dark and high-contrast theme values for semantic consistency.

v0.1.0 · Node.js 22+ · MIT

Browse the public repository · View releases

Check that every theme says the same things, and that every declared foreground/background pair is legible in every one of them.

This walkthrough uses the tool's public README and checked-in example files. Run the command from a repository checkout with Node.js 22+.

Run the checked-in example

# Clean: five pairs, three themes, fifteen measurements.
node bin/theme-contrast-palette.mjs \
  --palette examples/palette.json \
  --policy examples/policy.json \
  --root .
# -> "15 of 15 pair/theme combination(s) measured ... status pass."   exit 0

# One theme drifted: light fails, dark and high-contrast still pass.
node bin/theme-contrast-palette.mjs \
  --palette examples/drifted-palette.json \
  --policy examples/policy.json --root .
# -> contrast-below-minimum in "light" only   exit 1

# A translucent background with nothing declared behind it.
node bin/theme-contrast-palette.mjs \
  --palette examples/unbacked-palette.json \
  --policy examples/policy.json --root .
# -> alpha-backdrop-missing in all three themes, status incomplete   exit 2

# A token one theme has and another does not.
node bin/theme-contrast-palette.mjs \
  --palette examples/parity-gap-palette.json \
  --policy examples/policy.json --root .
# -> token-missing-in-theme, and 14 of 15 measured   exit 2

Read the result

Add --json for the machine-readable report on stdout, and --out report.json to write that report to a file as well.

Scope

Every bound is enforced where it can be exceeded, and exceeding one produces limit-exceeded with status: "incomplete" — never a silent truncation and never a pass. Override any of them under limits in the policy; an unknown limit name is refused.