Agent skill
tools-ui-contrast-sweep
At user-specified breakpoints, audit the UI for contrast failures (text/background, icons, controls, focus indicators) and visual-uniformity drift (inconsistent tokens, typography, spacing, component variants). Produces screenshot-backed findings with WCAG-aligned thresholds and fix hypotheses.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/tools-ui-contrast-sweep
SKILL.md
Contrast + Uniformity Sweep
Audit rendered UI across explicit breakpoints and theme modes to find legibility and visual-system consistency failures.
This skill is diagnostic only: identify, evidence, classify, and propose fix direction. Do not redesign or patch code during the sweep unless explicitly requested.
Relationship to Other Skills
tools-web-breakpoint: responsive containment/reflow failures across breakpoints. Use together when contrast failures appear only after responsive stacking.lp-design-qa: static code/token/a11y audit without runtime screenshots. Use to trace root causes for repeated uniformity drift.meta-user-test: broad site-wide health audit. Use when route coverage should be sitemap-driven rather than operator-selected.lp-do-build: implement fixes after this report is approved.
Required First Prompt
If missing from operator input, ask exactly:
Which breakpoint widths (px) and which theme modes (light/dark/brand themes) should I test for contrast + uniformity?
Then collect required surfaces:
Which UI surfaces should be in scope (header/nav, primary CTAs, forms, modals, tables, marketing pages)?
Inputs
| Input | Required | Notes |
|---|---|---|
| Breakpoints (px) | Yes | e.g. 320, 375, 430, 768, 1024, 1280 |
| Theme modes | Yes | light/dark/brand themes |
| Target surfaces | Yes | scope-critical areas to audit |
| Standard | No (recommended) | default WCAG 2.x AA; operator may request AAA |
| Token references | No | tokens.ts, CSS vars, Tailwind/token docs |
If operator gives only breakpoints:
- default to
WCAG 2.x AA - run light mode first
- record assumptions explicitly in the report
Standards and Thresholds
Use these defaults unless operator requests otherwise.
WCAG AA defaults
- Normal text (
<18ptand<14pt bold):>= 4.5:1 - Large text (
>=18ptor>=14pt bold):>= 3.0:1 - Non-text essential UI (icons, borders, controls):
>= 3.0:1 - Focus indicators:
>= 3.0:1against adjacent colors and visibly discernible
If operator requests AAA
- Normal text:
>= 7.0:1 - Large text:
>= 4.5:1 - Non-text/focus checks remain at WCAG non-text contrast criteria (
>= 3.0:1)
Sampling requirement for complex backgrounds
For gradients/images/translucent overlays/blurred surfaces, sample multiple points and report:
- worst-case ratio (required)
- average ratio (recommended)
Repo Context to Load
Before auditing, load the visual-system baseline:
docs/design-system-handbook.mddocs/typography-and-color.mdpackages/themes/<theme>/src/tokens.ts(orpackages/themes/base/src/tokens.ts)packages/design-system/src/utils/style/overflowContainment.ts
For token drift triage, run static scans in affected app paths (examples):
- non-token colors:
rg -n "#[0-9a-fA-F]{3,8}|rgb\\(|hsl\\(" apps packages - default Tailwind palette drift:
rg -n "\\b(bg|text|border)-(red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900)\\b" apps packages - arbitrary sizing/spacing drift (triage only):
rg -n "\\[[0-9.]+(px|rem|em|vh|vw|%)\\]" apps packages
Workflow
1) Intake and Matrix Setup
- Confirm breakpoints, modes, surfaces, and standard (AA/AAA).
- Resolve route list from operator surfaces (or infer best-effort routes and mark assumptions).
- Set stable viewport height (default
900). - Prepare artifact folder and screenshot naming convention.
- Detect JS theme toggle — scan page source for
localStorage+data-theme(or equivalent cookie/class-based toggle). If found, expand the test matrix (see step 2a below).
2) Breakpoint Sweep Execution
For each breakpoint W and each mode:
- Set viewport to
W x 900. - Visit each target route/surface.
- Capture baseline screenshot.
- Run contrast checks and uniformity checks.
- Trigger interaction states where feasible:
- hover / active
- disabled
focus-visiblevia keyboard tab flow- modal/drawer/popover open states
- form error states (if low-friction to trigger)
2a) Split-State Testing (mandatory when JS theme toggle detected)
A JS toggle (localStorage, cookie, or data-theme attribute) and prefers-color-scheme are independent systems. They can disagree — e.g. OS in light mode but toggle previously set to dark. CSS variables controlled only by @media(prefers-color-scheme) are invisible to the toggle, causing broken mixed states that emulateMedia alone can never reproduce.
Always test all four combinations when a toggle exists:
emulateMedia |
localStorage/toggle | Scenario label |
|---|---|---|
| light | light | media-light/toggle-light (clean) |
| dark | dark | media-dark/toggle-dark (clean) |
| light | dark | media-light/toggle-dark ← most common user-facing breakage |
| dark | light | media-dark/toggle-light |
How to inject localStorage state in Playwright:
await page.goto(url, { waitUntil: 'load' });
await page.evaluate(() => localStorage.setItem('sl-theme', 'dark')); // or whatever key
await page.reload({ waitUntil: 'load' });
// confirm: await page.evaluate(() => document.documentElement.getAttribute('data-theme'))
What to check in split states:
- CSS custom properties that appear in
@media(prefers-color-scheme)but NOT inhtml[data-theme]— these will hold stale values in the mismatched state - Text colour vars (
--text,--text-muted) that come fromdata-themepaired against background/surface vars that come from@mediaonly (or vice versa) - Any component that hardcodes
color:#ffforcolor:#000while its background var is theme-switched
Flag as S1 if any split state produces unreadable text. The root cause is always: CSS variables split across two theming systems that don't fully overlap.
Recommended fix pattern: Make html[data-theme="dark/light"] the single authoritative source for ALL CSS vars. Keep @media(prefers-color-scheme) only as a FOUC fallback (it fires before JS runs). Since html[data-theme] has higher specificity than :root inside @media, it will always win once JS sets it.
3) Contrast Checks (priority order)
Audit:
- primary text blocks (body/headings/captions/helper text)
- interactive text (links, button labels, nav items)
- form affordances (placeholder, borders, error/success text)
- icons and badges (especially icon-only controls)
- focus rings/outlines during keyboard navigation
- overlay scenarios (scrims, translucency, image cards, gradients)
Flag contrast findings when:
- measured ratio is below threshold
- normal state is borderline and fails on hover/focus/disabled/error
- worst-case sample on gradient/image fails
- placeholder substitutes label with low contrast
- focus indicator exists but is visually indistinct
Evidence required per contrast finding:
- breakpoint + mode + route
- element label/selector/component best-effort
- state (
default|hover|focus|disabled|error|active) - measured ratio(s) with threshold (worst-case mandatory)
- screenshot with element clearly visible
4) Uniformity Checks (priority order)
Audit:
- color/token compliance and repeated non-token drift
- component consistency (buttons/links/inputs across routes)
- typography consistency (size/weight/line-height hierarchy)
- spacing/radius/shadow rhythm consistency
- dark-mode parity for hierarchy/affordances
Flag uniformity findings when:
- same component family differs materially in computed styles
- repeated non-token colors or inconsistent opacity values appear
- disabled/focus states differ across equivalent components
- same semantic meaning uses conflicting visual treatments
- hierarchy weakens (e.g., heading visually weaker than body)
Evidence required per uniformity finding:
- breakpoint + mode + route
- component family (best effort)
- exact observed difference (what differs and where)
- screenshot pair (
referencevsdrift) - likely cause hypothesis (token bypass/local override/missing variant)
5) Severity Model
- S1 Blocker: text/controls not reliably readable; critical actions obscured; focus effectively invisible for keyboard users
- S2 Major: widespread AA/AAA failures on key UI or system inconsistency harming trust/comprehension
- S3 Minor: localized drift/cosmetic inconsistency without material task failure
6) Responsive-vs-Palette Attribution Rule
If a contrast failure appears only at specific breakpoints due to layout/image stacking, classify as responsive root cause (with contrast impact), not pure palette failure. Cross-reference tools-web-breakpoint for follow-up.
7) Output Artifacts
Write report + screenshots:
- Report:
docs/audits/contrast-sweeps/YYYY-MM-DD-<slug>/contrast-uniformity-report.md - Screenshots:
docs/audits/contrast-sweeps/YYYY-MM-DD-<slug>/screenshots/
Optional machine-readable artifacts (recommended for regression tracking):
docs/audits/contrast-sweeps/YYYY-MM-DD-<slug>/contrast-findings.jsondocs/audits/contrast-sweeps/YYYY-MM-DD-<slug>/uniformity-findings.json
Use .claude/skills/tools-ui-contrast-sweep/modules/report-template.md for required structure.
8) Completion Message
Return:
- breakpoints and modes tested
- surfaces/routes covered
- issue totals by severity
- report path + JSON artifact paths (if produced)
- assumptions and uncovered scope gaps
If no issues are found, state exactly:
No contrast or visual-uniformity failures detected across the tested breakpoint/mode matrix.
- If issues were found and fixed via
/lp-do-build: re-run this sweep to confirm findings are resolved before routing totools-refactor. - If the page has a JS theme toggle: re-run must include all four split-state combinations, not just clean
emulateMediastates. A fix that only passes clean states may still fail in the mismatched case.
Guardrails
- Do not propose color changes that break brand intent without noting tradeoffs.
- Prefer token-level/component-variant fixes over per-page overrides.
- Validate
focus-visiblestates explicitly via keyboard path. - Avoid reporting micro-differences unless they affect readability, interaction, or hierarchy.
Integration
- Upstream:
lp-design-qa(optional trigger — contrast-sweep is often invoked after lp-design-qa flags color or accessibility concerns);lp-do-build(direct invocation for pre-launch QA pass). - Downstream:
tools-refactor(contrast and token findings feed the refactor entry criteria);lp-do-build(issues returned as structured findings for fix tasks). - Loop position: S9B secondary skill, required before S9B→SIGNALS advance (
GATE-UI-SWEEP-01). Also runs alongsidetools-ui-breakpoint-sweepat S9C for ongoing quality passes. - S9B advance requirement: When running this sweep for S9B→SIGNALS advance, the operator must manually set
Business: <BIZ>in the report frontmatter (the template includes a placeholder — replace it with the actual business identifier). All application routes must be covered;Routes-Tested: 0will block the advance gate. Both light and dark modes must be tested. All S1 blockers must be resolved before advancing.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?