Skip to content

[TEST] Update base and display color scales#1369

Draft
danielguillan wants to merge 11 commits intomainfrom
danielguillan/update-brand-refactor-scales
Draft

[TEST] Update base and display color scales#1369
danielguillan wants to merge 11 commits intomainfrom
danielguillan/update-brand-refactor-scales

Conversation

@danielguillan
Copy link
Copy Markdown

Summary

Brand Color Scale Alignment POC

This branch updates Primer Primitives' base and display color scales to align with the Brand Refactor color palette (Figma / Primer Brand). It's a proof of concept to assess feasibility, preview changes in dotcom, surface potential breaking changes early, and gather information for a full implementation.

What changed

1. Base neutral scales

The light and dark neutral scales were updated to match Brand Refactor's greenish-gray palette.

  • neutrals shifted from a blue-gray hue to a green-gray hue.
  • black changed from #1f2328 (dark blue-gray) to #000000 (true black).
  • Step 13 (lightest in dark mode) changed from pure white (#fff) to #f2f5f3, which had downstream consequences (see below).

2. Display hue scales aligned with base scales

The display hue scales (gray, blue, green, red, orange, yellow, purple, pink, coral) were realigned so that display colors derive from their base scale counterparts.

3. New borderColor.onMuted display tokens

A new borderColor.onMuted token was added for all display hues. This token is purpose-built for borders rendered on top of bgColor-muted backgrounds, ensuring the border-on-muted contrast requirement is met independently from borderColor-emphasis (which targets contrast against bgColor-muted from the page level).

The contrast config was updated to check borderColor-onMuted against bgColor-muted instead of borderColor-emphasis. This was required to workaround contrast issues.

4. Functional token adjustments

Many functional tokens needed step-level adjustments to maintain contrast with the new scale values:

File Key changes
fgColor.json5 Dark neutral.13{base.color.white} for tokens semantically meaning white; accent/success bumped up steps
bgColor.json5 HC overrides shifted (e.g. muted light-HC n.3→n.2, dark-HC n.2→n.1); inverse/white dark → {base.color.white}; success-emphasis dark green.5→6; success-muted dark-PD alpha 0.2→0.15
borderColor.json5 emphasis neutral.8→9; dark mode default/muted stepped down for contrast
control.json5 HC hover/active shifted (e.g. n.5→n.3, n.6→n.4); knob.checked dark → {base.color.white}
button.json5 All dark neutral.13 fg refs → {base.color.white}; HC danger overrides adjusted
display.json5 161+ step changes across emphasis, muted, borderColor for all hues × all themes
avatar.json5 Dark border → {base.color.white}
header.json5 Dark text → {base.color.white}
syntax.json5 Dark comment color adjusted

Key challenges

The neutral.13 ≠ white problem

The old neutral scale had step 13 as #ffffff. Many dark-mode tokens referenced neutral.13 to mean "white". When the new scale changed step 13 to #f2f5f3, all those tokens broke contrast.

Fix: Replaced {base.color.neutral.13} with {base.color.white} wherever the intent was a true white value. This is semantically cleaner but is a pattern change that needs to be applied consistently across the full token set.

Contrast cascade

Changing scale hex values at the base level triggers a cascade of contrast failures in functional tokens. A single scale update can break dozens of theme × token combinations because:

  • Each token may have overrides for up to 13 themes
  • High-contrast themes have stricter ratios (7:1 text, 4.5:1 border vs 4.5:1 and 3:1)
  • Dark HC themes are the hardest to satisfy, sometimes opposing requirements make it structurally impossible for a single scale step to work

Structurally impossible HC contrasts

Some high-contrast requirements are in tension. For example, a token may need to be:

  • Dark enough to meet 7:1 against a light background
  • Light enough to meet 7:1 against a dark background

When no single scale step satisfies both, custom hex values between scale steps are needed (an existing pattern in the codebase, see fgColor.success light-HC override).

Breaking changes

This is a visually breaking change across the board:

  1. All neutral surfaces shift hue: every gray in the UI moves from blue-gray to green-gray
  2. Display colors shift: labels, tags, avatars, and other decorative elements change
  3. Contrast step changes: emphasis levels, muted backgrounds, and border weights subtly shift
  4. ~1,800 lines of token source changes
  5. ~1,860 snapshot files regenerated

Affected color token stats:

Category Affected New Total %
Base 216 0 290 74,5%
Functional 401 19 526 79,8%
Component 260 0 349 74,5%
Total 877 19 1.165 76,9%

There are no structural breaking changes (no tokens renamed, removed, or added except borderColor.onMuted).

Risks and considerations

  • Visual review needed: Automated checks pass, but the green-gray shift needs visual QA across dotcom surfaces. Screenshots/Storybook preview should be reviewed by design.
  • Figma-code sync: This PoC was done with hex values extracted from Figma. A production implementation should verify these are the final approved values.
  • HC custom hex values: A few high-contrast overrides use custom hex values between scale steps. These are hard to maintain and should be documented.
  • borderColor.onMuted is new API: Consumers using borderColor-emphasis on bgColor-muted backgrounds should migrate to borderColor-onMuted. Doing this in the implementation will require migration guidance.
  • Display token overrides: The display.json5 file grew significantly (+1,000 lines) due to per-hue × per-theme overrides. Consider whether the override strategy scales or if a different approach is needed.
  • Redundant base and display tokens: Base and display scale tokens map to the exact same values. Moving froward with this approach might require a larger refactor/merge/deprecation strategy.
  • A complete overhaul of the color scales like the one in this PoC affects approximately 77% of the total color tokens in this library and introduces significant risks.

danielguillan and others added 10 commits March 30, 2026 13:17
Update semantic/functional token references to darker or lighter scale
steps to restore contrast ratios broken by the base color scale updates.
Fixes 251 of 278 failures; remaining 27 are pre-existing structural
constraints that existed before our changes.
- Add borderColor.onMuted token to all 19 display colors in display.json5.
  This new token is intended for borders rendered on top of display color
  card backgrounds (display-{color}-bgColor-muted), solving a structural
  impossibility where borderColor.emphasis cannot simultaneously satisfy
  contrast requirements against both near-black page backgrounds (dark HC)
  and very light pastel card backgrounds within the same theme.

- Update colorContrast.config.ts to test borderColor.onMuted (instead of
  borderColor.emphasis) against display-{color}-bgColor-muted, reflecting
  the intended usage split.

- Fix gray borderColor.emphasis dark overrides: steps were too dark to
  contrast against near-black page backgrounds in dark themes.
  dark: step 4→3, dark-HC/colorblind-HC/tritanopia-HC: step 5→3,
  dark-dimmed-HC: step 5→2.

- Fix gray borderColor.onMuted: default step was too light for light-theme
  gray card backgrounds. Default: step 4→6 (adds dark override at step 4
  to preserve dark theme appearance), HC: step 5→7.

- Fix lime borderColor.onMuted: default step 5→6, HC step 6→7.

- Fix purple borderColor.onMuted: default step 4→5 (step 5 satisfies ≥3:1
  against both light and dark bgColor-muted simultaneously).

Result: 0 contrast failures across all themes (down from 27 pre-existing
structural failures and 278 introduced by the brand scale update).
Resolve all contrast failures introduced by neutral and display scale
changes. Key fixes:

- Replace dark-mode neutral.13 refs with {base.color.white} where
  semantically white (fgColor, buttons, avatar, header, syntax, etc.)
- Adjust display token emphasis/muted steps for new scale values
- Add HC theme overrides for bgColor-muted, bgColor-neutral-muted,
  control.bgColor, and button-danger-bgColor
- Fix borderColor.emphasis default (neutral.8 → neutral.9)
- Reduce bgColor-success-muted alpha in dark-PD themes (0.2 → 0.15)

All 2579 contrast checks now pass across 13 themes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 30, 2026

⚠️ No Changeset found

Latest commit: 5ed6389

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 30, 2026

Design Token Diff (CSS)

The message is too long to be displayed here. For more details, please check the job summary.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 30, 2026

Design Token Diff (StyleLint)

The message is too long to be displayed here. For more details, please check the job summary.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 30, 2026

Design Token Diff (Figma)

The message is too long to be displayed here. For more details, please check the job summary.

@danielguillan danielguillan added the update snapshots Update visual regression test snapshots label Apr 30, 2026
@github-actions github-actions Bot removed the update snapshots Update visual regression test snapshots label Apr 30, 2026
@github-actions github-actions Bot temporarily deployed to Preview (Storybook) April 30, 2026 13:38 Inactive
lukasoppermann added a commit that referenced this pull request May 5, 2026
- Copied neutral scale from PR #1369 brand refactor branch
- Light: 13 steps with green-gray tones (fff0eb → 25292E)
- Dark: 13 steps with inverted green-gray (ffddd2 → 460701)
- Functional tokens NOT modified - only base scales
- Ready for contrast analysis and functional token adjustments

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lukasoppermann added a commit that referenced this pull request May 5, 2026
Analysis findings:
- Light mode emphasis backgrounds lose 60% contrast (unacceptable)
- Dark mode text becomes unreadable (91% contrast loss)
- Dark mode's warm color inversion breaks functional architecture
- Some tokens improve significantly (dark emphasis +48%)

Three implementation paths identified with tradeoffs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lukasoppermann added a commit that referenced this pull request May 5, 2026
Analysis of color collisions when mapping old neutral scale to PR #1369:
- Light theme: 7 new steps needed (0-7 compress into fewer tones)
- Dark theme: 9 new steps needed (0-7 all map to same warm tone)

Identified functional token usage across 5 files.
Proposed two-phase approach: interpolate missing steps, then batch-update all token references.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lukasoppermann added a commit that referenced this pull request May 5, 2026
Light mode:
- Steps 0-4: white + interpolations toward PR #1369 brand palette
- Steps 5-9: PR #1369 warm brand colors (orange/brown/red)
- Steps 10-13: PR #1369 grays (dark brand colors)

Dark mode:
- Steps 0-7: preserved old cool grays (no warm inversion issues)
- Step 8: kept as-is for smooth gray progression
- Step 9: adjusted to #8E949F for better interpolation toward light grays
- Steps 10-12: PR #1369 light gray section (preserved)
- Step 13: white

14-step architecture maintains 1:1 token mapping, avoids collisions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lukasoppermann added a commit that referenced this pull request May 5, 2026
…ep 9 interpolation

The dark.json5 file had accumulated formatting errors from the scale updates.
This restores it to a clean state with:
- Step 0: reference to base.color.black (from main)
- Steps 1-8: preserved cool gray values
- Step 9: #8E949F (interpolated value for smooth transition to PR #1369 grays)
- Steps 10-12: PR #1369 light grays

Validates successfully as JSON5. Build completes without errors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lukasoppermann added a commit that referenced this pull request May 5, 2026
- NEUTRAL_SCALE_COMPARISON.html: Interactive visual comparison showing:
  - Light and dark theme scales side-by-side
  - Touch-in-middle visualization: left=new, right=original, middle=split
  - PR #1369 reference colors with opacity for context
  - All 14 steps with hex values and contrast info

- PR_SUMMARY.md: Comprehensive overview of changes including:
  - Color value changes for light and dark scales
  - Functional token mapping strategy
  - Validation results (tests, contrast, build)
  - Key design decisions and rationale

Both files facilitate review and visual validation of scale refactor.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lukasoppermann added a commit that referenced this pull request May 5, 2026
…ette

Replace warm orange/brown brand colors with green-gray palette from PR #1369:
- Steps 0-4: White to light green-gray gradient
- Steps 5-9: Mid-tone green-grays
- Steps 10-13: Dark green-grays to near-black

This aligns with the cooler, more neutral aesthetic of PR #1369 while
maintaining the 14-step scale structure for backward compatibility.

Note: Functional tokens still reference old color values. Will be updated
in follow-up commit after contrast analysis.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lukasoppermann added a commit that referenced this pull request May 5, 2026
- Extract actual light theme neutral colors from main branch (cool blue-grays)
- Fix proposed colors to match PR #1369 green-gray palette exactly
- Remove hard dividing line; use smooth gradients for visual blending
- Add data tables showing hex values and changes per step
- Update dark theme comparison (same palette for now)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lukasoppermann added a commit that referenced this pull request May 5, 2026
All color scales (blue, green, red, yellow, orange, purple, pink) restored
to authentic values from main branch. Semantic colors correctly reference
their respective scales (fgColor-accent uses blue.5, fgColor-success uses
green.5, etc.).

Baseline: 155 WCAG contrast failures - all legitimate due to light semantic
text colors on light backgrounds.

Next: Implement contrast fix strategy with PR #1369 green-gray palette
tweaks and optional new intermediate steps.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lukasoppermann added a commit that referenced this pull request May 5, 2026
- Applied PR #1369 green-gray neutral palette to both light and dark themes
- Currently showing ~300 total contrast failures across all themes
- Requires comprehensive functional token group migrations to fix
- Next: identify which tokens need which step migrations
lukasoppermann added a commit that referenced this pull request May 5, 2026
- Applied full PR #1369: both light/dark palettes + all functional token updates
- Result: 291 total contrast failures across themes
- Indicates PR #1369 was incomplete or designed for incremental application
- Next: analyze failure patterns to identify additional migrations needed
lukasoppermann added a commit that referenced this pull request May 5, 2026
…failures

- Expanded neutral scale from 14 to 15 steps (added interpolated neutral.9)
- Renumbered old steps 9-13 to 10-14 in both light and dark palettes
- Migrated 155+ functional token references to new step numbers
- Applied all PR #1369 palette, functional, and component changes

Current status: 340 contrast failures (vs 272 before scale expansion)
Key issues identified:
- fgColor-muted (#758479) insufficient contrast vs white/light backgrounds
- control-fgColor-placeholder same issue
- Display colors (accent/teal) insufficient contrast on emphasis

Next: Fine-tune muted color step or apply additional tweaks

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant