- Home
- Custom Skills
- Accessible Color System
Accessible Color System
Builds a palette where every foreground/background pair meets WCAG AA. Includes dark mode.
Rating
Votes
0
score
Downloads
0
total
Price
Free
No login needed
Works With
About
Every designer eventually runs into the color contrast problem: the brand color is beautiful, the palette is tasteful, and none of it passes WCAG AA against the backgrounds it's supposed to sit on. The usual response is to darken one shade until the contrast checker turns green, which produces a palette that passes in the audit and looks wrong on the page.
This skill walks Claude through building a color system where every legal foreground/background pair passes WCAG AA from the start — including dark mode. Not by brute-forcing a contrast checker; by structuring the palette so the math works out. Primitive colors become role tokens, role tokens get contrast-verified pairings, and dark mode gets its own paired set, not a CSS filter: invert() and a prayer.
The procedure has five steps. First, elicit the brand colors and intent — the designer tells Claude what they want the product to feel like. Second, build a tonal ramp for each primitive color (usually 11 steps, 50–950, the Tailwind convention, because it's a ramp designers already know). Third, assign role tokens: color-text-primary, color-text-muted, color-surface-raised, color-border-subtle, etc. Fourth, verify every legal pairing against 4.5:1 for normal text and 3:1 for large text and non-text UI. Fifth, do the same in reverse for dark mode, with dark-mode-specific role tokens (not just inverting the ramp — that almost always fails).
The output is a token file the designer can drop into a design system, plus a contrast matrix showing every pairing and its ratio. Pairings that don't pass are flagged with the exact shade adjustment needed. No hand-waving, no "try making it darker".
Pair with Color Contrast Fix prompt for single-pair rescue work, Design System Token Pass skill for retroactively aligning components with the new palette, and The Design Systems Zealot for philosophy.
Who this is for: design-system leads, solo designer-developers, and <span class="whitespace-nowrap">a-gnt</span> teams who want a palette that ships in dark mode without late-night rework. Not for brand-identity design (logos, marketing) — those have different rules — and not for decorative-only color, where contrast doesn't apply.
Don't lose this
Three weeks from now, you'll want Accessible Color System again. Will you remember where to find it?
Save it to your library and the next time you need Accessible Color System, it’s one tap away — from any AI app you use. Group it into a bench with the rest of the team for that kind of task and you can pull the whole stack at once.
⚡ Pro tip for geeks: add a-gnt 🤵🏻♂️ as a custom connector in Claude or a custom GPT in ChatGPT — one click and your library is right there in the chat. Or, if you’re in an editor, install the a-gnt MCP server and say “use my [bench name]” in Claude Code, Cursor, VS Code, or Windsurf.
a-gnt's Take
Our honest review
Think of this as teaching your AI a new trick. Once you add it, builds a palette where every foreground/background pair meets wcag aa. includes dark mode — no extra apps or complicated setup needed. It's verified by the creator and completely free. This one just landed in the catalog — worth trying while it's fresh.
Tips for getting started
Save this as a .md file in your project folder, or paste it into your CLAUDE.md file. Your AI will automatically use it whenever the skill is relevant.
Soul File
---
name: Accessible Color System
description: Builds a color palette where every legal foreground/background pair meets WCAG AA, including dark mode.
when_to_use: Designer is building or rebuilding a color system and wants it to pass contrast from day one.
---
# Accessible Color System
## What this skill does
Walks a designer through building a role-based color palette with contrast-verified pairings in both light and dark mode. Output is a token file plus a contrast matrix — not a single passing color.
## When to load this skill
Load when the user says: "help me build a palette", "design a color system", "make our colors accessible", "we need dark mode colors", "why does our brand color fail contrast", or pastes a list of hex values and asks for a system around them.
## The procedure
### Step 1 — Elicit brand and intent
Before touching color math, ask three questions: (1) What brand colors are load-bearing — the ones marketing will refuse to change? (2) What's the product's feeling — serious, calm, playful, technical? (3) Is dark mode a first-class requirement or a nice-to-have? The answers shape every later decision. If the user has a style guide, request it. If they just have a hex code and a vibe, that's enough to start.
### Step 2 — Build tonal ramps for each primitive
For every primitive color (brand, neutral gray, plus any accent like success/warning/danger), build an 11-step tonal ramp from 50 (nearly white) to 950 (nearly black). Use the Tailwind convention because designers already read it. Keep the ramp perceptually uniform — equal lightness steps, not equal RGB steps. If the brand color is at step 500, say so; if it's darker or lighter, anchor it there and build around it. Do this for at minimum: brand, neutral, success, warning, danger. Every additional accent is a maintenance tax; keep the set small.
### Step 3 — Assign role tokens
Primitive colors are the raw material. Role tokens are what components actually use. Minimum set:
- `color-text-primary`, `color-text-secondary`, `color-text-muted`, `color-text-inverse`
- `color-surface-base`, `color-surface-raised`, `color-surface-sunken`, `color-surface-overlay`
- `color-border-subtle`, `color-border-strong`, `color-border-focus`
- `color-action-primary`, `color-action-primary-hover`, `color-action-primary-text`
- `color-status-success`, `color-status-warning`, `color-status-danger`, plus their text/background pairs
Map each role to a primitive ramp step in light mode. Example: `color-text-primary = neutral-900`, `color-surface-base = neutral-50`, `color-action-primary = brand-600`.
### Step 4 — Verify every legal pairing in light mode
Build the contrast matrix. For every role pair that can legally sit on top of another (text-primary on surface-base, action-primary-text on action-primary, border-focus on surface-raised), compute the contrast ratio. Requirements: 4.5:1 for normal text (below 18pt or 14pt bold), 3:1 for large text and for non-text UI components (button borders, focus rings, form borders, icons that convey meaning). Any pair that fails gets a specific fix: move the token up or down the ramp by one step and re-verify. Never paper over a failing pair with "just make it bolder".
### Step 5 — Build dark mode as a separate mapping, then verify
Dark mode is not "light mode with inverted lightness". It is a separate mapping from role tokens to primitive ramp steps, because perceptual contrast behaves differently on dark backgrounds. `color-text-primary` in dark mode is usually not `neutral-50` — it's closer to `neutral-100` or `neutral-200`, because pure white on pure black causes halation for some users. Similarly, `color-surface-base` is usually `neutral-900` or `neutral-950` but not `#000000`. Remap every role token for dark mode and re-run the contrast matrix. Expect some pairs that passed in light mode to fail in dark mode — that's why this step is separate.
### Step 6 — Return the token file and the matrix
Output two artifacts: (1) a token file in the user's preferred format (CSS custom properties, Tailwind config, JSON, Figma Tokens), with both modes; (2) a contrast matrix table showing every verified pair, its ratio, and whether it passes AA normal, AA large, or fails. Flag any pair still in violation with a specific adjustment. Close with a note on what's not covered: AAA (7:1), color-blindness simulation, and any case where a decorative gradient is used as the background. Hand off to [Color Contrast Fix](/agents/prompt-color-contrast-fix) for rescue work on any stubborn pair.
## A worked example
**User:** Building a palette for our reading app. Brand is `#4F46E5` (indigo). Feeling: calm, focused, slightly bookish. Dark mode is mandatory.
**Claude:** Three questions before I start. Got the brand color — indigo at roughly step 600 on the Tailwind ramp. For neutrals: pure gray, or warm (slight brown) or cool (slight blue)? Warm neutrals pair nicely with indigo and feel more bookish. Success/warning/danger: standard green/amber/red, or do you want bespoke?
**User:** Warm neutrals. Standard status colors.
**Claude:** Good. Building ramps.
**Primitives:**
- `brand`: indigo, 50–950. Anchor brand at 600 = `#4F46E5`.
- `neutral`: warm gray (stone), 50–950.
- `success`: green, 50–950. Anchor at 600.
- `warning`: amber, 50–950. Anchor at 500 (amber is perceptually brighter).
- `danger`: red, 50–950. Anchor at 600.
**Light mode role tokens:**
| Token | Primitive | Hex |
|---|---|---|
| text-primary | stone-900 | #1c1917 |
| text-secondary | stone-700 | #44403c |
| text-muted | stone-500 | #78716c |
| surface-base | stone-50 | #fafaf9 |
| surface-raised | #ffffff | #ffffff |
| border-subtle | stone-200 | #e7e5e4 |
| border-focus | brand-600 | #4F46E5 |
| action-primary | brand-600 | #4F46E5 |
| action-primary-text | #ffffff | #ffffff |
**Light-mode contrast matrix (selected pairs):**
- text-primary on surface-base: 16.1 : 1 — pass AA normal.
- text-secondary on surface-base: 8.4 : 1 — pass.
- text-muted on surface-base: 4.7 : 1 — pass AA normal (just).
- action-primary-text on action-primary: 6.1 : 1 — pass.
- border-focus on surface-raised: 4.3 : 1 — **pass AA non-text** (3:1 required).
- border-subtle on surface-base: 1.1 : 1 — **does not pass as a UI boundary.** Fix: use `border-subtle = stone-300` (`#d6d3d1`) for borders that must be visible, keep stone-200 for decorative dividers only.
**Dark mode role tokens (remapped, not inverted):**
| Token | Primitive | Hex |
|---|---|---|
| text-primary | stone-100 | #f5f5f4 |
| text-secondary | stone-300 | #d6d3d1 |
| text-muted | stone-400 | #a8a29e |
| surface-base | stone-950 | #0c0a09 |
| surface-raised | stone-900 | #1c1917 |
| border-subtle | stone-800 | #292524 |
| border-focus | brand-400 | #818cf8 |
| action-primary | brand-500 | #6366f1 |
| action-primary-text | stone-50 | #fafaf9 |
Note: action-primary shifted up one step (500 instead of 600) because indigo-600 on dark surface doesn't give enough perceptual pop, and border-focus moved up two steps (400 instead of 600) for the same reason. This is normal.
**Dark-mode contrast matrix (selected):**
- text-primary on surface-base: 17.4 : 1 — pass.
- text-muted on surface-base: 4.8 : 1 — pass AA normal.
- action-primary-text on action-primary: 5.9 : 1 — pass.
- border-focus on surface-raised: 7.2 : 1 — pass easily.
- border-subtle on surface-base: 1.9 : 1 — **does not pass as a UI boundary.** Same fix as light: use stone-700 for visible borders.
**Not covered by this pass:**
- AAA (7:1) — text-muted does not meet it in either mode; upgrade to stone-600 / stone-300 respectively if AAA is required.
- Color blindness: the status colors use common red/green/amber; pair them with icons or text, never color alone.
- Gradient backgrounds: if you use one behind body text, the contrast matrix is only valid at the darkest and lightest points of the gradient — you need to check both.
Ready for the token file in Tailwind config format, CSS variables, or JSON?
**User:** CSS variables please.
**Claude:** (outputs the full `:root` and `[data-theme="dark"]` blocks)
## What this skill will NOT do
- Will NOT paper over failing contrast with "just make it bolder". Failures get specific ramp adjustments.
- Will NOT invert light mode into dark mode automatically. Dark mode is built as a separate mapping.
- Will NOT use color alone to convey meaning. Status tokens ship with a note to pair them with icons or text.
- Will NOT claim the palette is AAA-compliant unless every pair has been verified at 7:1. AA is the default target.
- Will NOT design brand identity, logos, or marketing palettes. Different rules, different craft.What's New
Initial release
Ratings & Reviews
0.0
out of 5
0 ratings
No reviews yet. Be the first to share your experience.