Skip to main content

Color checkpoints

Whether the color system is complete, readable, well named and well layered: roles, states, contrast, naming and alias chains.

Each checkpoint reports pass, warning, fail or skipped. A finding for a checkpoint links its section on this page.

Completeness

Semantic color roles defined

color-completeness-semantic-roles

Whether color tokens cover five roles: surface, text, border, accent and muted. A token's role comes from its role field, or else from its name; for example bg counts as surface, primary as accent and secondary as muted.

ResultWhen
PassAll five roles have tokens.
Warning1 or 2 roles are missing.
Fail3 or more roles are missing, or no color tokens are defined.
SkippedNot reported by this checkpoint.

How to improve. Add tokens for the missing roles.

Dark mode variants

color-completeness-dark-mode

Whether the color system supports dark mode, from the hasDarkMode flag and each token's hasDarkVariant, or else from token names containing dark.

ResultWhen
PasshasDarkMode is true and at least 80% of tokens have a dark variant.
WarninghasDarkMode is true with fewer than 80% covered; dark-named tokens exist without the flag; hasDarkMode is false; or support cannot be determined.
FailNot reported by this checkpoint.
SkippedNo color tokens were provided.

How to improve. Set hasDarkMode, and mark each token that has a dark variant with hasDarkVariant.

Interactive state colors

color-completeness-interactive-states

Whether hover, focus, active and disabled colors are defined, from the interactiveStates config or, without it, from token names.

ResultWhen
PassAll four states are defined.
WarningSome are missing: up to two with the config, or any number above zero when read from token names.
Fail3 or more are missing from the config, or no state appears in any token name.
SkippedNot reported by this checkpoint.

How to improve. Define a color for every interactive state.

Status colors defined

color-completeness-status-colors

Whether success, error, warning and info colors exist, from the statusColors config or, without it, from token names. Names containing danger or destructive count as error.

ResultWhen
PassAll four are defined.
WarningSome are missing: up to two with the config, or at least one found by name.
Fail3 or more are missing from the config, or none is found by name.
SkippedNot reported by this checkpoint.

How to improve. Add the missing status colors.

Surface and text pairs

color-completeness-surface-text-pairs

Whether both surface and text tokens exist, and whether the pairs config, which contrast checking uses, declares at least one pair that puts a detected text token on a detected surface token. Pairs between other tokens do not count.

ResultWhen
PassBoth kinds exist and at least one declared pair puts a text token on a surface token.
WarningBoth kinds exist but no declared pair puts a text token on a surface token.
FailSurface tokens, text tokens or both are missing.
SkippedNot reported by this checkpoint.

How to improve. Declare which text tokens go on which surface tokens in the pairs config.

Relationships

Contrast meets WCAG AA

color-relationships-contrast-aa

The contrast ratio of each foreground and background pair: the declared pairs or, without them, combinations of up to five surface and five text tokens. Normal text needs 4.5:1 (7:1 when the check runs at level AAA) and large text 3:1.

ResultWhen
PassEvery checkable pair meets its minimum.
WarningSome pairs fall short, but no more than half.
FailMore than half of the pairs fall short.
SkippedThere are no pairs to check, or no pair has values that can be read as hex, rgb or hsl.

How to improve. Darken the foreground or lighten the background of each failing pair.

Logical color hierarchy

color-relationships-semantic-hierarchy

Whether primary (or accent), secondary and muted colors step down in visual weight, judged by their contrast against white.

ResultWhen
PassPrimary outweighs secondary and secondary outweighs muted, for the values that can be read.
WarningThe hierarchy is inverted; there is no primary or accent token; or there is a primary but no secondary or muted token.
FailNot reported by this checkpoint.
SkippedNot reported by this checkpoint.

How to improve. Make primary the strongest color, then secondary, then muted.

Status colors are distinct

color-relationships-status-distinction

Whether each pair of status colors (success, error, warning, info) is at least 80 apart, measured as straight-line distance between their RGB values.

ResultWhen
PassEvery pair is far enough apart.
WarningSome pairs are too close.
FailNot reported by this checkpoint.
SkippedFewer than 2 status colors can be read.

How to improve. Move similar status colors further apart, and do not rely on red and green alone.

Dark mode contrast

color-relationships-dark-mode-contrast

The contrast of declared pairs whose foreground or background name contains dark, against a minimum of 4.5:1.

ResultWhen
PassEvery dark pair meets 4.5:1.
WarningSome fall short, or dark mode is declared but no dark pairs are declared.
FailNot reported by this checkpoint.
SkippedhasDarkMode is not true, or no dark pair can be read.

How to improve. Declare dark mode pairs and adjust any below 4.5:1.

Interactive states look different

color-relationships-interactive-progression

