# 03. UI Primitive Library — Button, Card, Input, Badge, Modal, Toast

meta:
  id: shieldai-unified-restructure-03
  feature: shieldai-unified-restructure
  priority: P0
  depends_on: [shieldai-unified-restructure-01, shieldai-unified-restructure-02]
  tags: [frontend, components, design-system, solidjs]

objective:
- Build a reusable set of UI primitive components in SolidJS that match the ShieldAI theme and are used across all pages and features. These should feel cohesive with the Lendair component style but adapted for ShieldAI's security-focused brand.

deliverables:
- `web/src/components/ui/Button.tsx` — Variants: primary, secondary, ghost, danger. Sizes: sm, md, lg. States: disabled, loading.
- `web/src/components/ui/Card.tsx` — Container with gradient-card background, border, padding, and optional header/footer slots.
- `web/src/components/ui/Input.tsx` — Text input with label, error state, helper text, and focus ring. Types: text, email, password, number.
- `web/src/components/ui/Badge.tsx` — Status badges with variants: default, success, warning, error, info.
- `web/src/components/ui/Modal.tsx` — Accessible dialog with overlay, close button, focus trap, and animation.
- `web/src/components/ui/Toast.tsx` — Toast notification system (single component + `ToastProvider` context) with auto-dismiss, positions, and variants.
- `web/src/components/ui/index.ts` — Barrel export for all primitives.
- `web/src/components/ui/ui.test.ts` — Unit tests for each primitive.

steps:
1. Create `web/src/components/ui/` directory.
2. **Button**:
   - Props: `variant`, `size`, `disabled`, `loading`, `onClick`, `children`, `class` (merge with base)
   - Primary: `.gradient-primary` bg, white text, `.shadow-glow-primary`
   - Secondary: transparent bg, border, primary text
   - Ghost: transparent, no border, text only
   - Danger: red gradient bg
   - Loading state shows spinner SVG and disables interaction
3. **Card**:
   - Props: `children`, `class`, `header?`, `footer?`
   - Uses `.gradient-card`, `.border-border/50`, rounded-xl
4. **Input**:
   - Props: `label`, `type`, `value`, `onInput`, `error`, `helperText`, `placeholder`
   - Styled with bg-transparent, border, focus ring using `--color-focus-ring`
   - Error state adds red border and error text
5. **Badge**:
   - Props: `variant`, `children`
   - Small rounded pill with semantic color backgrounds
6. **Modal**:
   - Props: `isOpen`, `onClose`, `title`, `children`, `size?`
   - Uses SolidJS `Portal` for rendering outside DOM tree
   - Backdrop click closes; Escape key closes
   - Focus trap inside modal content
   - Enter/exit CSS transitions
7. **Toast**:
   - Create `ToastContext` with `showToast({ message, variant, duration })` API
   - `ToastProvider` renders a fixed-position container
   - Individual toasts auto-dismiss after duration (default 4s)
   - Variants: success, error, warning, info
8. Write unit tests for each component using Vitest + Testing Library.
9. Create barrel export `index.ts`.

steps:
- Unit: Each component renders correctly with default props
- Unit: Button variants produce correct CSS classes
- Unit: Input error state renders error message
- Unit: Modal open/close toggles visibility and calls onClose
- Unit: Toast context show/dismiss works and auto-dismiss fires
- Visual: Inspect all components in Storybook-style page (optional) or directly in landing page

acceptance_criteria:
- [ ] All 6 primitives exist in `web/src/components/ui/` with barrel export
- [ ] Each primitive has full TypeScript types
- [ ] Button supports all 4 variants, 3 sizes, disabled, and loading states
- [ ] Input supports error states and focus rings
- [ ] Modal is accessible (focus trap, ESC to close, backdrop click)
- [ ] Toast system can queue multiple toasts and auto-dismiss
- [ ] All components use theme tokens (no hardcoded colors)
- [ ] Unit tests pass with >80% coverage

validation:
- `cd web && pnpm test` runs and passes all UI tests
- Manual inspection: create a temporary `/ui-test` route importing all primitives and verify visual appearance in both light/dark modes

notes:
- Reference Lendair components: `~/code/Lendair/web/src/components/ui/Button.tsx`, `Card.tsx`, `Input.tsx`, `Modal.tsx`, `Toast.tsx`
- Keep components uncontrolled where possible (SolidJS signals for state) to avoid prop drilling.
- The `class` prop should always merge with base classes using a utility like `clsx` or `tailwind-merge`. Install if not present.
- Do NOT add business logic to primitives — they are purely presentational.
