feat: design system v1.0.0 — reconcile tokens from cross-repo audit

Extracted real production usage from 8 KDC repos and consolidated the
consensus (kdcsurveyadd / kdcvault / kdc_void_planner) into the canonical
design.md + tokens.

Highlights:
- brand.ink #000000 -> #1A1530 (purple-tinted, matches real usage)
- brand.canvas #F5F4F0 -> #F7F4ED (warm)
- neutral ramp rebuilt around ink (purple-tinted, not cold slate)
- semantic palette retuned for warm canvas + soft tints
- elevation shadows retinted with brand-ink rgb
- new accent.gold (product) and accent.mint (marketing) tokens
- real themes/light, themes/dark, themes/high-contrast
- fleshed out every component + foundation README
- docs/consolidation-2026-05.md captures the full audit + drift inventory

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Roberts
2026-05-17 17:51:39 +00:00
parent 5c6d703774
commit 6593bdf689
28 changed files with 904 additions and 247 deletions
+35 -11
View File
@@ -1,25 +1,49 @@
# Inputs
Specification for the **inputs** primitive.
Text inputs, textareas, selects. Single visual treatment, semantic states. Reference: `kdcvault/frontend/src/components/ui/input.tsx` and `.kdc-input` / `.kdc-input-underline` utilities in `kdcsurveyadd/app/globals.css`.
## Anatomy
TODO — drop `anatomy.svg` next to this file.
See `anatomy.svg`. Label · input shell · helper / error text. Label sits above the input; helper text below in `text.muted` `bodyS`.
## Variants
- default
- (list per-component variants)
| Token | Use | Background | Border |
|-------|-----|------------|--------|
| `input.default` | Standard field | `surface.background` | `border.default` (1px) |
| `input.filled` | High-density forms | `surface.subtle` | none |
| `input.underline` | Marketing / minimal forms | transparent | bottom 1px `border.default` |
## Sizes
| Size | Height | Padding |
|------|--------|---------|
| `sm` | 32px | `6px 10px` |
| `md` (default) | 40px | `8px 12px` |
| `lg` | 48px | `12px 16px` |
## States
default · hover · focus-visible · active/pressed · disabled · loading
- **Hover** — border `border.default``border.strong`, `120ms` transition.
- **Focus-visible** — apply `elevation.focusRing`, border `brand.primary`.
- **Disabled** — `opacity: 0.5`, `cursor: not-allowed`, background `surface.subtle`.
- **Error** — border `semantic.danger`, helper text `semantic.danger`, focus ring `rgba(176,56,47,0.18)`.
- **Read-only** — background `surface.subtle`, remove border, keep text colour.
## Tokens used
See `design.md``components.inputs.*`.
`components.input.*`, `elevation.focusRing`, `colors.border.*`, `colors.semantic.danger`.
## Accessibility
- All interactive instances are keyboard-reachable.
- Focus state has ≥ 3:1 contrast against its background.
- Pair color with an icon or text to convey meaning.
- Every input has a programmatically associated `<label>` (visible or `sr-only` only when an adjacent icon supplies meaning).
- Error messages reference the input via `aria-describedby` and use `role="alert"` on first appearance.
- Placeholder text is decorative — never the only label.
- Maintain 4.5:1 contrast on placeholder text (currently `text.muted` `#6B647A`).
## Do / Don't
- ✅ Use the canonical token references.
- ❌ Don't hardcode colors, sizes, or radii.
- ✅ Show errors *under* the input, not as a tooltip.
- ✅ Use `tabular-nums` for numeric-only inputs (`.tnum` utility).
- ❌ Don't use placeholder text as a label.
- ❌ Don't shrink the height below 32px — it breaks touch targets.