nexus/.planning/phases/41-diagrams-icons-theme-engine/41-UI-SPEC.md

241 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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 (`<input type="color">` 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 `<input type="color">` must have an associated `<label>` with `for` binding.
- Icon grid checkboxes must have `aria-label="Select {icon name}"`.
- Progress bar must use `role="progressbar"` with `aria-valuenow`, `aria-valuemin=0`, `aria-valuemax=100`.
- Theme preview panel: `aria-label="Theme preview"` on the container, `aria-live="polite"` for palette update announcements.
- DiagramSourcePanel "Copy source" IconButton: `aria-label="Copy source"` and `title="Copy source"` required (no visible text label on the icon-only button).
- ThemeExportTabs copy IconButton per tab: `aria-label="Copy {tab name}"` and `title="Copy {tab name}"` required (e.g. `aria-label="Copy CSS Variables"`).
- Keyboard: Tab order in ThemeExportTabs follows tab order; Copy button reachable via keyboard.
- `prefers-reduced-motion`: disable height/slide animations for collapsible and result panel; keep progress bar (functional feedback).
---
## Checker Sign-Off
- [ ] Dimension 1 Copywriting: PASS
- [ ] Dimension 2 Visuals: PASS
- [ ] Dimension 3 Color: PASS
- [ ] Dimension 4 Typography: PASS
- [ ] Dimension 5 Spacing: PASS
- [ ] Dimension 6 Registry Safety: PASS
**Approval:** pending