Color
Senco uses 7 color groups — primary, accent, info, neutral, and 3 status colors. Each one maps to a specific UI function, not decoration. All pairings pass WCAG 2.1 AA contrast checks in both light and dark mode.
Palette
The base palette provides raw color values organized by function. Each group spans 10 shades from darkest (900) to lightest (50), used to differentiate contrast levels and visual hierarchy.
- Primary — Dark anchors for headings, text, and UI structure
- Accent — Brand blue for interactive elements, links, and focus states
- Info — Softer blue for informational feedback, distinct from brand accent
- Neutral — Gray scale for text hierarchy, borders, and surfaces
- Green / Yellow / Red — Status colors for success, warning, and error states
On-colors
Text and icon colors used on filled surfaces:
| Token | Value | Usage | |
|---|---|---|---|
#FFFFFF | on-accent | #FFFFFF | White text on accent-600 buttons |
#111827 | on-surface | #111827 | Dark text on light surfaces |
#FFFFFF | on-error | #FFFFFF | White text on error-600 |
Primary
Neutral / Gray
Accent / Blue
Green
Yellow
Red
Info
Semantic usage
Components reference semantic tokens, not raw palette values. This indirection allows theme switching and ensures consistent intent across the system.
| Token | Maps to | Purpose |
|---|---|---|
color-primary | {accent-600} | Brand, primary actions, links |
color-primary-hover | {accent-700} | Primary hover state |
color-primary-light | {accent-50} | Primary tinted backgrounds |
color-bg | {white} | Page background |
color-surface | {gray-100} | Card/section fill |
color-fg | {gray-700} | Body text |
color-heading | {primary-900} | Headings, strong text |
color-muted | {gray-500} | Secondary text, hints, labels |
color-border | {gray-200} | Dividers, input borders |
color-link | {accent-600} | Inline links |
color-focus | {accent-600} | Focus ring |
Feedback colors
Each feedback state uses a triplet of background, border, and text tokens for consistent signaling:
| State | Background | Border | Text |
|---|---|---|---|
| Info | {info-50} | {info-400} | {info-800} |
| Success | {green-50} | {green-400} | {green-800} |
| Warning | {yellow-50} | {yellow-400} | {yellow-900} |
| Error | {red-50} | {red-400} | {red-800} |
For the full token architecture (base → semantic → component), see Tokens.
| Semantic token | Base token | Resolved | |
|---|---|---|---|
| --ds-bg | --ds-white | ||
| --ds-fg | --ds-gray-700 | ||
| --ds-heading | --ds-primary-900 | ||
| --ds-muted | --ds-gray-500 | ||
| --ds-border | --ds-gray-200 | ||
| --ds-surface | --ds-gray-100 | ||
| --ds-primary | --ds-accent-600 | ||
| --ds-primary-hover | --ds-accent-700 | ||
| --ds-primary-light | --ds-accent-50 | ||
| --ds-success-bg | --ds-green-50 | ||
| --ds-success-border | --ds-green-400 | ||
| --ds-success-text | --ds-green-800 | ||
| --ds-warning-bg | --ds-yellow-50 | ||
| --ds-warning-border | --ds-yellow-400 | ||
| --ds-warning-text | --ds-yellow-900 | ||
| --ds-error-bg | --ds-red-50 | ||
| --ds-error-border | --ds-red-400 | ||
| --ds-error-text | --ds-red-800 | ||
| --ds-info-bg | --ds-info-50 | ||
| --ds-info-border | --ds-info-400 | ||
| --ds-info-text | --ds-info-800 |
Contrast verification
All color pairings are validated against WCAG 2.1 AA requirements: 4.5:1 for text, 3:1 for UI components.
Light mode (verified)
| Pairing | Foreground | Background | Ratio | Pass |
|---|---|---|---|---|
| Body text | #374151 | #FFFFFF | 10.31:1 | ✓ |
| Heading | #111827 | #FFFFFF | 17.74:1 | ✓ |
| Muted text | #636971 | #FFFFFF | 5.54:1 | ✓ |
| Muted on surface | #636971 | #F3F4F6 | 5.04:1 | ✓ |
| Primary link | #0F62FE | #FFFFFF | 5.00:1 | ✓ |
| Placeholder | #727780 | #FFFFFF | 4.50:1 | ✓ |
| White on primary btn | #FFFFFF | #0F62FE | 5.00:1 | ✓ |
| White on destructive | #FFFFFF | #BB4A4A | 5.01:1 | ✓ |
| Info text | #1E4D8C | #EFF6FF | 7.73:1 | ✓ |
| Success text | #2D6A4F | #F0FAF3 | 5.99:1 | ✓ |
| Warning text | #7C6A0A | #FEFAEB | 5.12:1 | ✓ |
| Error text | #8B2E2E | #FCF4F4 | 7.67:1 | ✓ |
For dark mode contrast verification, see Themes.
Key decisions
- Primary (
accent-600/#0F62FE) is used for all call-to-action purposes — white text passes 5.0:1 - Placeholder (
gray-400) darkened from#9CA3AFto#727780— passes 4.5:1 on white - Muted (
gray-500) darkened from#6B7280to#636971— passes 4.7:1 on surfaces - Status colors use softer values so the page doesn't feel alarming — all still pass AA contrast
/ BG: Usage guidelines
- Always use semantic tokens in components — never reference base palette directly
- Pair color with icon + text for status indicators (never color alone)
- Focus ring: 2px solid
color-focuswith 2px offset on all interactive elements - Disabled states: rely on both color and visual cues
background: var(--ds-surface);
Semantic tokens adapt to themes automatically.
background: #F3F4F6;
Hardcoded hex breaks in dark mode and ignores token updates.
Semantic colors with icon + background reinforcement. Success is clear at a glance.
Colored text on white — no background, no icon. Easy to miss and inaccessible.
Heading at 17.7:1, muted at 5.5:1 — both pass AA. Financial data must be readable.
Light gray text fails contrast. Users can't read their own transfer summary.