6593bdf689
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>
2.5 KiB
2.5 KiB
Buttons
Specification for the buttons primitive, reconciled from production usage in kdcsurveyadd, kdcvault, and kdc_void_planner (CVA-driven shadcn variants).
Anatomy
See anatomy.svg — label · optional leading/trailing icon · 8px gap · 40px height (default size).
Variants
| Token | Use | Background | Text |
|---|---|---|---|
button.primary |
Default CTA (one per surface) | brand.primary |
text.inverse |
button.accent |
Emphasis / submit / commit action | accent.gold |
text.inverse |
button.secondary |
Neutral default action | surface.subtle |
text.default |
button.outline |
Lower-emphasis bordered | transparent | text.default + border.strong |
button.ghost |
Tertiary, inline within text | transparent | brand.primary |
button.destructive |
Irreversible negative action | semantic.danger |
text.inverse |
button.link |
Visually a link, behaves as a button | transparent | brand.primary (underlined on hover) |
Reference implementation: kdcvault/frontend/src/components/ui/button.tsx (class-variance-authority).
Sizes
| Size | Height | Padding | Typography |
|---|---|---|---|
xs |
28px | 4px 10px |
caption |
sm |
32px | 6px 12px |
bodyS |
md (default) |
40px | 10px 16px |
bodyM |
lg |
48px | 12px 20px |
bodyM |
icon |
40×40px | 0 |
— |
States
default · hover · focus-visible · active/pressed · disabled · loading
- Hover swaps
primary→primaryHover(#5C2D90), darkens accent by ~12%. - Focus-visible applies
elevation.focusRing(0 0 0 3px rgba(107,53,167,0.18)). - Disabled sets
opacity: 0.5andpointer-events: none. Keep colour — don't desaturate. - Loading swaps the label for a 14px spinner; preserve width to avoid layout shift.
Tokens used
See design.md → components.button.* and elevation.focusRing.
Accessibility
- All buttons are keyboard-reachable and have a visible focus ring.
- Icon-only buttons must carry
aria-label. - Focus and hover states meet ≥ 3:1 contrast against the button surface.
- Touch target ≥ 44×44px on mobile (
mdsize satisfies this).
Do / Don't
- ✅ One
primaryor oneaccentper surface, never both side-by-side. - ✅ Use
accent.goldfor the forward-moving action in a multi-step flow. - ❌ Don't hardcode
#6B35A7— usecolors.brand.primary. - ❌ Don't put two CTAs of equal emphasis next to each other.