Whether each state looks different from the next, in the order default, hover, focus, active, disabled: adjacent states must be at least 15 apart in RGB distance. Values come from the interactiveStates config or from token names.

ResultWhen
PassEvery adjacent pair is distinct.
WarningSome adjacent states look the same.
FailNot reported by this checkpoint.
SkippedFewer than 2 state colors can be read.

How to improve. Make hover, focus and active visibly different from each other.

Naming

Consistent naming convention

color-naming-convention

Which naming convention each token name follows, compared with the declared namingConvention or, without one, with the most common convention.

ResultWhen
PassWith a declared convention, at least 90% follow it. Without one, every name follows the same convention.
WarningWith a declared convention, fewer than 90% follow it. Without one, at least 80% follow the most common.
FailWithout a declared convention, fewer than 80% follow the most common one.
SkippedNo tokens were provided.

How to improve. Pick one convention and rename the outliers.

Semantic names over primitive names

color-naming-semantic-over-primitive

The share of tokens with semantic names rather than primitive ones, such as blue-500, a hex value, a bare number or light-red. Tokens with the primitive role count as primitive.

ResultWhen
PassAt least 90% are semantic.
WarningBetween 60% and 90%.
FailBelow 60%.
SkippedNo tokens were provided.

How to improve. Add a semantic layer, such as accent-primary or surface-muted, that references the primitives, and have components use it.

No ambiguous or conflicting names

color-naming-no-ambiguity

Generic names (color1, c2, custom-3, or names starting with temp, new-, old- or test) and pairs of names that become identical once case, dashes and underscores are ignored, such as text-primary and textPrimary.

ResultWhen
PassNo such names.
WarningSome, up to 20% of tokens.
FailMore than 20% of tokens.
SkippedNo tokens were provided.

How to improve. Give generic tokens descriptive names, and resolve names that collide.

Valid alias chains

color-naming-alias-chain

Whether every token's aliasOf points to a token that exists.

ResultWhen
PassEvery alias resolves, or no token uses aliases and none looks like a reference.
WarningSome aliases are broken, up to half; or values look like references but aliasOf is not set.
FailMore than half of the aliases are broken.
SkippedNot reported by this checkpoint.

How to improve. Point each broken alias at an existing token, and use aliasOf for every reference.

Role-based prefixes

color-naming-role-prefix

The share of non-primitive tokens whose name starts with a role prefix such as surface, text, border, accent, status, hover or button.

ResultWhen
PassAt least 80%, or every token is a primitive.
WarningBetween 50% and 80%.
FailBelow 50%.
SkippedNo tokens were provided.

How to improve. Prefix tokens with their role: surface-, text-, border-, accent-, status-.

Usage

No orphaned primitives

color-usage-no-orphaned

Primitive tokens (the primitive role, or no role and no alias) that no other token aliases. It only applies once some tokens use aliasOf.

ResultWhen
PassEvery primitive is referenced, or no token uses aliases (scored 80 in that case).
WarningSome primitives are not referenced, up to 30% of them.
FailMore than 30% of primitives are not referenced.
SkippedNo tokens were provided.

How to improve. Remove unused primitives, or reference them from semantic tokens.

No duplicate values

color-usage-no-duplicates

Groups of tokens with direct (non-alias) values that are the same color once normalized.

ResultWhen
PassNo duplicates, or fewer than 2 direct-value tokens.
WarningTokens that repeat another token's value make up 20% or less of direct-value tokens.
FailThey make up more than 20%.
SkippedNo tokens were provided.

How to improve. Merge duplicates, or have both tokens reference one shared primitive.

No circular references

color-usage-no-circular-refs

Tokens whose alias chain loops back on itself.

ResultWhen
PassNo cycles, or no aliases.
WarningNot reported by this checkpoint.
FailAny cycle.
SkippedNot reported by this checkpoint.

How to improve. Break each cycle by pointing one token at a direct value.

Short alias chains

color-usage-alias-depth

Alias chains longer than 3 levels, for example primitive, semantic, component.

ResultWhen
PassNo chain is longer than 3 levels, or no aliases exist.
WarningSome chains are longer.
FailNot reported by this checkpoint.
SkippedNot reported by this checkpoint.

How to improve. Flatten chains to 3 levels or fewer.

Semantic to primitive ratio

color-usage-token-ratio

The share of semantic tokens (an alias, or a role other than primitive or other) among tokens classified as semantic or primitive (the primitive role).

ResultWhen
PassAt least 50% are semantic.
WarningBelow 50%, or no token is classified either way.
FailNot reported by this checkpoint.
SkippedNo tokens were provided.

How to improve. Add semantic tokens that reference primitives, and tag tokens with roles.

Was this page helpful?

Last reviewed by @jschuyler
All systems operationalDocsDevelopersPlatformPricing
PrivacyTerms© 2026 fndd, LLC