# 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.5` and `pointer-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 (`md` size satisfies this). ## Do / Don't - ✅ One `primary` *or* one `accent` per surface, never both side-by-side. - ✅ Use `accent.gold` for the *forward-moving* action in a multi-step flow. - ❌ Don't hardcode `#6B35A7` — use `colors.brand.primary`. - ❌ Don't put two CTAs of equal emphasis next to each other.