Measure the palette
Compare lightness endpoints and adjacent tonal distances. Identify compressed steps and abrupt jumps.
An audit of colour foundations, semantic relationships and theme behaviour, turning visual inconsistencies into a structured improvement plan.
My contribution: colour analysis, semantic token restructuring, contrast review and proposed governance. This case study presents an independent library assessment, not a shipped product redesign.
The starting point was a UI library with colour primitives and semantic roles for light and dark themes. Its visible structure suggested a reusable foundation. My task was to look beneath that structure: were the tones meaningfully differentiated, did named colour relationships remain readable, and could teams apply them without repeatedly making their own interpretations?
I treated the audit as a systems problem. An individual colour can be visually appealing while being unsuitable for a particular text or background role. A semantic name can sound clear while leaving its intended foreground undefined. Those gaps matter because they can be repeated wherever the library is reused.
Does the library give designers and developers enough information to make consistent, accessible colour decisions across themes and states?
I focused this assessment on the colour foundation and its relationship to components. I did not treat a colour review as proof that the whole product was accessible. Typography, keyboard behaviour, assistive technology support and interaction-level evaluation would require their own checks.
I organised the work around three connected layers. First, I reviewed the primitive ramps to understand their lightness progression and adjacent perceptual differences. Then I examined foreground/background combinations in each theme. Finally, I considered whether the token architecture could communicate intended use and support future changes.
Compare lightness endpoints and adjacent tonal distances. Identify compressed steps and abrupt jumps.
Review Surface / On Surface and Container / On Container relationships in both themes.
Separate raw values, semantic purposes and component usage. Make unresolved relationships visible.
This sequence kept the recommendations connected. Rebuilding a ramp creates more usable colour choices, but those choices still need explicit semantic assignments. Likewise, renaming tokens cannot repair a pairing whose contrast remains insufficient.
The original blue ramp moved from light to dark, but the distance between tones was uneven. I retained its anchor colour and redistributed the surrounding tones to give semantic roles a more predictable foundation.
#B0C5F0#8AA9E8#5481DE#3369D8#0043CE#003DBB#003092#002571#001C57#DEF1FE#AFCFF7#82ADEF#588BE5#2E68DA#0043CE#002BA2#00157D#00005EMore distinction between neighbouring tones in the proposed scale.
A smaller jump brings this interval closer to the surrounding steps.
The existing blue moves from tone 500 to 600 in the revised scale.
Adjacent ΔE on the same 0–14 scale. A controlled progression creates more predictable choices; the aim is not to maximise every step.
| Step | Before | Proposed |
|---|---|---|
| 100–200 | 9.25 | 11.12 |
| 200–300 | 13.07 | 11.02 |
| 300–400 | 7.49 | 10.72 |
| 400–500 | 10.20 | 10.54 |
| 500–600 | 3.41 | 9.80 |
| 600–700 | 7.59 | 9.20 |
| 700–800 | 6.44 | 8.18 |
| 800–900 | 5.34 | 7.26 |
Calculated from the report’s hex values using Euclidean distance in OKLab × 100. The blue calculations reproduce the report’s labelled original values. Shading aids comparison and does not encode another measure.
Reported lightness endpoints on a 0–100 scale.
The revised lightest orange provides a subtler surface option. Its reported lightness rises from 91.22 to 96.02, while the central orange remains unchanged.
#FCDCB8#FCD0A1#FBC082#F9AB58#F78F20#E57A08#C36807#A55806#8D4B05#FDEFE4#F9D9BF#F6C297#F6A968#F78F20#D7802B#B57338#95663F#8C4F0DAdjacent ΔE on the same 0–14 scale. A controlled progression creates more predictable choices; the aim is not to maximise every step.
| Step | Before | Proposed |
|---|---|---|
| 100–200 | 3.40 | 6.19 |
| 200–300 | 4.45 | 6.40 |
| 300–400 | 5.59 | 6.70 |
| 400–500 | 6.54 | 6.72 |
| 500–600 | 5.98 | 7.00 |
| 600–700 | 7.88 | 7.23 |
| 700–800 | 7.18 | 7.04 |
| 800–900 | 5.94 | 6.73 |
Calculated from the report’s hex values using Euclidean distance in OKLab × 100. The blue calculations reproduce the report’s labelled original values. Shading aids comparison and does not encode another measure.
Red, green, yellow and violet extend to nine tones each. Lighter and darker options give teams more scope to define surfaces, content and states without inventing extra colours.
#E96E6E#E55151#DE2626#CA2323#9E1B1B#7A1515#FDEEEE#FAD2D2#F4A7A7#EB6E6E#DE2626#C41616#A30F0F#7E0C0C#5A0808#54B18E#33A279#008B57#007E4F#00633E#004C30#E8F8EF#C9EFD8#97E0B7#58CD93#33A279#0E8B57#007E4F#00633E#004C30#FFF2B3#FFE45B#FFDE3B#FFD60A#FFF9D9#FFF2B3#FFE45B#FFD60A#F9C000#DCA000#B48000#8F6400#6B4A00#D4BBDD#A36CB6#914FA8#752396#F3E8FC#E1C9F5#C89CEB#A36CB6#914FA8#7A3394#63247D#4C1866#34104AA broader palette does not make every pairing accessible. The next step is to assign foreground and background roles, then validate those relationships in each theme.
Swatches reproduce the original and revised hex values shown in the audit. Tone numbers are positions within each scale; matching numbers do not guarantee equivalent lightness across colour families.
Base neutral surface pairings met the audit’s AA checks, but positive, negative and link text did not perform consistently across the two surfaces and themes. This demonstrated why checking a colour in isolation was insufficient. The same foreground could work against one background and fail against another.
For example, positive text on the first light surface was reported at 3.19:1, while the proposed pairing reached 7.36:1. On the second light surface, link text moved from a reported 3.13:1 to 6.48:1. These were targeted pairing changes, not evidence that every combination in the library had passed.
Reported before/proposed ratios for two specific pairings. Higher values mean greater contrast; these examples are not a whole-library score.
The neutral foundation was workable. The inconsistency appeared in semantic text: positive feedback, negative feedback and links behaved differently across surfaces and themes.
3.19:1 → 7.36:1
The proposed darker foreground creates a stronger relationship with the light surface.
5.78:1 → 9.27:1
A lighter foreground serves the same semantic purpose against a dark surface.
Ratios are transcribed from the assessment. These native colour samples illustrate the proposed pairings, not a complete component test.
The container review exposed three distinct situations: defined pairings that could be tested, container roles without an explicit foreground counterpart, and foreground tokens without a corresponding container. I separated these categories because they require different fixes. A failing pair needs colour adjustment; an undefined relationship first needs an intended-use decision.
One light-theme negative pairing used the same colour for foreground and background, producing a reported ratio of 1.00:1. Other secondary and positive pairings also failed the audit’s checks. In the dark theme, several existing combinations remained difficult to distinguish. I proposed explicit pairings for primary and secondary actions, information, positive and negative roles, including interaction-state variations.
A role and its counterpart exist, but their combination does not pass the audit’s contrast check.
A container exists without an explicit On Container role. The relationship needs to be specified before it can be evaluated.
A foreground token exists without a corresponding container. Its scope needs a decision rather than an assumed pairing.
| Relationship | Original | Proposed | Design response |
|---|---|---|---|
| Light · Secondary default | 3.89:1 | 15.31:1 | Darker content on the light neutral container |
| Light · Negative | 1.00:1 | 9.58:1 | Separate the foreground from the background |
| Dark · Secondary default | 1.50:1 | 7.00:1 | Light content on the dark neutral container |
| Dark · Positive | 1.22:1 | 9.20:1 | A defined light foreground and deep-green container |
Selected examples show different issues, not a representative sample or a whole-library average.
The recommendation was to preserve proximity to the existing palette where possible while choosing combinations that supported the intended role. The goal was a usable relationship between colours, rather than unnecessary extremes at either end of a ramp.
The deliverables followed two levels of semantic maturity. The first retained the supplied structure so the improvements could remain recognisable. The second proposed a clearer extension for borders, interaction states and accessibility-driven roles. Keeping these levels separate made the difference between a requirement-aligned revision and a future evolution explicit.
Rebuilt tonal choices around the existing anchors. Raw values provide the available palette, rather than prescribing every use.
Light and dark mappings for Surface, On Surface, Container, On Container and Transparency.
Additional border, state and accessibility-driven roles to reduce ambiguity as the library grows.
This distinction is central to how I approach Design Systems. A semantic token describes purpose. Its underlying value may change by theme, but the component should retain a stable reference to that purpose. When components bypass the semantic layer and use raw palette values directly, every later theme or contrast adjustment becomes harder to manage.
Positive feedback keeps its meaning when the interface changes theme. Its foreground and container need to change together.
Values and ratios from the proposed container pairings in the assessment. The example illustrates the semantic relationship without reproducing a product screen.
In a design library, this structure also supports review. A reviewer can ask whether a component references the correct role, whether its matching foreground exists, and whether that relationship is supported in each theme. Those questions are more actionable than asking whether a chosen colour simply looks right.
The assessment recorded 97 passing combinations out of 104 tested across contrast, theme consistency and UI states. That is a calculated pass rate of 93.3%, with seven combinations not passing. I would keep those remaining cases visible rather than describe the system as fully accessible.
97 passing · 7 not passing
93.3% is calculated as 97 ÷ 104. The seven remaining cases are calculated as 104 − 97.
The report supplies the aggregate result, not a full row-by-row record of all 104 checks. This figure is not an overall product accessibility score.
The surface and container evidence shows where specific pairings improved, while the aggregate result gives a broader view of validation coverage. Those are complementary forms of evidence. Neither establishes how the library performed after implementation or how users experienced the final product.
Before release, the next step would be to identify the seven outstanding combinations, resolve or document each case, and repeat the relevant checks in actual components. That follow-through matters because a token can be valid in one documented pairing and be applied incorrectly elsewhere.
The audit defined semantic-first usage: components should reference semantic tokens rather than primitives. I would operationalise that principle through a small set of review expectations, making it easier to recognise acceptable use and to assess additions consistently.
For each role, specify its purpose, supported background or foreground, theme mapping and applicable state. Keep ambiguous or unpaired roles visible until resolved.
Check that the intended pairing survives in the actual component, including default, hover and pressed states. Token-level results should inform component review, not replace it.
Record which roles changed, why they changed and which components depend on them. Keep the requirement-aligned revision distinct from the proposed architectural extension.
Keep unresolved checks in an explicit follow-up list. Recheck affected combinations when palette values, semantic mappings or component usage change.
These are the implementation and maintenance steps I recommend from the findings. The assessment demonstrates the audit and proposed system direction; it does not establish that a team adopted these processes or completed a production migration.
This assessment shows how I connect visual craft with measurable evidence and system structure. I moved from identifying irregular tonal spacing to reviewing semantic relationships, then shaped the findings into a clearer architecture for two themes. The work made the reasoning behind the changes visible, rather than presenting a revised palette without explanation.
The most important lesson was that a Design System is not simply a collection of well-arranged assets. Its value depends on the relationships and rules that help other people use those assets correctly. Colour foundations, paired semantic roles and component references need to work together.
I diagnosed colour and pairing issues, proposed rebuilt ramps, developed two semantic architecture directions and communicated validation results with their remaining gaps.
The resulting assessment offers a concrete basis for the next conversation: which changes can be adopted within the existing structure, which need broader architecture agreement, and what must be validated before implementation. It is a foundation for informed delivery decisions, with the remaining work clearly identified.
Source: my Design Library Audit assessment, pages 2–9. Figures are reported measurements or explicitly labelled calculations. Client identity is omitted. Proposed architecture and pairings are presented as assessment outputs, not verified production outcomes.