241 lines
14 KiB
Markdown
241 lines
14 KiB
Markdown
---
|
||
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
|