docs: add comprehensive guide to color scales and contrast patterns#1361
docs: add comprehensive guide to color scales and contrast patterns#1361lukasoppermann wants to merge 7 commits intomainfrom
Conversation
Adds a lint script that detects when tokens are deleted or renamed without being documented in src/tokens/removed/. Compares the current working tree against the git merge-base with main to find token names that disappeared. Changes: - scripts/checkRemovedTokens.ts: main lint script - scripts/utilities/extractTokenNames.ts: token name extraction utility - scripts/utilities/extractTokenNames.test.ts: unit tests (7 cases) - package.json: lint:removed script, wired into npm run lint - .github/workflows/ci.yml: fetch-depth: 0 for base branch access - .husky/pre-commit: runs check against HEAD before each commit Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Rename color.json → removed.json as the single tracking file - Add 310 missing removed/renamed tokens from full version history: - v7.11.2 → v7.15.7: color scales, ansi, prettylights, fgColor renames (170) - v7.15.7 → v8.0.0: color.scale → base.color, gray → neutral (105) - v8.0.0 → v9.0.0: data.*.color, fgColor.*.@ renames (28) - v9.0.0 → v10.0.0: diffBlob restructuring (11) - v10.0.0 → v10.4.0: motion, outline.focus, button changes (7) - v11.0.0 → v11.7.0: lineBoxHeight, shadow.floating.legacy (7) - Document removal/rename process in token-authoring.md - Total: 757 entries (447 existing + 310 new) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Document base scale structure (13 steps 0-13) - Explain functional tokens and how they layer on base scales - Detail WCAG 2.1 AA contrast requirements - Show how changes propagate through themes - Include best practices for scale modifications - Link to relevant ADRs and scripts Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
There was a problem hiding this comment.
Pull request overview
This PR adds new documentation describing Primer’s color scales and contrast constraints, and also introduces tooling/CI changes to enforce documenting removed/renamed tokens.
Changes:
- Added
COLOR_SCALES.mdguide covering base scales, functional tokens, and contrast checking. - Added a removed-token lint script (
scripts/checkRemovedTokens.ts) plus token-name extraction utility + tests. - Consolidated removed token mappings into
src/tokens/removed/removed.json, wired the check intonpm run lint, and adjusted CI checkout depth.
Show a summary per file
| File | Description |
|---|---|
COLOR_SCALES.md |
New documentation for color scales/contrast; currently has a few accuracy issues. |
contributor-docs/agents/token-authoring.md |
Documents the new “removed/renamed tokens must be recorded” workflow. |
scripts/checkRemovedTokens.ts |
New lint script to detect removed tokens vs base branch and require documentation. |
scripts/utilities/extractTokenNames.ts |
Utility to extract dot-path token names from parsed token JSON5. |
scripts/utilities/extractTokenNames.test.ts |
Unit tests for token-name extraction behavior. |
src/tokens/removed/removed.json |
New consolidated registry of removed tokens and replacements. |
src/tokens/removed/color.json |
Deleted in favor of the consolidated removed-token registry. |
package.json |
Adds lint:removed to lint pipeline; adds Husky prepare hook. |
package-lock.json |
Lockfile updates for new dev dependencies. |
.husky/pre-commit |
Adds pre-commit hook invoking the removed-token check (currently ineffective). |
.github/workflows/ci.yml |
Ensures full git history is available (fetch-depth 0). |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 10/11 changed files
- Comments generated: 7
| "lint": "eslint '**/*.{js,ts,tsx,md,mdx}' --config eslint.config.mjs && npm run lint:tokens && npm run lint:removed", | ||
| "lint:fix": "eslint '**/*.{js,ts,tsx,md,mdx}' --fix --max-warnings=0 --config eslint.config.mjs", | ||
| "lint:tokens": "tsx ./scripts/validateTokenJson.ts", | ||
| "lint:removed": "tsx ./scripts/checkRemovedTokens.ts", |
There was a problem hiding this comment.
The PR description is scoped to adding a color-scales/contrast guide, but this diff also adds a new removed-token lint/check script, Husky hook wiring, and a CI checkout-depth change. Either update the PR description/title to reflect these additional behavioral/tooling changes or split them into a separate PR to keep review and rollout risk manageable.
There was a problem hiding this comment.
@copilot Can you move those changes into a new PR and a different branch?
|
|
||
| ### Scale Structure | ||
|
|
||
| Each base scale has **13 steps** (0–13): |
There was a problem hiding this comment.
“13 steps (0–13)” is inconsistent: 0 through 13 inclusive is 14 steps. The repo’s base scales (e.g. base.color.neutral) do include keys 0…13, so the text should say “14 steps (0–13)” (or adjust the range if that’s not intended).
There was a problem hiding this comment.
Fixed in 9a65447 — updated "13 steps (0–13)" to "14 steps (0–13)" and corrected all other "13 steps" count references in the file (theme table, FAQ section).
| npm run build:tokens # Generates all token files | ||
| npm run check:contrast # Runs contrast test |
There was a problem hiding this comment.
The documented contrast command npm run check:contrast doesn’t exist in this repo (the script is validate:contrast). Update the doc to reference the actual package script name so readers can run the check successfully.
| npm run build:tokens # Generates all token files | |
| npm run check:contrast # Runs contrast test | |
| npm run build:tokens # Generates all token files | |
| npm run validate:contrast # Runs contrast test |
| for (const file of files) { | ||
| try { | ||
| const content = fs.readFileSync(path.join(REMOVED_DIR, file), 'utf-8') | ||
| const parsed = JSON.parse(content) |
There was a problem hiding this comment.
collectDocumentedRemovals() reads both .json and .json5 files but uses JSON.parse(), which will fail for valid JSON5 (comments/trailing commas). Either restrict the scan to .json only or parse with json5.parse() for .json5 to avoid the removed-token lint becoming brittle as soon as someone adds a JSON5 file.
| const parsed = JSON.parse(content) | |
| const parsed = file.endsWith('.json5') ? json5.parse(content) : JSON.parse(content) |
| const baseRef = getArg('--base') ?? process.env.BASE_REF ?? 'main' | ||
| const isCI = process.env.CI === 'true' | ||
|
|
||
| const baseCommit = getBaseCommit(baseRef) | ||
|
|
||
| if (!baseCommit) { | ||
| if (isCI) { | ||
| console.error(`❌ Could not find merge-base with "${baseRef}". Ensure the base branch is fetched.`) | ||
| process.exit(1) | ||
| } | ||
| console.log(`⏭️ Skipping removed token check: could not resolve base ref "${baseRef}"`) |
There was a problem hiding this comment.
Defaulting baseRef to main is likely to fail in GitHub Actions because actions/checkout typically fetches origin/main but does not create a local main ref. Consider defaulting to origin/main, using GITHUB_BASE_REF when present, and/or falling back to origin/${baseRef} when git merge-base fails, otherwise npm run lint will hard-fail in CI even when no tokens were removed.
| const baseRef = getArg('--base') ?? process.env.BASE_REF ?? 'main' | |
| const isCI = process.env.CI === 'true' | |
| const baseCommit = getBaseCommit(baseRef) | |
| if (!baseCommit) { | |
| if (isCI) { | |
| console.error(`❌ Could not find merge-base with "${baseRef}". Ensure the base branch is fetched.`) | |
| process.exit(1) | |
| } | |
| console.log(`⏭️ Skipping removed token check: could not resolve base ref "${baseRef}"`) | |
| const requestedBaseRef = | |
| getArg('--base') ?? process.env.GITHUB_BASE_REF ?? process.env.BASE_REF ?? 'origin/main' | |
| const isCI = process.env.CI === 'true' | |
| const baseRefCandidates = [...new Set([ | |
| requestedBaseRef, | |
| requestedBaseRef.startsWith('origin/') ? requestedBaseRef.slice('origin/'.length) : `origin/${requestedBaseRef}`, | |
| ])] | |
| let baseRef: string | null = null | |
| let baseCommit: string | null = null | |
| for (const candidate of baseRefCandidates) { | |
| baseCommit = getBaseCommit(candidate) | |
| if (baseCommit) { | |
| baseRef = candidate | |
| break | |
| } | |
| } | |
| if (!baseCommit) { | |
| const attemptedRefs = baseRefCandidates.map(ref => `"${ref}"`).join(', ') | |
| if (isCI) { | |
| console.error(`❌ Could not find merge-base with any of: ${attemptedRefs}. Ensure the base branch is fetched.`) | |
| process.exit(1) | |
| } | |
| console.log(`⏭️ Skipping removed token check: could not resolve base ref from ${attemptedRefs}`) |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@lukasoppermann I've opened a new pull request, #1362, to work on those changes. Once the pull request is ready, I'll request review from you. |
Agent-Logs-Url: https://github.com/primer/primitives/sessions/55bdd2b5-fb9a-47e2-bcb5-62c9fecfb7e9 Co-authored-by: lukasoppermann <813754+lukasoppermann@users.noreply.github.com>
- Add contrast requirements (WCAG 2.1 AA rules) - Document three semantic regions of neutral scale (light, transition, text) - Explain the 7↔8 lightness break and its architectural importance - Show contrast matrix for neutral steps vs. functional tokens - Clarify why functional tokens anchor at specific steps - Document why scale changes cascade and propose solutions - Include practical examples of contrast patterns in use Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@copilot the new PR removes all the tooling changes, but I also need a second PR that include only the tooling changes. |
|
@lukasoppermann I've opened a new pull request, #1363, to work on those changes. Once the pull request is ready, I'll request review from you. |
…RemovedTokens issues - Remove COLOR_SCALES.md: this file belongs in the docs PR (#1361), not the tooling PR - Fix JSON5 parsing: use json5.parse() for .json5 files in collectDocumentedRemovals() - Fix baseRef defaulting: default to 'origin/main' instead of 'main', try both origin/ prefixed and unprefixed variants, handle empty env vars with || operator - Add GITHUB_BASE_REF support for GitHub Actions context
Overview
Added a new document explaining how Primer's color system works:
Why now?
This context is needed for evaluating design decisions (like PR #1340) and serves as reference material for future color system work.
Target audience