--- phase: 41 slug: diagrams-icons-theme-engine status: draft shadcn_initialized: true preset: new-york / neutral / cssVariables / lucide created: 2026-04-04 --- # Phase 41 — UI Design Contract > Visual and interaction contract for Phase 41: Diagrams, Icons & Theme Engine. > Generated by gsd-ui-researcher. Verified by gsd-ui-checker. --- ## Design System | Property | Value | Source | |----------|-------|--------| | Tool | shadcn | components.json detected | | Style | new-york | components.json | | Preset | neutral base color, cssVariables, radius=0 | ui/src/index.css | | Component library | Radix UI (via shadcn) | components.json | | Icon library | lucide-react | components.json | | Font | System UI (inherited from body; no custom font loaded) | index.css | **Existing components available (no reinstall needed):** `button`, `badge`, `breadcrumb`, `card`, `checkbox`, `collapsible`, `command`, `dialog`, `dropdown-menu`, `input`, `label`, `popover`, `scroll-area`, `select`, `separator`, `sheet`, `skeleton`, `tabs`, `textarea`, `tooltip` **New shadcn components needed for Phase 41:** - `progress` — job progress bar (SSE render progress) - `toggle` — dark/light variant switcher in theme preview - `slider` — color seed hue picker (optional; Input[type=color] is acceptable fallback) --- ## Spacing Scale Declared values (multiples of 4). Source: existing Tailwind scale in project. | Token | Value | Usage | |-------|-------|-------| | xs | 4px | Icon gaps, badge padding, inline chip gaps | | sm | 8px | Compact element spacing, button icon gap | | md | 16px | Default card padding, form field spacing | | lg | 24px | Section padding, panel gaps | | xl | 32px | Layout column gaps, page section breaks | | 2xl | 48px | Major section breaks (e.g. diagram panel → source panel) | | 3xl | 64px | Not used in Phase 41 | **Exceptions (Phase 41 specific):** - Touch targets on coarse-pointer devices: `min-height: 44px` on all interactive controls (already enforced by `@media (pointer: coarse)` rule in index.css — no new work needed). - Diagram preview container: no fixed height. Use `overflow-x: auto` with `width: max-content; min-width: 100%` (matches `.paperclip-mermaid svg` pattern already in index.css). - Theme swatch grid: 8px gap between swatches, swatches 40×40px minimum. - Color seed input: 48px height to meet touch targets on mobile. --- ## Typography Source: index.css `.paperclip-markdown`, button.tsx, existing component patterns. | Role | Size | Weight | Line Height | Usage | |------|------|--------|-------------|-------| | Body | 15px (0.9375rem) | 400 (regular) | 1.6 | Diagram source editor, theme description text | | Label | 14px (0.875rem) | 400 (regular) | 1.5 | Form labels, badge text, panel section titles | | Heading | 20px (1.25rem) | 600 (semibold) | 1.3 | Panel titles ("Generate Diagram", "Theme Preview") | | Display | 28px (1.75rem) | 600 (semibold) | 1.2 | Not used in Phase 41 | **Declared weights: 2 — 400 (regular) and 600 (semibold).** - 400 (regular): body text, labels, badge text, monospace code blocks. - 600 (semibold): panel headings, dialog headings, section titles. **Monospace (code/source):** `ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace` at 14px, weight 400, line-height 1.6. Used for the Mermaid source collapsible panel and palette export code blocks. --- ## Color Source: index.css CSS custom properties — Catppuccin Latte (light) + Catppuccin Mocha (dark). | Role | Light value | Dark value | Usage | |------|-------------|------------|-------| | Dominant (60%) | `#eff1f5` (--background) | `#1e1e2e` (--background) | Page background, diagram canvas background | | Secondary (30%) | `#e6e9ef` (--card) | `#181825` (--card) | Diagram panel card, theme preview panel, icon result card | | Muted surface | `#ccd0da` (--secondary) | `#313244` (--secondary) | Source code panel background, export format tabs, collapsible header | | Accent (10%) | `#bcc0cc` (--accent) | `#45475a` (--accent) | Hover states on non-primary interactive elements | | Primary | `#1e66f5` (--primary) | `#89b4fa` (--primary) | See "Accent reserved for" below | | Destructive | `#d20f39` (--destructive) | `#f38ba8` (--destructive) | Destructive actions only | | Border | `#ccd0da` (--border) | `#313244` (--border) | Panel edges, dividers, input outlines | | Muted foreground | `#9ca0b0` (--muted-foreground) | `#6c7086` (--muted-foreground) | Helper text, secondary labels, status text | **Accent (--primary) reserved for:** 1. "Generate" / "Apply Theme" primary CTA buttons 2. Job progress bar fill 3. Active tab indicator in export format tabs 4. Seed color ring/focus ring on color input 5. WCAG PASS badges (green: use `--chart-2 #40a02b` light / `#a6e3a1` dark) 6. WCAG FAIL badges (red: use `--destructive`) **Theme Preview special case:** The theme preview panel injects CSS custom properties dynamically from the generated palette. It must not inherit `--primary` from the app shell. Scope theme preview under a `.nexus-theme-preview` container class so injected tokens do not leak into nav/sidebar. --- ## Component Inventory (Phase 41) ### Diagram Panel - **DiagramGeneratePanel** — Full-width card. Contains: prompt textarea (4 rows), diagram type selector (Select component, options: Architecture, Flowchart, ERD, Sequence, Mind Map), "Generate Diagram" Button (primary). - **DiagramPreview** — Renders SVG output inside `.paperclip-mermaid` container (reuse existing CSS class). Shows status line ("Rendering…" / error) using `.paperclip-mermaid-status` / `.paperclip-mermaid-status-error` classes. Download buttons (SVG, PNG) appear below the preview as ghost buttons. - **DiagramSourcePanel** — Collapsible (shadcn `collapsible`). Shows Mermaid source in monospace Textarea (read/write). "Copy source" IconButton at top-right. IconButton must carry `aria-label="Copy source"` and `title="Copy source"`. - **DiagramAttachToChatBadge** — After successful render, a badge appears in the conversation thread: "Diagram attached — SVG + PNG". Reuse ChatTaskCreatedBadge visual pattern. ### Icon Generation Panel - **IconGeneratePanel** — Card with: description textarea (3 rows), style selector (Select, options: Outline, Filled, Rounded), count selector (Select: 1, 4, 8, 16), "Generate Icons" Button (primary). - **IconResultGrid** — CSS grid, 4 columns on desktop / 2 on mobile. Each cell: white card, SVG preview centered, icon name label below (text-xs). Hover reveals download row (SVG, PNG 16, PNG 32, PNG 64) as a bottom sheet within the card. - **IconDownloadBar** — Appears below grid when any icon is selected (checkbox on card corner). "Download selected (N)" Button (primary), format selector (Select: SVG, PNG 16, PNG 32, PNG 64). ### Theme Engine Panel - **ThemeSeedInput** — Color picker (`` styled with ring) + hex text Input side-by-side. Label: "Seed color". Helper text: "We'll generate a full palette in OKLCH." - **ThemeVariantToggle** — Toggle group (light / dark), uses shadcn `Toggle`. Default: dark. - **ThemePaletteGrid** — Displays generated swatches. Two rows: Light variant, Dark variant. Columns: Background, Surface, Overlay, Text, Accent-1, Accent-2, Accent-3. Each swatch: 40×40px minimum, hex label below (text-xs, monospace), WCAG badge (AA PASS / FAIL) inline. - **ThemePreviewPanel** — Scoped under `.nexus-theme-preview`. Renders a mini mock of Nexus UI (sidebar strip + one card) with injected CSS variables. "Apply to Nexus" Button (primary, full-width at panel bottom). - **ThemeExportTabs** — Tabs component. Tabs: CSS Variables, Tailwind Config, VS Code Theme, JSON. Each tab: pre/code block (monospace 14px), "Copy export" IconButton top-right. IconButton must carry `aria-label="Copy {tab name}"` (e.g. `aria-label="Copy CSS Variables"`) and a matching `title` attribute. - **ThemeApplyConfirmDialog** — Dialog. Heading: "Apply theme?". Body: "This will update your Nexus color scheme. You can revert from Settings." Confirm: "Apply theme" (primary). Cancel: "Keep current" (ghost). --- ## Interaction Contracts ### Job Progress (shared pattern across all three generators) 1. User submits prompt → Button shows spinner + label "Generating…" (disabled). Primary CTA label changes in-place; no separate loading overlay. 2. SSE events arrive → Progress bar (shadcn `progress`, primary fill) animates from 0→100%. Progress bar sits directly below the CTA button, full-width of the panel. 3. On `ready`: progress bar disappears (fade out 200ms), result panel slides down (height animation 300ms ease-out). Button reverts to "Generate again" (secondary variant). 4. On `error`: progress bar fills destructive color, error message appears below bar ("Render failed — {detail}. Try again."), Button reverts to "Generate Diagram" (primary, enabled). 5. Reconnect on SSE disconnect: silent reconnect, no user-facing error unless render ultimately fails. ### Mermaid Source Collapsible - Default state: collapsed. - Trigger label: "View Mermaid source" (chevron right). Expanded: "Hide source" (chevron down). - Height transition: 250ms ease. - Textarea is editable. "Re-render diagram" Button (secondary, xs size) appears at bottom-right of expanded panel when source is modified. - Security stripping is server-side. No client-side feedback needed beyond standard error state. ### Theme Live Preview - Preview updates on every palette recalculation (debounced 150ms after seed color change). - No full-page refresh. CSS variables injected via JS into `.nexus-theme-preview` scope only. - "Apply to Nexus" triggers ThemeApplyConfirmDialog before writing to settings. - After apply: toast notification "Theme applied. Reload to see full effect." (not destructive; use default toast variant). ### Icon Selection - Checkbox appears on card hover (top-left corner, 16px). On coarse pointer: always visible. - Multi-select: selecting any card shows the DiagramDownloadBar at the bottom of the panel (sticky, z-index above scroll content). - Deselect all: "Clear selection" link in the sticky bar. --- ## Copywriting Contract | Element | Copy | |---------|------| | Diagram CTA | "Generate Diagram" | | Diagram generating state | "Generating…" | | Diagram re-render CTA | "Re-render diagram" | | Diagram download (SVG) | "Download SVG" | | Diagram download (PNG) | "Download PNG" | | Diagram source toggle (collapsed) | "View Mermaid source" | | Diagram source toggle (expanded) | "Hide source" | | Diagram attach confirmation | "Diagram attached — SVG + PNG" | | Icon CTA | "Generate Icons" | | Icon generating state | "Generating…" | | Icon download (selected) | "Download selected ({N})" | | Icon empty state heading | "No icons yet" | | Icon empty state body | "Describe what you need and we'll generate a cohesive set." | | Theme CTA | "Generate Palette" | | Theme generating state | "Generating…" | | Theme apply CTA | "Apply to Nexus" | | Theme apply dialog heading | "Apply theme?" | | Theme apply dialog body | "This will update your Nexus color scheme. You can revert from Settings." | | Theme apply confirm | "Apply theme" | | Theme apply cancel | "Keep current" | | Theme applied toast | "Theme applied. Reload to see full effect." | | WCAG pass badge | "AA" | | WCAG fail badge | "Fails AA" | | Export copy button (visible label) | "Copy {tab name}" (e.g. "Copy CSS Variables") | | Export copy button (aria-label) | `aria-label="Copy {tab name}"` matching visible label | | Export copied state | "Copied!" (reverts after 2s) | | Diagram source copy button (aria-label) | `aria-label="Copy source"` | | Generic render error | "Render failed — {detail}. Try again." | | Mermaid security strip notice | "Unsafe directives were removed before rendering." (shown as muted helper text below diagram, only when stripping occurred) | | Empty diagram state heading | "No diagram yet" | | Empty diagram state body | "Describe an architecture, flow, or sequence and we'll render it." | | Empty theme state heading | "No palette yet" | | Empty theme state body | "Pick a seed color to generate a full OKLCH palette with dark and light variants." | **Destructive actions in Phase 41:** None. "Apply theme" is reversible (can revert from Settings). Confirm dialog is informational, not destructive-red. --- ## Registry Safety | Registry | Blocks Used | Safety Gate | |----------|-------------|-------------| | shadcn official | `progress`, `toggle`, `slider` (optional) | not required | No third-party registries declared for Phase 41. --- ## Accessibility - All color swatches must render WCAG AA badge computed at runtime — not decorative. - Diagram SVG output passes DOMPurify before DOM insertion (server responsibility; client renders trusted output only). - Color seed `` must have an associated `