Migrate color scales and new brand colors#1407
Conversation
Replace the light neutral base scale with a 15-step green-tinted scale and resolve all resulting WCAG contrast failures. - Light default: bump fgColor muted/neutral, onEmphasis/white, and attention to the smallest step that passes contrast (190/0). - Light high-contrast themes (light-high-contrast, light-tritanopia, light-protanopia-deuteranopia): move neutral-backed tokens the smallest step to just pass 7:1 text / 4.5:1 border, scoped only to their HC override keys. All three now 186/0. No non-light themes touched; all 13 themes pass contrast. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Design Token Diff (CSS)The message is too long to be displayed here. For more details, please check the job summary. |
Design Token Diff (StyleLint)The message is too long to be displayed here. For more details, please check the job summary. |
Design Token Diff (Figma)The message is too long to be displayed here. For more details, please check the job summary. |
There was a problem hiding this comment.
Pull request overview
Updates Primer’s light neutral base scale to a new 15-step green-tinted ramp and adjusts a small set of light + light high-contrast functional/component tokens to eliminate resulting WCAG contrast failures, without altering dark or non-light themes.
Changes:
- Replace
base.color.light.neutralwith a new 15-step (0–14) ramp and updated HSL/hex values. - Increase several light foreground semantic tokens (
fgColor.muted,fgColor.neutral,fgColor.attention) and ensure “pure white” semantics (fgColor.white,fgColor.onEmphasis) still resolve to{base.color.white}rather than the new tinted neutral 0. - Adjust light high-contrast background/controls/button overrides (e.g.,
bgColor.muted,bgColor.neutral.*,control.bgColor.*, and select button hover/rest backgrounds) to meet stricter contrast thresholds.
Show a summary per file
| File | Description |
|---|---|
| src/tokens/base/color/light/light.json5 | Replaces the light neutral base scale with a new 15-step ramp (adds neutral.14, updates neutral.0–13). |
| src/tokens/functional/color/fgColor.json5 | Updates light foreground semantic steps for contrast; maps onEmphasis/white to {base.color.white} to remain truly white despite tinted neutral.0. |
| src/tokens/functional/color/bgColor.json5 | Tweaks light high-contrast overrides for muted + neutral semantic backgrounds to restore contrast compliance. |
| src/tokens/functional/color/control.json5 | Lightens light high-contrast control.bgColor.hover/active (and related HC fg overrides) to resolve contrast constraints. |
| src/tokens/component/button.json5 | Adds light high-contrast overrides for invisible hover and danger rest backgrounds to meet HC contrast requirements. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 5/5 changed files
- Comments generated: 0
- Review effort level: Low
- Move light high-contrast control surface (bgColor rest/active/hover/ selected) from relief step n4 to n3/B3 so the 7:1 control text relationship is anchored on a role step, not a relief step. Still passes (8.37:1). - Restore avatarStack fade backgrounds in light themes to the neutral step closest to their pre-change contrast: default neutral.7 -> n4, muted neutral.5 -> n3. Scoped to light variants only; dark unchanged. All 13 themes remain at 0 contrast failures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the 10-step light green scale with the 15-step proposal (adds B0, B2, both relief steps 04/08, and an extra dark B11). Fix the resulting contrast regression: fgColor.success (and open, which inherits from it) referenced green.5, which shifted lighter (#55db73, 1.71:1 on bgColor-default). Add a light override to green.9 (#137a33) — the minimum non-relief step passing 4.5:1 and the direct successor of the prior success anchor. Scoped to light only; dark themes unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the 10-step light lime display scale (base.display.color.lime in display-light.json5) with the 15-step proposal (adds B0, B1, both relief steps 04/08, and B10 + ext at the dark end). Fix the resulting contrast regressions in the six light themes by bumping the affected display-lime tokens to the smallest non-relief step that passes. Scoped via light / light-colorblind override keys so the dark display scale is untouched: - fgColor: light-tier -> lime.9, light-HC -> lime.11 - bgColor.emphasis: light-tier -> lime.9, light-HC -> lime.10 - borderColor.emphasis: light-tier -> lime.7, light-HC -> lime.9 All 13 themes back to 0 contrast failures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the 10-step light pine display scale (base.display.color.pine in display-light.json5) with the 15-step proposal. All 10 existing pine colors are preserved exactly and shift index to make room for the 5 additions: B0 (#e1fdee), the two relief steps 04/08, and B11 + ext at the dark end. No contrast fixes required: all display-pine token pairs still pass across the six light themes (and dark is unaffected — it resolves against the separate dark display scale). All 13 themes remain at 0 contrast failures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This reverts commit d12f8db.
The new pine scale shifted the mid-tones lighter, so display-pine fgColor, bgColor-emphasis and borderColor-emphasis stopped meeting contrast in the six light themes. Bump each to the smallest non-relief step that passes, scoped via light / light-colorblind override keys so the dark display scale is untouched: - fgColor: light-tier -> pine.7, light-HC -> pine.10 - bgColor.emphasis: light-tier -> pine.7, light-HC -> pine.10 - borderColor.emphasis: light-tier -> pine.6, light-HC -> pine.9 All 13 themes back to 0 contrast failures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This reverts commit 62e5857.
Override light teal base scale with 15-step proposal and fix WCAG contrast regressions via light-tier overrides (fgColor teal.9/HC teal.11, bgColor.emphasis teal.9/HC teal.10, borderColor.emphasis teal.7/HC teal.10). Dark themes untouched. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Author the provided 15-step dark lime/pine/teal base scales (light->dark order, kept inverted as intended). Remap the dark functional overrides (bgColor/fgColor/borderColor) to the nearest-equivalent steps in the new scales so dark themes preserve their prior appearance and pass all WCAG contrast checks. Fixes the broken dark token build that was blocking Storybook/VRT (missing lime.10/11, pine.10, teal.10/11 references). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restores contrast for contribution.default.bgColor.4 in light, light-tritanopia, and light-protanopia-deuteranopia by pointing them at base.color.green.9 (#137a33, 5.44:1) instead of the migrated green.6 (#0fbf3e, 2.46:1). Dark is unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The pink base retrofit left bgColor.sponsors.emphasis at pink.5 (#e22d9f) in dark themes, which only reaches 4.1:1 against fgColor.onEmphasis (white) — below the 4.5:1 minimum. Bump the dark override to pink.6 (#ca2186, 5.16:1), the minimum passing step. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The plum and auburn display retrofits remapped display.json5 but missed
component/label.json5 and functional/color/data-vis.json5, which also
reference base.display.color.{plum,auburn}.N directly. Because 5 steps
were inserted, each old index landed on a shifted color.
Remap those refs by the same lossless maps (light L, dark D) so every
label/data-vis plum & auburn token resolves to its original main color.
Verified: 0 diff vs main across 196 label/data-vis plum+auburn values
(14 themes); 0 contrast failures; full gate green.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Migrate base orange to the new 15-step scale (light + dark) and remap all 124 semantic/component refs to nearest-L* redesign values by side (light/dark). Extend the high-contrast and dark-dimmed variant orange scales to 15 steps, placing existing values at mapped positions so those 8 themes stay identical. Add dark overrides to the two severe.emphasis tokens that were default-only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Migrate base yellow to the new 15-step scale (light + dark) and remap all 34 semantic/component refs to nearest-L* redesign values by side (light/dark). Extend the high-contrast and dark-dimmed variant yellow scales to 15 steps, placing existing values at mapped positions so those 8 themes stay identical. Add dark overrides to the two attention.emphasis tokens that were default-only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Override the brown display scale with the new 15-step colors. The old
10-step scale is a lossless subset of the proposal, so every existing
brown color keeps its exact hex; the retrofit only inserts 5 new steps
(lighter B0 tint, two mid relief steps, a darker end, and an extended
step).
- base/color/light/display-light.json5: brown 10 -> 15 steps
- base/color/dark/display-dark.json5: brown 10 -> 15 steps (stored reversed)
- functional/color/display.json5: expand scale mirror to 15 identity
steps; remap semantic bgColor/fgColor/borderColor refs per-theme
(light L={0:1,1:2,2:3,3:5,4:6,5:7,6:9,7:10,8:11,9:12},
dark D={0:2,1:3,2:4,3:5,4:7,5:9,6:10,7:11,8:12,9:13})
- component/label.json5 + functional/color/data-vis.json5: remap refs
No contrast bumps needed (lossless). Full gate green; 0 contrast
failures; all 14 themes resolve brown semantics identically.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Override the lemon display scale with the new 15-step colors. Unlike the
lossless display retrofits, lemon is a redesign: the old 10 hexes are not
a subset of the proposal, so each existing lemon color shifts to its
nearest new step (nearest-L*, resolved to a strictly monotonic map).
- base/color/light/display-light.json5: lemon 10 -> 15 steps
- base/color/dark/display-dark.json5: lemon 10 -> 15 steps (stored reversed)
- functional/color/display.json5: expand scale mirror to 15 identity
steps; remap semantic refs per-theme
(light L={0:1,1:4,2:5,3:6,4:7,5:8,6:9,7:10,8:11,9:12},
dark D={0:2,1:3,2:4,3:5,4:6,5:7,6:8,7:9,8:11,9:12})
- component/label.json5, component/contribution.json5,
functional/color/data-vis.json5: remap refs
Contrast: since lemon is display-only, all themes share the redesigned
scale, so 24 pairs initially failed. Bumped to the minimum passing step:
bgColor.emphasis (light) lemon.8->9; fgColor (dark) lemon.8->9;
borderColor.emphasis (dark) lemon.7->8, (dark high-contrast) ->9,
(dark-dimmed high-contrast) ->10. Full gate green; 0 contrast failures.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Override the olive display scale with the new 15-step colors. The old
10-step scale is a lossless subset of the proposal, so every existing
olive color keeps its exact hex; the retrofit only inserts 5 new steps
(lighter tint, two mid relief steps, a darker end, and an extended step).
Note: the source tables had their light/dark headers swapped; colors
were placed by hex match so appearance is preserved (light themes use
the #F9FAD0…#1B1F17 ramp, dark themes the #ECDB5F…#0C1006 ramp).
- base/color/light/display-light.json5: olive 10 -> 15 steps
- base/color/dark/display-dark.json5: olive 10 -> 15 steps (stored reversed)
- functional/color/display.json5: expand scale mirror to 15 identity
steps; remap semantic bgColor/fgColor/borderColor refs per-theme
(light L={0:1,1:2,2:3,3:5,4:6,5:7,6:9,7:10,8:11,9:12},
dark D={0:2,1:3,2:4,3:5,4:7,5:9,6:10,7:11,8:12,9:13})
- component/label.json5 + functional/color/data-vis.json5: remap refs
No contrast bumps needed (lossless). Full gate green; 0 contrast
failures; all 14 themes resolve olive semantics identically.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Regenerate purple base scales to 15 steps (light + dark) and remap 12 downstream semantic tokens (done/upsell, ansi/prettylights/codeMirror entity). HC and dimmed themes pinned to prior resolved literals for zero visual drift. Bump fgColor.done dark override purple.5→purple.4 to clear WCAG contrast against bgColor-done-muted in dark themes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adopt the migrated base scales for display gray (←neutral), blue, red and coral (light + dark), expanding each 10→15 steps. Dark blue/red/coral values are reversed so display keeps step 0 = darkest and existing references stay aligned. Repoint 228 references in label, display and data-vis to the nearest new step to preserve appearance. Bump five display emphasis/border tokens to the minimum contrast-passing step (red/coral bgColor-emphasis light; gray borderColor-emphasis dark; red/coral borderColor-emphasis dark-dimmed-hc). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…h 2) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…earance Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ronger menu highlight Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a dark-theme override on borderColor.accent.emphasis so the focus ring / selected border resolves to blue.10 (#082a8f) instead of blue.9. Light theme is unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a dark-theme override on focus.outline-color so the focus ring resolves to blue.4 (#3094ff, 6.1:1) instead of inheriting the dark navy accent-emphasis (blue.10, ~1.6:1 which failed the 3:1 non-text minimum). Selected borders keep blue.10 and light theme is unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Repoints the light halloween bgColor-1 from lemon.7 (#a98906, dark mustard) to lemon.4 (#f2da3b), matching the expected bright yellow (orig #f0db3d). Passes all contrast checks; dark override unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Repoints the dark label.red.fgColor.rest from red.9 (#fa383d, vivid red) to red.11 (#fd8986), matching the expected softer salmon (orig #f27d83). Contrast 7.9:1 on the label bg; light theme unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Repoints the dark display.coral.fgColor override from red.9 (#fa383d, vivid red) to red.11 (#fd8986), matching the expected softer salmon (orig red.6 #f27d83). Contrast 7.9:1 on coral bgColor.muted; light theme (coral.9) unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Repoints the dark bgColor.inset override from raw base.color.black (#010409) to neutral.0 (#060907), so it participates in the migrated neutral scale and matches bgColor.default instead of reading as the old pure-black surface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace hardcoded dark override #4493F8 with {base.color.blue.4}
(#3094ff) so the link/accent color follows the migrated blue scale.
ΔE 1.6 from prior value; contrast 6.48:1 (default) / 5.99:1 (muted).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bump the segmented control / switch track: light neutral.3->neutral.2 (#e9f0eb), dark black->neutral.0 (#060907). No contrast regressions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
Migrates GitHub's core color scales to a new green-tinted, 15-step system (up from 14) and resolves every downstream WCAG contrast regression. Scope spans light and dark themes across the base (
neutral,green) and display (lime,pine,teal,green) scales, plus all functional and component tokens that consume them.All 13 themes pass contrast with 0 failures.
Base scales (
base.color.*)Neutral — light & dark migrated from 14 → 15 steps and re-toned green (was cool blue‑grey). The extra step adds mid‑tone resolution, and the ramps now end warm/dark rather than pure black/white.
Light neutral (n0 → n14):
#F9FBF9#F2F7F3#E9F0EB#D6E0D8#CBD6CD#B8C4BC#9CA89F#859188#6C786F#616D64#58635B#39423B#353C37#252B27#191F1BDark neutral (n0 → n14):
#060907#0F1511#191F1B#252B27#353C37#3B443E#434C45#4E5750#58635B#6C786F#9CA89F#B8C4BC#CBD6CD#D6E0D8#E9F0EBGreen — light base scale migrated to the 15-step proposal.
Display scales (
base.display.color.*)lime, pine, teal, green — light & dark expanded to 15-step scales and reindexed to match main's role convention. These drive the expressive surfaces: labels, data‑viz, and the contribution graph.
Downstream & component fixes
Everywhere the scales are consumed was reindexed and contrast‑tuned to stay as close to main's appearance as possible while passing:
pine,teal,green,limefg + bg (rest/hover/active) realigned to main at the minimum passing step (e.g. dark pine bg#082119/#0b3224/#0e4430).default.bgColorlevels 2/3/4 mapped togreen5 / 7 / 9→10.green/greenBrightandmarkup.insertedusegreen.9/green.10.lime/pine/tealmuted & emphasis tightened to min‑passing steps.danger/invisiblebackgrounds andcontrolfg/bg tuned (mainly for high‑contrast); fixed abutton.json5reindex miss and added aborderColor.emphasisdark override (→neutral.9) for the control border.bgColor-default→neutral.0(#060907) andbgColor-muted→neutral.1(#0F1511, incl. HC overrides) so PR/issue status text (open/closed/done) clears contrast over muted, while preservinginset<default<mutedelevation (insetstays pure black).Methodology
Verification
npm run lint && npm run format && npm run test && npm run build— all green.