--- phase: 37 slug: web-chat-voice-ui status: draft shadcn_initialized: true preset: new-york / neutral / tailwind-v4 created: 2026-04-03 --- # Phase 37 — UI Design Contract > Visual and interaction contract for frontend phases. Generated by gsd-ui-researcher, verified by gsd-ui-checker. --- ## Design System | Property | Value | |----------|-------| | Tool | shadcn (new-york style) | | Preset | new-york, baseColor: neutral, cssVariables: true | | Component library | Radix UI (via shadcn) | | Icon library | lucide-react | | Font | System default (inherit from body) | Source: `components.json` detected + `npx shadcn info -c ui` confirmed. --- ## Spacing Scale Declared values (must be multiples of 4): | Token | Value | Usage | |-------|-------|-------| | xs | 4px | Icon gaps, waveform bar gaps, badge inner padding | | sm | 8px | Button icon padding, compact element spacing | | md | 16px | Chat message padding, input field padding | | lg | 24px | Panel section spacing | | xl | 32px | Layout gaps between major sections | | 2xl | 48px | Major section breaks | | 3xl | 64px | Page-level spacing | Exceptions: - Mic button and voice mode toggle touch target: 32px (h-8 w-8) to match existing VoiceRecordButton/TtsButton sizing pattern - Waveform canvas height: 32px fixed (h-8) to stay within input row --- ## Typography | Role | Size | Weight | Line Height | |------|------|--------|-------------| | Body | 14px (text-sm) | 400 (regular) | 1.5 | | Label | 12px (text-xs) | 400 (regular) | 1.4 | | Heading | 16px (text-base) | 600 (semibold) | 1.2 | | Display | 20px (text-xl) | 600 (semibold) | 1.2 | Source: Existing chat components use `text-sm` for message content, `text-xs` for file labels and badges. Matches `ChatMessage.tsx` and `ChatInput.tsx` patterns. --- ## Color | Role | Value | Usage | |------|-------|-------| | Dominant (60%) | `--background` (#eff1f5 light / #1e1e2e dark) | Chat surface, page background | | Secondary (30%) | `--secondary` (#ccd0da light / #313244 dark) | User message bubbles, sidebar | | Accent (10%) | `--primary` (#1e66f5 light / #89b4fa dark) | Active recording state, voice mode active indicator, audio player progress bar | | Destructive | `--destructive` (#d20f39 light / #f38ba8 dark) | Stop-recording button state (Square icon when recording), delete confirmations | Accent reserved for: 1. VoiceMicButton border/ring when in active recording state 2. Voice mode toggle active-state highlight (currently selected mode pill) 3. Audio player progress fill while audio is playing 4. Waveform bars while recording is live Source: `src/index.css` CSS variable definitions. Existing `VoiceRecordButton` uses `text-destructive` for stop state — contract preserves this pattern. --- ## Component Inventory New components to build for this phase: | Component | Location | Description | |-----------|----------|-------------| | `VoiceMicButton` | `ui/src/components/VoiceMicButton.tsx` | Replaces `VoiceRecordButton` — adds VAD auto-stop, waveform visualization, three visual states (idle / recording+waveform / processing) | | `VoiceWaveform` | `ui/src/components/VoiceWaveform.tsx` | Canvas-based amplitude bars, 30-50 data points, 32px tall, animated during recording only | | `VoiceModeToggle` | `ui/src/components/VoiceModeToggle.tsx` | Three-state pill toggle: "Text" / "Voice In" / "Full Voice" — persists via nexus-settings | | `ChatVoicePlayer` | `ui/src/components/ChatVoicePlayer.tsx` | Inline `