From 6ff793bf4515f33dd146b7e9636aa78dad1e240f Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Sat, 21 Mar 2026 22:36:03 -0400 Subject: [PATCH 01/37] =?UTF-8?q?docs:=20swap=20to=20Design=20System=20v4?= =?UTF-8?q?=20=E2=80=94=20flat=20dark=20theme,=20no=20glass=20morphism?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add DESIGN-SYSTEM.md as single source of truth for all design decisions - Update CLAUDE.md branding and design system sections to reference new system - Archive UI-DESIGN-SYSTEM.md to docs/archive/design-docs/ - Update tech stack styling line and quick reference table The new design system moves from glassmorphism/gradients to a flat, high-contrast dark theme inspired by Sentry/PostHog. Light mode planned. CSS implementation to follow in a separate branch. Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 66 +-- DESIGN-SYSTEM.md | 378 ++++++++++++++++++ .../archive/design-docs/UI-DESIGN-SYSTEM.md | 0 3 files changed, 411 insertions(+), 33 deletions(-) create mode 100644 DESIGN-SYSTEM.md rename UI-DESIGN-SYSTEM.md => docs/archive/design-docs/UI-DESIGN-SYSTEM.md (100%) diff --git a/CLAUDE.md b/CLAUDE.md index c75453bb..1d65028a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,29 +19,29 @@ | Repository / directory / database / Docker | `patherly` / `patherly_postgres` | | Backend, frontend UI, production URLs | **ResolutionFlow** | -- **Design:** Dark glassmorphism with ice-cyan accent gradient (`#06b6d4` → `#22d3ee`). Charcoal backgrounds, frosted-glass cards with `backdrop-filter: blur()`, orchestrated page-load animations, bold display typography. Design doc: [docs/plans/2026-03-03-aesthetic-redesign-design.md](docs/plans/2026-03-03-aesthetic-redesign-design.md) -- **Fonts:** Bricolage Grotesque (`font-heading`, headings/titles), IBM Plex Sans (`font-sans`, body text), JetBrains Mono (`font-label`, labels/badges/timestamps) — loaded via Google Fonts -- **Logo:** Inline SVG in `BrandLogo.tsx` (decision-tree icon with cyan gradient). Wordmark: "Resolution" in `text-foreground` + "Flow" in `text-gradient-brand` -- **Brand assets:** `brand-assets/` (source SVGs + brand-guide.html), `frontend/src/assets/brand/` (app assets), `frontend/public/icons/` (favicon) -- **CSS utilities:** `text-gradient-brand`, `bg-gradient-brand`, `bg-gradient-brand-hover` (defined in `index.css` via `@theme`). Glass utilities: `.glass-card` (interactive, `scale(1.02)` hover), `.glass-card-static` (no hover transform), `.active-glow` (breathing cyan shadow) -- **Layout:** App shell with persistent sidebar + top bar + main content (CSS Grid). Two fixed atmosphere orbs (cyan top-right, purple bottom-left) behind the shell for ambient glow. See [UI-DESIGN-SYSTEM.md](UI-DESIGN-SYSTEM.md) -- **Navigation:** Sidebar nav with type sub-items (All Flows → Troubleshooting / Projects / Maintenance). Pinned flows section for quick access. NO workspace switcher. See [UI-DESIGN-SYSTEM.md](UI-DESIGN-SYSTEM.md) +- **Design system:** [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) — THE source of truth for all design decisions +- **Design aesthetic:** Flat, high-contrast dark theme (Sentry/PostHog-inspired). No glass morphism, no gradients on surfaces, no ambient effects. Light mode planned. +- **Accent color:** Cyan (#22d3ee / #06b6d4). Used sparingly — ≤5% of the UI. +- **Fonts:** IBM Plex Sans (`font-sans`, body), Bricolage Grotesque (`font-heading`, headings), JetBrains Mono (`font-mono`, code) — loaded via Google Fonts +- **Logo:** 30px gradient square (cyan) + "ResolutionFlow" in Bricolage Grotesque 700 +- **Layout:** Icon rail sidebar (72px default) with hover flyout panels. Pinnable to full 260px sidebar. See [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) +- **Brand assets:** `brand-assets/` (source SVGs), `frontend/src/assets/brand/` (app assets), `frontend/public/icons/` (favicon) - **Terminology:** User-facing label is "Flows" (not "Trees"). Procedural flows are called "Projects" in the UI. Maintenance flows are called "Maintenance" in the UI. `tree_type` column values unchanged in DB. -- **Rebrand guide:** [REBRAND-IMPLEMENTATION-GUIDE.md](docs/archive/REBRAND-IMPLEMENTATION-GUIDE.md) +- **Reference mockups:** `docs/mockups/` (HTML files, open in browser) **Component styling rules:** -- Primary buttons: `bg-gradient-brand` (cyan `135deg`) with `shadow-lg shadow-primary/20`, hover `opacity-0.9`, active `scale(0.97)` -- Secondary buttons: `bg-[rgba(255,255,255,0.04)]` with `border-[rgba(255,255,255,0.06)]`, hover brightens border -- Active nav items: `bg-primary/10` background + 3px left cyan gradient accent bar -- Stat values: use `text-gradient-brand` for highlighted metrics -- Status colors: emerald-400 (success), amber-400 (in-progress), rose-500 (error/critical) -- Category dots: 8px colored circles using the category color palette -- Tags/badges: `font-label` (JetBrains Mono), small rounded chips with `bg-card border-border` -- Cards: `.glass-card` (interactive) or `.glass-card-static` (non-interactive) — semi-transparent bg with `backdrop-filter: blur(16px)`, `border-radius: 16px` -- Section labels: `font-label text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground` +- Primary buttons: solid `accent` background (#22d3ee), white text, 5px radius +- Ghost buttons: transparent with 1px `border-default`, hover `bg-elevated` +- Cards: `bg-card` with 1px `border-default`, 8px radius. NO shadows, NO blur, NO gradients. +- Badges: pill-shaped (20px radius), semantic dim background + matching text color +- Active nav: `accent-dim` background + `accent-text` color + 3px left accent bar +- Stat cards: 3px colored left border (accent/success/warning by position) +- Code blocks: `bg-code` with JetBrains Mono, material-inspired syntax highlighting +- Status colors: green/`#34d399` (success), amber/`#fbbf24` (warning), red/`#f87171` (danger) — ONLY for semantic meaning +- Section labels: 10px, 600 weight, uppercase, `text-muted`, 1.2px letter-spacing -When adding new pages/components: use "ResolutionFlow" branding, ice-cyan gradient accent theme, `.glass-card` / `.glass-card-static` containers, `text-foreground`/`text-muted-foreground` hierarchy. Primary actions use `bg-gradient-brand`. Pages render inside the app shell (CSS Grid: topbar + sidebar + main). Use "Flows" not "Trees" in all user-facing text; use "Projects" not "Procedures" for procedural flows. Reference [UI-DESIGN-SYSTEM.md](UI-DESIGN-SYSTEM.md) for layout patterns, navigation, and component specs. +When adding new pages/components: reference [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md). Use flat dark surfaces, 1px borders, no decorative effects. All colors via CSS variables. Use "Flows" not "Trees" in all user-facing text; use "Projects" not "Procedures" for procedural flows. ## Implementation Principles @@ -97,7 +97,7 @@ When adding new pages/components: use "ResolutionFlow" branding, ice-cyan gradie ### Frontend - **Framework:** React 19 + Vite + TypeScript -- **Styling:** Tailwind CSS v4 (`@tailwindcss/vite` plugin, CSS-only config in `index.css`) — dark-first with ice-cyan gradient accents (see Branding section) +- **Styling:** Tailwind CSS v4 (`@tailwindcss/vite` plugin, CSS-only config in `index.css`) — flat dark theme with cyan accent (see [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md)) - **State:** Zustand (with immer + zundo for undo/redo) - **Routing:** React Router v7 - **API Client:** Axios with token refresh interceptor @@ -379,20 +379,20 @@ gh run view --json jobs --jq '.jobs[] | {name: .name, conclusion: .conclusi --- -## Design System (Slate & Ice Modern) +## Design System -- **Theme:** Dark glassmorphism with ice-cyan accent (`#06b6d4` → `#22d3ee`). Uses `.glass-card` / `.glass-card-static` for card surfaces -- **Backgrounds:** `bg-background` (`#101114` page), glass surfaces use `rgba(24, 26, 31, 0.55)` with `backdrop-filter: blur()` -- **Cards:** `.glass-card` (interactive, hover `scale(1.02)` + border/shadow upgrade) or `.glass-card-static` (no hover). Both have `border-radius: 16px`, semi-transparent bg, backdrop blur -- **Buttons:** Primary: `bg-gradient-brand text-[#101114] font-semibold rounded-[10px] hover:opacity-90 active:scale-[0.97]`. Secondary: `bg-[rgba(255,255,255,0.04)] border-[rgba(255,255,255,0.06)] text-foreground rounded-[10px]` -- **Inputs:** `border-border bg-card text-foreground placeholder:text-muted-foreground` + focus: `focus:border-[rgba(6,182,212,0.3)]` -- **Text:** `text-foreground` (`#f8fafc`) → `text-muted-foreground` (`#8891a0`) → `text-[#5a6170]` (dim, for section labels/timestamps) -- **Borders:** `var(--glass-border)` (`rgba(255,255,255,0.06)`) default, `rgba(255,255,255,0.12)` on hover -- **Hover states:** Border brightens to `rgba(255,255,255,0.12)`, shadow upgrades to `--shadow-float-hover` -- **Active/selected:** `bg-primary/10 text-foreground` or cyan gradient accent bar -- **Functional colors:** emerald-400 (success), rose-500 (error), amber-400 (warning), blue-400 (info). Always pair with icons, not color alone. -- **CSS variables:** Glass system vars (`--glass-bg`, `--glass-border`, `--glass-blur`), shadow system (`--shadow-float`, `--shadow-float-hover`, `--shadow-cyan-glow`), easing (`--ease-out-smooth`) — all in `index.css` `:root` -- **Animations:** Orchestrated page-load sequence (slideDown, slideInLeft, fadeInUp cascade, fadeInRight). `breatheGlow` on first stat card. `bellWobble` on notification hover. See design doc for full spec. +**Source of truth:** [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) — always read this before making visual or UI decisions. + +- **Theme:** Flat, high-contrast dark theme (Sentry/PostHog-inspired). No glass morphism, no backdrop blur, no ambient orbs, no gradient backgrounds on surfaces. Light mode planned. +- **Backgrounds:** `bg-page` (`#0c0d10`), `bg-sidebar` (`#0f1118`), `bg-card` (`#14161d`), `bg-elevated` (`#1c1f2a`) +- **Cards:** `bg-card` with 1px `border-default` (`#1e2130`), 8px radius. No shadows, no blur, no gradients. Hover: `border-hover` (`#2a2f3d`) +- **Buttons:** Primary: solid `accent` (#22d3ee), white text, 5px radius. Ghost: transparent + 1px border, hover `bg-elevated` +- **Inputs:** `bg-input` (`#191c25`) with 1px `border-default`, 5px radius. Focus: `border-color: accent` + `box-shadow: 0 0 0 2px accent-dim` +- **Text:** `text-heading` (`#f0f2f5`) → `text-primary` (`#e2e5eb`) → `text-secondary` (`#848b9b`) → `text-muted` (`#4f5666`) +- **Borders:** `border-default` (`#1e2130`), `border-hover` (`#2a2f3d`) +- **Functional colors:** `#34d399` (success), `#fbbf24` (warning), `#f87171` (danger) — each with `-dim` variant at 10% opacity +- **Accent:** Cyan `#22d3ee` — used sparingly (≤5% of UI). `accent-dim` = `rgba(34,211,238,0.10)`, `accent-text` = `#67e8f9` +- **Deprecated:** Do NOT use `glass-card`, `glass-stat`, `bg-gradient-brand`, `text-gradient-brand`, `backdrop-filter: blur()`, ambient orbs, or purple gradients --- @@ -518,5 +518,5 @@ Use `/browse` from gstack for **all web browsing** — never use `mcp__claude-in | GitHub Issues | `gh issue list --state open` | | Bugs & Fixes | CLAUDE.md → Critical Lessons Learned section | | Feature Specs | [04-FEATURE-SPECIFICATIONS.md](04-FEATURE-SPECIFICATIONS.md) | -| Design System | [docs/plans/Frontend/DESIGN_SYSTEM_GUIDE.md](docs/plans/Frontend/DESIGN_SYSTEM_GUIDE.md) | +| Design System | [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) | | Dev Environment | [DEV-ENV.md](DEV-ENV.md) — devserver01 setup, Docker, CORS, networking | diff --git a/DESIGN-SYSTEM.md b/DESIGN-SYSTEM.md new file mode 100644 index 00000000..aafd2911 --- /dev/null +++ b/DESIGN-SYSTEM.md @@ -0,0 +1,378 @@ +# ResolutionFlow Design System v4 + +> **Status:** ACTIVE — This document is the single source of truth for all frontend design decisions. +> **Supersedes:** All previous design system docs including `DESIGN_SYSTEM_GUIDE.md`, `UI-DESIGN-SYSTEM.md`, `REBRAND-IMPLEMENTATION-GUIDE.md`, and any `COMPONENT_EXAMPLES.md` files. +> **Last Updated:** March 21, 2026 + +--- + +## Design Philosophy + +ResolutionFlow uses a **flat, high-contrast dark theme** inspired by Sentry and PostHog. The aesthetic is premium, clean, and minimal — no glass morphism, no backdrop blur, no ambient orbs, no gradient backgrounds on surfaces. The accent color appears in ≤5% of the UI. Every design decision prioritizes **readability over decoration**. + +**Light mode** is a planned addition (dark/light toggle). Design all components with CSS variables so theming is a variable swap, not a rewrite. + +--- + +## Color System + +All colors are defined as CSS custom properties in `index.css` inside the `@theme` block (Tailwind v4) or `:root` / `.dark` blocks (Tailwind v3). + +### Dark Mode (Default) + +``` +Page background: #0c0d10 +Sidebar background: #0f1118 +Card background: #14161d +Card hover: #191c25 +Input background: #191c25 +Code background: #0e1017 +Elevated surface: #1c1f2a + +Text primary: #e2e5eb +Text heading: #f0f2f5 +Text secondary: #848b9b +Text muted: #4f5666 +Text rail label: #6b7280 + +Border default: #1e2130 +Border hover: #2a2f3d + +Accent (cyan): #22d3ee +Accent hover: #06b6d4 +Accent dim (8-10%): rgba(34,211,238,0.10) +Accent text: #67e8f9 + +Success: #34d399 +Success dim: rgba(52,211,153,0.10) +Warning: #fbbf24 +Warning dim: rgba(251,191,36,0.10) +Danger: #f87171 +Danger dim: rgba(248,113,113,0.10) +``` + +### Light Mode (Planned) + +``` +Page background: #f3f4f7 +Sidebar background: #ffffff +Card background: #ffffff +Card hover: #f8f9fb +Input background: #eef0f4 +Code background: #f5f6f9 +Elevated surface: #e8eaef + +Text primary: #1a1d24 +Text heading: #0d0f13 +Text secondary: #5a6274 +Text muted: #8b92a1 + +Border default: #dde0e7 +Border hover: #c5c9d3 + +Accent: #0891b2 +Accent dim: rgba(8,145,178,0.07) +Accent text: #0e7490 +``` + +### What NOT To Use + +- No glass morphism (`backdrop-filter: blur`) +- No gradient backgrounds on cards or surfaces +- No ambient orbs or floating glow elements +- No `bg-white/[0.04]` opacity-based backgrounds +- No purple gradient accent (`#818cf8 → #a78bfa`) — this is deprecated +- No `text-gradient-brand` utility — replaced by solid `accent-text` color +- No `glass-card`, `glass-stat`, `glass-card-glow` CSS utilities + +--- + +## Typography + +### Font Stack + +| Role | Font | Weights | CSS Variable | +|------|------|---------|-------------| +| Body text | IBM Plex Sans | 400, 500, 600, 700 | `--font-sans` / `font-sans` | +| Headings | Bricolage Grotesque | 600, 700, 800 | `--font-heading` / `font-heading` | +| Code / Monospace | JetBrains Mono | 400, 500 | `--font-mono` / `font-mono` | + +### Typography Scale + +| Element | Size | Weight | Color | Letter Spacing | +|---------|------|--------|-------|---------------| +| Page title (h1) | 22px | 700 (Bricolage) | text-heading | -0.03em | +| Section title | 15px | 600 (Bricolage) | text-heading | normal | +| Card title | 14px | 600 (IBM Plex) | text-heading | normal | +| Body text | 14px | 400 (IBM Plex) | text-primary | normal | +| Secondary text | 13px | 400 (IBM Plex) | text-secondary | normal | +| Label / hint | 12px | 500 (IBM Plex) | text-muted | normal | +| Nav section header | 10px | 600 (IBM Plex) | text-muted | 1.2px, uppercase | +| Rail icon label | 10px | 500 (IBM Plex) | text-rail-label | normal | +| Code | 12px | 400 (JetBrains) | text-primary | normal | +| Stat number | 28px | 700 (Bricolage) | text-heading | -0.03em | +| Badge | 11px | 550 (IBM Plex) | varies | normal | + +### What NOT To Use + +- No Inter, Plus Jakarta Sans, or Outfit — these are deprecated +- No `font-label` utility — use `font-mono` for monospace or `font-sans` at small size +- No font sizes below 10px + +--- + +## Layout Architecture + +### App Shell + +The app uses a CSS Grid layout with two states: + +**Icon Rail (Default):** +``` +[icon-rail: 72px] [main-content: 1fr] +``` + +**Pinned Sidebar:** +``` +[full-sidebar: 260px] [main-content: 1fr] +``` + +### Icon Rail Sidebar + +The default navigation is a narrow icon rail (72px) with: +- Logo mark at top (30px square, gradient background, lightning bolt icon) +- Nav items as vertical column: icon (20px) + label text (10px) underneath +- Dividers between nav sections +- User avatar at bottom +- Pin/expand button below avatar + +**Hover behavior:** Hovering a rail item opens a flyout panel (220px) to the right of the rail with sub-navigation items for that section. The flyout stays open while the cursor is on either the rail item or the flyout panel. + +**Pinned state:** Clicking the pin button expands to a traditional 260px sidebar with full text labels, section headers, badges, and the active left-bar accent. An unpin button in the header returns to the icon rail. + +### Active Nav Indicator + +- **Icon rail:** `accent-dim` background on the item, `accent-text` color on icon and label +- **Pinned sidebar:** Same as above, plus a 3px left border (`border-radius: 0 3px 3px 0`) in `accent` color + +### Main Content Area + +- Padding: 28px top/bottom, 36px left/right +- Max content width: not constrained (fills available space) +- Page title: Bricolage Grotesque, 22px, weight 700 + +--- + +## Component Patterns + +### Stat Cards + +``` +Background: bg-card +Border: 1px solid border-default +Border-left: 3px solid [varies by position - accent, success, warning, accent] +Border-radius: 8px +Padding: 18px 16px +``` + +- Label: 11px, uppercase, 600 weight, text-muted +- Value: 28px, Bricolage Grotesque 700, text-heading +- Delta: 12px, 500 weight, success/danger color with ↑/↓ prefix + +### Cards + +``` +Background: bg-card +Border: 1px solid border-default +Border-radius: 8px +Padding: 20px +Hover: border-color transitions to border-hover +``` + +No shadows. No gradients. No glow effects. + +### Flow List Items + +``` +Layout: flex row, 12px gap +Padding: 10px 8px +Border-bottom: 1px solid border-default (divider style, not bordered cards) +Hover: bg-card-hover +``` + +- Icon: 34px square, border-radius 5px, semantic dim background + colored stroke +- Name: 13px, 500 weight, text-heading +- Meta: 11.5px, text-muted +- Badge: right-aligned status badge + +### Badges + +``` +Font: 11px, 550 weight +Padding: 3px 9px +Border-radius: 20px (pill) +``` + +| Type | Background | Text Color | +|------|-----------|------------| +| Info/Accent | accent-dim | accent-text | +| Success | success-dim | success | +| Warning | warning-dim | warning | +| Danger | danger-dim | danger | + +### Form Inputs + +``` +Background: bg-input +Border: 1px solid border-default +Border-radius: 5px +Padding: 9px 12px +Font: 13px, IBM Plex Sans +Focus: border-color accent, box-shadow 0 0 0 2px accent-dim +Placeholder: text-muted +``` + +### Buttons + +**Primary:** +``` +Background: accent (#22d3ee) +Color: #fff +Border: none +Border-radius: 5px +Padding: 9px 16px +Font: 13px, 550 weight +Hover: brightness(1.1) +``` + +**Ghost:** +``` +Background: transparent +Color: text-secondary +Border: 1px solid border-default +Hover: bg-elevated, text-primary, border-hover +``` + +### Code Blocks + +``` +Background: bg-code (#0e1017) +Border: 1px solid border-default +Border-radius: 8px +Padding: 18px 20px +Font: JetBrains Mono, 12px, line-height 1.7 +``` + +**Syntax colors (dark mode):** + +| Token | Color | +|-------|-------| +| Comment | #4a5568 | +| Keyword | #c792ea | +| Function/Cmdlet | #82aaff | +| String | #c3e88d | +| Variable | #89ddff | +| Parameter | #8c93a4 | +| Number | #f78c6c | + +### Chips / Tags + +``` +Font: 11.5px, 500 weight +Padding: 4px 11px +Border-radius: 20px +Background: accent-dim +Color: accent-text +``` + +--- + +## Logo + +- **Mark:** 30-32px square, border-radius 8px, `linear-gradient(135deg, #06b6d4, #22d3ee)`, white lightning bolt SVG +- **Wordmark:** "ResolutionFlow" in Bricolage Grotesque, 16-17px, weight 700, text-heading color +- **Combined:** Mark + wordmark horizontally, 10px gap + +--- + +## Spacing System + +- Component internal gaps: 6px, 8px, 12px, 14px, 16px +- Card padding: 20px +- Section gaps: 24px between major sections +- Page padding: 28px vertical, 36px horizontal +- Stat grid gap: 12px +- Two-column gap: 16px +- Nav item padding: 8px 10px (pinned), 8px 4px (rail) + +--- + +## Border Radius + +| Token | Value | Use | +|-------|-------|-----| +| radius-sm | 5px | Inputs, buttons, small elements | +| radius | 8px | Cards, stat cards, code blocks | +| radius-lg | 12px | Large cards, modals | +| radius-xl | 16px | Hero elements, CTA boxes | +| radius-pill | 100px | Badges, chips, toggle tracks | + +--- + +## Shadows + +Minimal to none. No decorative shadows. + +- Cards: none (border only) +- Dropdowns/flyouts: `0 4px 12px rgba(0,0,0,0.3)` if needed +- Logo mark: `0 2px 8px rgba(14,165,233,0.25)` (subtle brand glow on logo only) + +--- + +## Icons + +All icons use Lucide React (`lucide-react` package). +- Default size: 16-18px +- Stroke width: 1.6-1.8 +- Color: `currentColor` (inherits from parent text color) +- Nav icons: 20px at stroke-width 1.6 +- Rail icon opacity: 0.6 default, 0.85 on hover, 1.0 when active + +--- + +## Landing Page + +The marketing landing page at `/` shares the same color system and typography but has its own layout (no sidebar, full-width sections). Key differences: + +- Navigation: fixed top bar with logo, links, and CTAs +- Hero: centered layout with glow effect (radial gradient, accent at 15% opacity) +- Sections: 100px vertical padding, max-width 1120px container +- Section labels: JetBrains Mono, 12px, uppercase, accent-text color +- Section titles: Bricolage Grotesque, clamp(28px, 4vw, 42px), weight 800 +- Pricing cards: same card pattern but with featured state (accent border + subtle glow) +- Product mockup: embedded in hero, shows the actual app UI with browser chrome + +--- + +## Files That Define The Design System + +These are the source-of-truth files in the codebase: + +| File | What It Controls | +|------|-----------------| +| `frontend/src/index.css` | CSS variables, `@theme` block, base styles | +| `frontend/tailwind.config.js` (v3) or inline in index.css (v4) | Color tokens, font families, spacing extensions | +| `frontend/index.html` | Google Font imports | +| `DESIGN-SYSTEM.md` (this file) | Design decisions, component specs, rules | + +--- + +## Deprecated Files — DO NOT Reference + +These files contain outdated design information and should be ignored: + +- `DESIGN_SYSTEM_GUIDE.md` — Old monochrome glass-morphism system +- `UI-DESIGN-SYSTEM.md` — Old workspace/purple gradient system +- `REBRAND-IMPLEMENTATION-GUIDE.md` — Old purple rebrand from Patherly +- `COMPONENT_EXAMPLES.md` — Old monochrome component patterns +- Any file referencing `glass-card`, `glass-stat`, `bg-gradient-brand`, or `text-gradient-brand` diff --git a/UI-DESIGN-SYSTEM.md b/docs/archive/design-docs/UI-DESIGN-SYSTEM.md similarity index 100% rename from UI-DESIGN-SYSTEM.md rename to docs/archive/design-docs/UI-DESIGN-SYSTEM.md -- 2.49.1 From 1de0b50ce4a5da0927437683f653c0152aa77039 Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Sat, 21 Mar 2026 23:50:59 -0400 Subject: [PATCH 02/37] docs: add Design System v4 migration spec Flat dark theme migration plan: CSS foundation, icon rail sidebar, ~130 file component sweep, landing page updates. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../2026-03-22-design-system-v4-migration.md | 276 ++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 docs/superpowers/specs/2026-03-22-design-system-v4-migration.md diff --git a/docs/superpowers/specs/2026-03-22-design-system-v4-migration.md b/docs/superpowers/specs/2026-03-22-design-system-v4-migration.md new file mode 100644 index 00000000..c438af96 --- /dev/null +++ b/docs/superpowers/specs/2026-03-22-design-system-v4-migration.md @@ -0,0 +1,276 @@ +# Design System v4 Migration — Flat Dark Theme + +> **Goal:** Migrate ResolutionFlow's frontend from glassmorphism/gradient aesthetic to a flat, high-contrast dark theme (Sentry/PostHog-inspired) with an icon rail sidebar, as defined in DESIGN-SYSTEM.md. + +## Scope + +~130 files across 15+ directories use old design patterns (`glass-card`, `bg-gradient-brand`, `text-gradient-brand`, `backdrop-filter: blur()`, ambient orbs). All must be updated to the new flat dark system. + +## Approach + +**Foundation first, then sweep.** Three phases: + +1. **Phase 1: CSS Foundation** — Rewrite `index.css` tokens, remove old utilities, add new variables +2. **Phase 2: Layout Shell** — Icon rail sidebar + app layout restructure +3. **Phase 3: Component Sweep** — Update all 132 files directory-by-directory + +Each phase produces deployable commits. The app will look inconsistent during Phase 3 but will always be functional. + +--- + +## Phase 1: CSS Foundation + +### index.css @theme Block + +Rewrite the `@theme` block with new color tokens matching DESIGN-SYSTEM.md: + +``` +Page background: #0c0d10 → --bg-page +Sidebar background: #0f1118 → --bg-sidebar +Card background: #14161d → --bg-card +Card hover: #191c25 → --bg-card-hover +Input background: #191c25 → --bg-input +Code background: #0e1017 → --bg-code +Elevated surface: #1c1f2a → --bg-elevated + +Text heading: #f0f2f5 → --text-heading +Text primary: #e2e5eb → --text-primary +Text secondary: #848b9b → --text-secondary +Text muted: #4f5666 → --text-muted + +Border default: #1e2130 → --border-default +Border hover: #2a2f3d → --border-hover + +Accent: #22d3ee → --accent +Accent hover: #06b6d4 → --accent-hover +Accent dim (10%): rgba(34,211,238,0.10) → --accent-dim +Accent text: #67e8f9 → --accent-text + +Success: #34d399 + dim at 10% +Warning: #fbbf24 + dim at 10% +Danger: #f87171 + dim at 10% + +Rail label: #6b7280 → --text-rail-label +``` + +### Variables Structure + +All colors in `:root` (dark is default). Light mode values prepared as comments — implementing the toggle is a future follow-up that just adds a `.light` class block. + +### Compatibility Shims (Critical) + +To avoid breaking the entire app while Phase 3 sweeps components, Phase 1 keeps the old utility class names as **deprecated aliases** mapping to the new values: + +```css +/* Deprecated — remove after Phase 3 sweep completes */ +.glass-card, .glass-card-static { @apply bg-[var(--bg-card)] border border-[var(--border-default)] rounded-lg; } +.glass-card:hover { @apply border-[var(--border-hover)]; } +``` + +These shims are removed in a final cleanup commit after Phase 3 is complete. + +### Remove Old Utilities + +Delete from `index.css` (after Phase 3 sweep — shims keep the app functional until then): +- `.glass-card`, `.glass-card-static`, `.glass-stat`, `.glass-card-glow` +- `.active-glow`, `.breatheGlow` keyframes +- `bg-gradient-brand`, `text-gradient-brand`, `bg-gradient-brand-hover` +- `--glass-bg`, `--glass-border`, `--glass-blur` variables +- `--shadow-float`, `--shadow-float-hover`, `--shadow-cyan-glow` shadow variables +- Atmosphere orb styles (`.atmosphere-orb`) +- Orchestrated page-load animation keyframes (slideDown, slideInLeft, fadeInUp, fadeInRight) + +### Rename + +- `--font-label` → `--font-mono` (JetBrains Mono, same font, clearer name) + +### Keep + +- Google Fonts imports (same three fonts) +- React Flow import +- Tailwind v4 `@theme` approach +- Base animation keyframes: `fade-in`, `fade-in-up`, `slide-in-from-left`, `slide-in-from-bottom` — all others removed (no `breatheGlow`, `bellWobble`, `slideDown`, orchestrated page-load sequence) + +### New Base Classes + +Add reusable component classes: + +```css +.card { /* bg-card, 1px border-default, 8px radius, no shadow */ } +.card-interactive { /* extends .card + hover border-hover transition */ } +.stat-card { /* extends .card + 3px left border */ } +.badge { /* 11px, pill shape, dim bg + matching text */ } +.btn-primary { /* solid accent, white text, 5px radius — NOTE: text changes from dark (#101114) to white */ } +.btn-ghost { /* transparent, 1px border, hover bg-elevated */ } +``` + +Implement each class per DESIGN-SYSTEM.md Component Patterns section for exact values. + +--- + +## Phase 2: Icon Rail Sidebar + +### New Component: IconRailSidebar + +Replaces current `Sidebar.tsx`. Two states: + +**Icon Rail (72px, default):** +- `bg-sidebar` background, full viewport height +- Logo mark at top: 30px cyan gradient square with lightning bolt +- Nav items: vertical column, 20px icon + 10px label underneath +- Horizontal dividers between sections (RESOLVE / KNOWLEDGE / INSIGHTS) +- User avatar at bottom +- Pin/expand toggle below avatar +- Active item: `accent-dim` background, `accent-text` on icon + label + +**Hover Flyout (220px panel):** +- Opens to the right of the hovered rail item with 150ms ease-out transition +- Also opens on keyboard focus/Enter for accessibility; closes on Escape or focus-out +- Shows sub-navigation for that section +- If section has many sub-items, flyout scrolls with `max-height: 70vh; overflow-y: auto` +- `bg-card` with `border-default` and `box-shadow: 0 4px 12px rgba(0,0,0,0.3)` +- Stays open while cursor is on rail item OR flyout panel +- Closes on mouse leave from both + +**Pinned State (260px full sidebar):** +- Click pin → expands to traditional sidebar with text labels, section headers, badges +- 3px left accent bar on active item +- Unpin button in sidebar header +- Preference persisted in localStorage / userPreferences store + +**Mobile:** +- Icon rail hidden below `sm` breakpoint +- Hamburger menu opens full overlay sidebar (same as pinned content) + +### Layout Changes + +`AppLayout.tsx` CSS Grid: +- Default: `grid-template-columns: 72px 1fr` +- Pinned: `grid-template-columns: 260px 1fr` +- Mobile: `grid-template-columns: 1fr` +- CSS variable `--sidebar-w` updated accordingly (used by FlowPilotMessageBar, FlowPilotActionBar) +- Ensure `--sidebar-w` transition is coordinated with sidebar width transition to prevent layout jump on pin/unpin + +**Sidebar commits:** Phase 2 produces 2-3 commits (icon rail core, flyout behavior, pinned state + persistence). + +### BrandLogo Update + +Replace current decision-tree icon SVG in `BrandLogo.tsx` with 30px gradient square (cyan, `border-radius: 8px`) + white lightning bolt mark. Wordmark: "ResolutionFlow" in Bricolage Grotesque 700, `text-heading` color (no gradient). + +### Files + +| Action | File | +|--------|------| +| Rewrite | `frontend/src/components/layout/Sidebar.tsx` → icon rail with flyout + pinned state | +| Modify | `frontend/src/components/layout/AppLayout.tsx` → grid columns, mobile handling | +| Modify | `frontend/src/components/layout/TopBar.tsx` → flat styling, remove blur | +| Keep | `FlowPilotMessageBar.tsx`, `FlowPilotActionBar.tsx` — `left: var(--sidebar-w)` still works | + +--- + +## Phase 3: Component Sweep + +### Pattern Replacement Map + +| Old Pattern | New Pattern | +|------------|-------------| +| `glass-card` / `glass-card-static` | `bg-[var(--bg-card)] border border-[var(--border-default)] rounded-lg` (or `.card` class) | +| `bg-gradient-brand` | `bg-[var(--accent)]` (solid cyan) | +| `text-gradient-brand` | `text-[var(--accent-text)]` | +| `bg-gradient-brand-hover` | `hover:brightness-110` | +| `text-foreground` | `text-[var(--text-primary)]` | +| `text-muted-foreground` | `text-[var(--text-secondary)]` | +| `bg-background` | `bg-[var(--bg-page)]` | +| `bg-card` (old token) | `bg-[var(--bg-card)]` | +| `border-border` | `border-[var(--border-default)]` | +| `font-label` (on code/monospace content) | `font-mono` | +| `font-label` (on labels/badges/timestamps) | `font-sans text-xs` — inspect each usage | +| `backdrop-filter: blur(...)` | Remove | +| `shadow-lg shadow-primary/20` on buttons | Remove | +| `rounded-[10px]` / `rounded-[16px]` on cards | `rounded-lg` (8px) | +| `scale(1.02)` hover on cards | Border color transition | +| `.atmosphere-orb` elements | Remove from JSX | +| `style={{ background: 'rgba(...)' }}` glass surfaces | Use CSS variable classes | + +### Sweep Order (one commit per directory group, ~10 commits total) + +Phase 3 covers app components only; landing page is handled in Phase 4. + +1. **`components/layout/`** (3 files) — AppLayout, TopBar, BrandLogo +2. **`components/dashboard/`** (16 files) — highest visibility +3. **`components/flowpilot/`** (12 files) — core product +4. **`pages/`** (25 files) — all page components +5. **`components/session/`** (8 files) +6. **`components/script-builder/`** (4 files) +7. **`components/kb-accelerator/`** (5 files) +8. **`components/account/`** (4 files) +9. **`components/tree-editor/`** (4 files) +10. **All remaining directories** (~51 files: admin, analytics, assistant, common, copilot, library, procedural, public, script-editor, ui) + +### What Stays the Same + +- Component logic, state management, hooks, API calls — untouched +- Lucide icons — same +- `cn()` utility — same +- All non-design Tailwind utilities (flex, grid, padding, margin, etc.) +- React Router, Zustand stores, type definitions + +--- + +## Phase 4: Landing Page + +- Remove ambient glow effects and gradient overlays from `landing.css` +- Hero: subtle radial gradient at 15% accent opacity (replaces heavy glow) +- Section labels: JetBrains Mono, 12px, uppercase, accent-text +- Section titles: Bricolage Grotesque, `clamp(28px, 4vw, 42px)`, weight 800 +- Pricing cards: flat `bg-card` + `border-default`, featured card gets accent border +- Top nav: flat, no blur backdrop +- CTAs: solid accent buttons +- Product mockup: update screenshot to show new flat UI + +**Files:** `landing.css`, `LandingPage.tsx`, landing-specific components + +--- + +## Phase 5: Cleanup & Documentation + +- Remove compatibility shims from `index.css` (deprecated `glass-card` aliases from Phase 1) +- Update CLAUDE.md: verify branding section and design system section reflect the new flat theme (already partially done in the doc-swap commit — verify no stale references remain) +- Update `BrandWordmark.tsx` if it references `text-gradient-brand` +- Verify `npm run build` passes with zero references to removed utilities + +**Light mode note:** All colors use CSS custom properties. Light mode values from DESIGN-SYSTEM.md are stored as comments in `index.css`. Adding light mode later = add `.light` class values + toggle in user settings. Not implemented in this migration. + +--- + +## Out of Scope + +- Light mode toggle (future follow-up — just variable swap + settings toggle) +- React Flow canvas theme updates (separate concern, works with any color scheme) +- Backend changes (none needed) +- New features or functionality (purely visual migration) +- Test changes (no visual tests exist) + +--- + +## Risk Mitigation + +- Each phase produces deployable commits +- The app is functional throughout (just visually inconsistent during Phase 3) +- Old CSS utilities removed in Phase 1 — if a component breaks visually, it's obvious +- `npm run build` verified after each phase +- No logic changes = no new bugs in functionality + +--- + +## Verification + +After each phase: +1. `npm run build` passes +2. Visual spot-check of key pages (Dashboard, FlowPilot session, Script Builder, Landing) + +After all phases: +1. Full app walkthrough — every sidebar nav item +2. Mobile responsive check (icon rail hidden, hamburger menu works) +3. Landing page check +4. FlowPilot session check (message bar, action bar positioning) -- 2.49.1 From 6efabff0904549265b9799bc71005e8ae344a2e9 Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Sun, 22 Mar 2026 00:01:33 -0400 Subject: [PATCH 03/37] docs: add Design System v4 migration implementation plan 9 tasks: CSS foundation, icon rail sidebar, component sweep (~200 files across 6 directory-group commits), landing page, cleanup. Plan reviewed and all issues addressed. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../2026-03-22-design-system-v4-migration.md | 665 ++++++++++++++++++ 1 file changed, 665 insertions(+) create mode 100644 docs/superpowers/plans/2026-03-22-design-system-v4-migration.md diff --git a/docs/superpowers/plans/2026-03-22-design-system-v4-migration.md b/docs/superpowers/plans/2026-03-22-design-system-v4-migration.md new file mode 100644 index 00000000..bafb7c62 --- /dev/null +++ b/docs/superpowers/plans/2026-03-22-design-system-v4-migration.md @@ -0,0 +1,665 @@ +# Design System v4 Migration — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Migrate ResolutionFlow's frontend from glassmorphism/gradient aesthetic to a flat, high-contrast dark theme with an icon rail sidebar, as defined in DESIGN-SYSTEM.md. + +**Architecture:** Five phases executed sequentially. Phase 1 rewrites CSS tokens and adds compatibility shims. Phase 2 rebuilds the sidebar as an icon rail. Phase 3 sweeps ~200 component files replacing old patterns. Phase 4 updates the landing page. Phase 5 removes shims and cleans up. + +**Tech Stack:** React 19, Tailwind CSS v4, CSS custom properties, Lucide React + +**Spec:** `docs/superpowers/specs/2026-03-22-design-system-v4-migration.md` + +**Design system reference:** `DESIGN-SYSTEM.md` (project root) + +--- + +## File Map + +### Phase 1 — CSS Foundation +| Action | File | +|--------|------| +| Rewrite | `frontend/src/index.css` | + +### Phase 2 — Icon Rail Sidebar +| Action | File | +|--------|------| +| Rewrite | `frontend/src/components/layout/Sidebar.tsx` | +| Modify | `frontend/src/components/layout/AppLayout.tsx` | +| Modify | `frontend/src/components/layout/TopBar.tsx` | +| Modify | `frontend/src/components/common/BrandLogo.tsx` and `BrandWordmark.tsx` | + +### Phase 3 — Component Sweep (~200 files) +| Action | Files | +|--------|-------| +| Modify | All `.tsx` files in `components/` and `pages/` that reference old patterns | + +### Phase 4 — Landing Page +| Action | File | +|--------|------| +| Modify | `frontend/src/pages/LandingPage.tsx` | +| Modify | `frontend/src/styles/landing.css` | + +### Phase 5 — Cleanup +| Action | File | +|--------|------| +| Modify | `frontend/src/index.css` (remove shims) | +| Modify | `CLAUDE.md` (verify no stale references) | + +--- + +## Task 1: Rewrite CSS Foundation (index.css) + +**Files:** +- Modify: `frontend/src/index.css` +- Reference: `DESIGN-SYSTEM.md` (project root) + +- [ ] **Step 1: Rewrite the `@theme` block with new color tokens** + +Replace the entire `@theme { ... }` block. New tokens from DESIGN-SYSTEM.md: + +```css +@theme { + /* ── Surface colors ────────────────────────────── */ + --color-bg-page: #0c0d10; + --color-bg-sidebar: #0f1118; + --color-bg-card: #14161d; + --color-bg-card-hover: #191c25; + --color-bg-input: #191c25; + --color-bg-code: #0e1017; + --color-bg-elevated: #1c1f2a; + + /* ── Text colors ───────────────────────────────── */ + --color-text-heading: #f0f2f5; + --color-text-primary: #e2e5eb; + --color-text-secondary: #848b9b; + --color-text-muted: #4f5666; + --color-text-rail-label: #6b7280; + + /* ── Border colors ─────────────────────────────── */ + --color-border-default: #1e2130; + --color-border-hover: #2a2f3d; + + /* ── Accent (cyan) ─────────────────────────────── */ + --color-accent: #22d3ee; + --color-accent-hover: #06b6d4; + --color-accent-dim: rgba(34,211,238,0.10); + --color-accent-text: #67e8f9; + + /* ── Semantic colors ───────────────────────────── */ + --color-success: #34d399; + --color-success-dim: rgba(52,211,153,0.10); + --color-warning: #fbbf24; + --color-warning-dim: rgba(251,191,36,0.10); + --color-danger: #f87171; + --color-danger-dim: rgba(248,113,113,0.10); + + /* ── Tailwind semantic mappings ─────────────────── */ + --color-background: #0c0d10; + --color-foreground: #e2e5eb; + --color-card: #14161d; + --color-card-foreground: #e2e5eb; + --color-popover: #14161d; + --color-popover-foreground: #e2e5eb; + --color-primary: #22d3ee; + --color-primary-foreground: #ffffff; + --color-secondary: #1c1f2a; + --color-secondary-foreground: #e2e5eb; + --color-muted: #1c1f2a; + --color-muted-foreground: #848b9b; + --color-accent-tw: #1c1f2a; + --color-accent-foreground: #e2e5eb; + --color-destructive: #f87171; + --color-destructive-foreground: #ffffff; + --color-border: #1e2130; + --color-input: #191c25; + --color-ring: #22d3ee; + + /* ── Radii ─────────────────────────────────────── */ + --radius-sm: 5px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-xl: 16px; + + /* ── Fonts ─────────────────────────────────────── */ + --font-sans: 'IBM Plex Sans', system-ui, -apple-system, sans-serif; + --font-heading: 'Bricolage Grotesque', system-ui, sans-serif; + --font-mono: 'JetBrains Mono', monospace; + /* Deprecated alias — remove in Phase 5 */ + --font-label: 'JetBrains Mono', monospace; + + /* ── Animations ────────────────────────────────── */ + --animate-fade-in: fade-in 200ms ease-out; + --animate-fade-in-up: fade-in-up 200ms ease-out; + --animate-slide-in-left: slide-in-from-left 200ms ease-out; + --animate-slide-in-bottom: slide-in-from-bottom 200ms ease-out; + --animate-scale-in: scale-in 150ms ease-out; + + @keyframes fade-in { + from { opacity: 0; } to { opacity: 1; } + } + @keyframes fade-in-up { + from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } + } + @keyframes slide-in-from-left { + from { transform: translateX(-100%); } to { transform: translateX(0); } + } + @keyframes slide-in-from-bottom { + from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } + } + @keyframes scale-in { + from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } + } + @keyframes fadeIn { + from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } + } +} +``` + +- [ ] **Step 2: Replace `:root` variables** + +Replace the `:root` block (lines 168-192) with: + +```css +:root { + --sidebar-w: 72px; + --sidebar-w-pinned: 260px; + --ease-out-smooth: cubic-bezier(0.4, 0, 0.2, 1); +} +``` + +- [ ] **Step 3: Add compatibility shims** + +Replace the old `@utility` blocks (glass-card, glass-card-static, active-glow, text-gradient-brand) with shims: + +```css +/* ── Deprecated shims — remove after Phase 3 sweep ── */ +@utility glass-card { + background: var(--color-bg-card); + border: 1px solid var(--color-border-default); + border-radius: 8px; + transition: border-color 200ms ease; + &:hover { + border-color: var(--color-border-hover); + } +} + +@utility glass-card-static { + background: var(--color-bg-card); + border: 1px solid var(--color-border-default); + border-radius: 8px; +} + +@utility text-gradient-brand { + color: var(--color-accent-text); +} + +@utility active-glow { + /* no-op — glow removed in v4 */ +} + +@utility bg-gradient-brand-hover { + /* Shim — maps to brightness hover until components are swept */ + &:hover { filter: brightness(1.1); } +} +``` + +Remove the old gradient `--background-image-*` theme values. Remove `breatheGlow`, `bellWobble`, `slideDown`, `slideInRight`, `fadeInRight`, `pulse-dot`, `stagger-fade-in` keyframes. Remove `stagger-item` utility. + +- [ ] **Step 4: Add new base component classes** + +Add after the shims: + +```css +/* ── New component base classes ─────────────────── */ +@utility card-flat { + background: var(--color-bg-card); + border: 1px solid var(--color-border-default); + border-radius: 8px; +} + +@utility card-interactive { + background: var(--color-bg-card); + border: 1px solid var(--color-border-default); + border-radius: 8px; + transition: border-color 200ms ease; + &:hover { + border-color: var(--color-border-hover); + } +} + +@utility btn-primary { + background: var(--color-accent); + color: #ffffff; + font-weight: 550; + border-radius: 5px; + padding: 9px 16px; + font-size: 13px; + transition: filter 150ms ease; + &:hover { + filter: brightness(1.1); + } +} + +@utility btn-ghost { + background: transparent; + color: var(--color-text-secondary); + border: 1px solid var(--color-border-default); + border-radius: 5px; + padding: 9px 16px; + font-size: 13px; + transition: background 150ms ease, color 150ms ease, border-color 150ms ease; + &:hover { + background: var(--color-bg-elevated); + color: var(--color-text-primary); + border-color: var(--color-border-hover); + } +} +``` + +- [ ] **Step 5: Update layout utilities** + +Update `.app-shell` grid columns: + +```css +.app-shell { + display: grid; + grid-template-columns: var(--sidebar-w) 1fr; + grid-template-rows: 1fr; /* No topbar row — topbar is inside main content now, or handled differently */ + height: 100vh; + overflow: hidden; + transition: grid-template-columns 200ms ease; +} + +.app-shell--pinned { + --sidebar-w: 260px; +} + +@media (max-width: 767px) { + .app-shell { + grid-template-columns: 1fr; + } +} +``` + +- [ ] **Step 6: Update base body styles** + +```css +body { + @apply bg-background text-foreground font-sans; + color: var(--color-text-primary); + background-color: var(--color-bg-page); +} +``` + +- [ ] **Step 7: Keep React Flow, Sonner, scrollbar, and accessibility styles** + +These stay mostly unchanged — just verify they reference the correct new variable names. Update any references to removed variables. + +- [ ] **Step 8: Verify build** + +Run: `cd frontend && npm run build` +Expected: Build succeeds. App looks different (shims mapping old classes to flat styles) but is functional. + +- [ ] **Step 9: Commit** + +```bash +git add frontend/src/index.css +git commit -m "refactor: rewrite CSS foundation for Design System v4 + +New flat dark color tokens, remove glass/gradient utilities, +add compatibility shims for phased migration. + +Co-Authored-By: Claude Opus 4.6 (1M context) " +``` + +--- + +## Task 2: Icon Rail Sidebar + +**Files:** +- Rewrite: `frontend/src/components/layout/Sidebar.tsx` +- Modify: `frontend/src/components/layout/AppLayout.tsx` +- Modify: `frontend/src/components/layout/TopBar.tsx` +- Modify: `frontend/src/components/common/BrandLogo.tsx` +- Reference: `DESIGN-SYSTEM.md` → Layout Architecture, Icon Rail Sidebar sections + +This is a complex task. The sidebar has three states: icon rail (72px), flyout (hovering), and pinned (260px). Read the current `Sidebar.tsx` and `AppLayout.tsx` fully before starting. + +- [ ] **Step 1: Read current sidebar and layout** + +Read `frontend/src/components/layout/Sidebar.tsx` and `frontend/src/components/layout/AppLayout.tsx` completely to understand current nav structure, items, mobile handling, and grid layout. + +- [ ] **Step 2: Implement icon rail sidebar** + +Rewrite `Sidebar.tsx` with: +- Default: 72px icon rail with `bg-[var(--color-bg-sidebar)]` +- Logo mark at top: 30px cyan gradient square with lightning bolt SVG +- Nav items: 20px Lucide icon + 10px label text underneath, centered +- Horizontal dividers between RESOLVE / KNOWLEDGE / INSIGHTS sections +- Active item: `bg-[var(--color-accent-dim)]` background, `text-[var(--color-accent-text)]` on icon + label +- Inactive: `text-[var(--color-text-rail-label)]`, opacity 0.6 default, 0.85 hover +- User avatar at bottom +- Pin toggle button below avatar + +Nav items (same as current, just icon + short label): +- Dashboard (LayoutDashboard) +- Sessions (Activity) — with count badge +- Escalations (AlertTriangle) +- Divider +- Flows (GitBranch) +- Steps (Layers) +- Scripts (Code2) +- Builder (Wand2) +- Review (ListChecks) +- Divider +- Exports (Download) +- Analytics (BarChart3) +- FP Analytics (Rocket) + +Footer: User Guides, Feedback, Account (as icons), Pin/Unpin toggle + +- [ ] **Step 3: Implement flyout panels** + +On hover of a nav item, show a 220px flyout panel to the right: +- `bg-[var(--color-bg-card)]` with `border border-[var(--color-border-default)]` +- `box-shadow: 0 4px 12px rgba(0,0,0,0.3)` +- 150ms ease-out transition (opacity + translateX) +- Also opens on keyboard focus/Enter +- Closes on Escape, mouse leave from both rail item and flyout, or focus-out +- `max-height: 70vh; overflow-y: auto` for long sub-item lists +- Sub-items match current sidebar children (e.g., Flows → All Flows, Troubleshooting, Projects, Maintenance) + +- [ ] **Step 4: Implement pinned state** + +Clicking pin button: +- Expands sidebar to 260px with full text labels, section headers, badges +- Updates `--sidebar-w` CSS variable to `260px` +- Shows unpin button in sidebar header +- Persists preference to localStorage (`sidebarPinned: true/false`) +- Active item gets 3px left accent bar + +- [ ] **Step 5: Mobile handling** + +Below `sm` breakpoint: +- Icon rail hidden +- Hamburger button in top-left corner +- Opens full-screen overlay with pinned sidebar content +- Close button (X) in overlay header + +- [ ] **Step 6: Update AppLayout.tsx** + +- Grid layout changes from `grid-template-rows: 56px 1fr` to `grid-template-rows: auto 1fr` — TopBar remains a grid row spanning both columns (same as current), but with flat styling +- Grid columns: `var(--sidebar-w) 1fr` (72px default, 260px when pinned via `.app-shell--pinned` class) +- Sidebar pin state: read from `localStorage.getItem('sidebarPinned')` on mount, toggle sets `localStorage.setItem('sidebarPinned', 'true'/'false')` and updates `--sidebar-w` CSS variable on the `.app-shell` element +- Ensure `--sidebar-w` transition is coordinated with sidebar width transition to prevent layout jump on pin/unpin (both use `transition: 200ms ease`) +- Mobile: single column, no sidebar + +- [ ] **Step 7: Update TopBar.tsx** + +- Remove backdrop blur +- Flat `bg-[var(--color-bg-sidebar)]` or `bg-[var(--color-bg-page)]` background +- `border-b border-[var(--color-border-default)]` +- Remove any glass/gradient styling + +- [ ] **Step 8: Update BrandLogo.tsx** + +- Replace decision-tree icon SVG with 30px gradient square (cyan, border-radius 8px) + white lightning bolt +- Wordmark: "ResolutionFlow" in Bricolage Grotesque 700, `text-[var(--color-text-heading)]` (no gradient) +- Remove `text-gradient-brand` usage + +- [ ] **Step 9: Verify build and test** + +Run: `cd frontend && npm run build` +Expected: Build succeeds. Sidebar renders as icon rail. Flyout works on hover. Pin/unpin works. + +- [ ] **Step 10: Commit** + +```bash +git add frontend/src/components/layout/ frontend/src/components/common/BrandLogo.tsx +git commit -m "refactor: implement icon rail sidebar for Design System v4 + +72px icon rail with hover flyouts, pin-to-expand toggle, +keyboard accessible, mobile hamburger overlay. + +Co-Authored-By: Claude Opus 4.6 (1M context) " +``` + +--- + +## Task 3: Component Sweep — Layout & Dashboard + +**Files:** +- Modify: All files in `frontend/src/components/dashboard/` (~16 files) +- Modify: Any remaining layout components + +Apply the pattern replacement map from the spec to every file. For each file: + +1. Replace `glass-card` / `glass-card-static` → `card-flat` or `card-interactive` +2. Replace `bg-gradient-brand` → `btn-primary` class or `bg-[var(--color-accent)]` +3. Replace `text-gradient-brand` → `text-[var(--color-accent-text)]` +4. Replace `text-foreground` → `text-[var(--color-text-primary)]` +5. Replace `text-muted-foreground` → `text-[var(--color-text-secondary)]` +6. Replace `font-label` on code/monospace → `font-mono`; on labels/badges → `font-sans text-xs` +7. Remove `backdrop-filter`, `shadow-lg shadow-primary/20`, `scale(1.02)` hover +8. Remove atmosphere orb JSX elements +9. Replace `rounded-[10px]` / `rounded-[16px]` → `rounded-lg` (8px) +10. Replace inline `style={{ background: 'rgba(...)' }}` glass surfaces → CSS variable classes + +- [ ] **Step 1: Read and update all dashboard components** + +Process all `.tsx` files in `frontend/src/components/dashboard/` (~18 files). Apply the pattern replacement map to each. + +- [ ] **Step 2: Verify build** + +Run: `cd frontend && npm run build` + +- [ ] **Step 3: Commit** + +```bash +git add frontend/src/components/dashboard/ frontend/src/components/layout/ +git commit -m "refactor: migrate dashboard components to Design System v4 + +Co-Authored-By: Claude Opus 4.6 (1M context) " +``` + +--- + +## Task 4: Component Sweep — FlowPilot + +**Files:** +- Modify: All files in `frontend/src/components/flowpilot/` (~12 files) + +Same pattern replacement map as Task 3. + +- [ ] **Step 1: Read and update all FlowPilot components** + +Process all `.tsx` files in `frontend/src/components/flowpilot/` (~17 files). Apply the pattern replacement map to each. + +- [ ] **Step 2: Verify build** + +Run: `cd frontend && npm run build` + +- [ ] **Step 3: Commit** + +```bash +git add frontend/src/components/flowpilot/ +git commit -m "refactor: migrate FlowPilot components to Design System v4 + +Co-Authored-By: Claude Opus 4.6 (1M context) " +``` + +--- + +## Task 5: Component Sweep — Pages + +**Files:** +- Modify: All files in `frontend/src/pages/` (~25 files) + +Same pattern replacement map. + +- [ ] **Step 1: Read and update all page components** + +Process all `.tsx` files in `frontend/src/pages/` (~41 files). Apply the pattern replacement map to each. + +- [ ] **Step 2: Verify build** + +Run: `cd frontend && npm run build` + +- [ ] **Step 3: Commit** + +```bash +git add frontend/src/pages/ +git commit -m "refactor: migrate page components to Design System v4 + +Co-Authored-By: Claude Opus 4.6 (1M context) " +``` + +--- + +## Task 6: Component Sweep — Session, Script Builder, Account + +**Files:** +- Modify: `frontend/src/components/session/` (~21 files) +- Modify: `frontend/src/components/script-builder/` (~5 files) +- Modify: `frontend/src/components/account/` (~5 files) + +- [ ] **Step 1: Update session components** +- [ ] **Step 2: Update script-builder components** +- [ ] **Step 3: Update account components** +- [ ] **Step 4: Verify build** + +Run: `cd frontend && npm run build` + +- [ ] **Step 5: Commit** + +```bash +git add frontend/src/components/session/ frontend/src/components/script-builder/ frontend/src/components/account/ +git commit -m "refactor: migrate session, script-builder, account to Design System v4 + +Co-Authored-By: Claude Opus 4.6 (1M context) " +``` + +--- + +## Task 7: Component Sweep — All Remaining + +**Files:** +- Modify: `frontend/src/components/common/` (~22 files) +- Modify: `frontend/src/components/tree-editor/` (~20 files) +- Modify: `frontend/src/components/kb-accelerator/` (~5 files) +- Modify: `frontend/src/components/copilot/` (~3 files) +- Modify: `frontend/src/components/assistant/` (~3 files) +- Modify: `frontend/src/components/analytics/` (~3 files) +- Modify: `frontend/src/components/library/` (~3 files) +- Modify: `frontend/src/components/procedural/` (~3 files) +- Modify: `frontend/src/components/public/` (~3 files) +- Modify: `frontend/src/components/script-editor/` (~6 files) +- Modify: `frontend/src/components/ui/` (any using old patterns) +- Modify: `frontend/src/components/admin/` (~12 files) + +- [ ] **Step 1: Update all remaining component directories** + +Process each directory. Use the same pattern replacement map. + +- [ ] **Step 2: Verify build** + +Run: `cd frontend && npm run build` + +- [ ] **Step 3: Commit** + +```bash +git add frontend/src/components/ +git commit -m "refactor: migrate remaining components to Design System v4 + +Co-Authored-By: Claude Opus 4.6 (1M context) " +``` + +--- + +## Task 8: Landing Page + +**Files:** +- Modify: `frontend/src/pages/LandingPage.tsx` +- Modify: Landing page CSS (check if `landing.css` exists or if styles are in `index.css`) + +- [ ] **Step 1: Find landing page styles** + +```bash +find frontend/src -name "landing*" -o -name "Landing*" | head -10 +grep -r "landing" frontend/src/index.css | head -5 +``` + +- [ ] **Step 2: Update landing page** + +- Remove ambient glow effects, gradient overlays +- Hero: subtle radial gradient at 15% accent opacity +- Section labels: `font-mono`, 12px, uppercase, `text-[var(--color-accent-text)]` +- Section titles: `font-heading`, `clamp(28px, 4vw, 42px)`, weight 800 +- Pricing cards: `card-flat` with featured card getting `border-[var(--color-accent)]` +- Top nav: flat, no blur +- CTAs: `btn-primary` (solid accent) + +- [ ] **Step 3: Verify build** + +Run: `cd frontend && npm run build` + +- [ ] **Step 4: Commit** + +```bash +git add frontend/src/pages/LandingPage.tsx frontend/src/styles/landing.css +git commit -m "refactor: migrate landing page to Design System v4 + +Co-Authored-By: Claude Opus 4.6 (1M context) " +``` + +--- + +## Task 9: Cleanup & Verification + +**Files:** +- Modify: `frontend/src/index.css` +- Modify: `CLAUDE.md` (verify) + +- [ ] **Step 1: Remove compatibility shims** + +Remove from `index.css`: +- The `glass-card` shim utility +- The `glass-card-static` shim utility +- The `text-gradient-brand` shim utility +- The `active-glow` shim utility +- The `--font-label` alias (keep only `--font-mono`) +- Any remaining old gradient references + +- [ ] **Step 1.5: Update BrandWordmark.tsx** + +Check `frontend/src/components/common/BrandWordmark.tsx` for `text-gradient-brand` usage. Replace with `text-[var(--color-accent-text)]`. + +- [ ] **Step 2: Verify no old patterns remain** + +```bash +cd frontend && grep -r "glass-card\|glass-stat\|bg-gradient-brand\|text-gradient-brand\|backdrop-filter.*blur\|atmosphere-orb\|active-glow\|breatheGlow\|bellWobble" src/ --include="*.tsx" --include="*.css" | head -20 +``` + +Expected: Zero results (or only in comments/string literals). + +- [ ] **Step 3: Verify CLAUDE.md** + +Grep CLAUDE.md for any stale references to old design system patterns. Should already be clean from the doc-swap commit, but verify. + +- [ ] **Step 4: Final build verification** + +Run: `cd frontend && npm run build` +Expected: Clean build with zero errors. + +- [ ] **Step 5: Commit** + +```bash +git add frontend/src/index.css CLAUDE.md +git commit -m "chore: remove design system v3 compatibility shims + +All components migrated to v4 flat dark theme. +No glass-card, gradient, or blur references remain. + +Co-Authored-By: Claude Opus 4.6 (1M context) " +``` -- 2.49.1 From 04992846797896ab34c4f2fa9622fe73564feb2c Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Sun, 22 Mar 2026 00:19:21 -0400 Subject: [PATCH 04/37] refactor: rewrite CSS foundation for Design System v4 New flat dark color tokens, remove glass/gradient utilities, add compatibility shims for phased migration. Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/index.css | 325 ++++++++++++++++++----------------------- 1 file changed, 143 insertions(+), 182 deletions(-) diff --git a/frontend/src/index.css b/frontend/src/index.css index b40e3f7c..045ce347 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -8,186 +8,104 @@ @import '@xyflow/react/dist/style.css'; @theme { - /* ── Brand tokens ─────────────────────────────────── */ - --color-brand-gradient-from: oklch(0.65 0.13 195); /* #06b6d4 cyan-500 */ - --color-brand-gradient-to: oklch(0.74 0.12 195); /* #22d3ee cyan-400 */ - --color-brand-dark: oklch(0.145 0.013 264); /* #101114 */ - --color-brand-dark-card: oklch(0.17 0.01 264); /* #14161a */ - --color-brand-dark-surface: oklch(0.17 0.01 264); /* #14161a */ - --color-brand-text-primary: oklch(0.98 0.005 264); /* #f8fafc */ - --color-brand-text-secondary: oklch(0.63 0.02 260); /* #8891a0 */ - --color-brand-text-muted: oklch(0.45 0.015 260); /* #5a6170 */ - --color-brand-border: oklch(0.35 0 0 / 0.06); + /* ── Surface colors ────────────────────────────── */ + --color-bg-page: #0c0d10; + --color-bg-sidebar: #0f1118; + --color-bg-card: #14161d; + --color-bg-card-hover: #191c25; + --color-bg-input: #191c25; + --color-bg-code: #0e1017; + --color-bg-elevated: #1c1f2a; - /* ── Semantic color tokens (OKLCH, direct values) ── */ - --color-background: oklch(0.145 0.013 264); /* dark charcoal #101114 */ - --color-foreground: oklch(0.98 0.005 264); /* near-white #f8fafc */ + /* ── Text colors ───────────────────────────────── */ + --color-text-heading: #f0f2f5; + --color-text-primary: #e2e5eb; + --color-text-secondary: #848b9b; + --color-text-muted: #4f5666; + --color-text-rail-label: #6b7280; - --color-card: oklch(0.178 0.008 264); /* #17191d */ - --color-card-foreground: oklch(0.98 0.005 264); + /* ── Border colors ─────────────────────────────── */ + --color-border-default: #1e2130; + --color-border-hover: #2a2f3d; - --color-popover: oklch(0.178 0.008 264); - --color-popover-foreground: oklch(0.98 0.005 264); + /* ── Accent (cyan) ─────────────────────────────── */ + --color-accent: #22d3ee; + --color-accent-hover: #06b6d4; + --color-accent-dim: rgba(34,211,238,0.10); + --color-accent-text: #67e8f9; - --color-primary: oklch(0.65 0.13 195); /* cyan #1ea8c4 */ - --color-primary-foreground: oklch(0.145 0.013 264); /* dark bg for contrast */ + /* ── Semantic colors ───────────────────────────── */ + --color-success: #34d399; + --color-success-dim: rgba(52,211,153,0.10); + --color-warning: #fbbf24; + --color-warning-dim: rgba(251,191,36,0.10); + --color-danger: #f87171; + --color-danger-dim: rgba(248,113,113,0.10); - --color-secondary: oklch(0.22 0.008 264); /* #212329 */ - --color-secondary-foreground: oklch(0.98 0.005 264); + /* ── Tailwind semantic mappings ─────────────────── */ + --color-background: #0c0d10; + --color-foreground: #e2e5eb; + --color-card: #14161d; + --color-card-foreground: #e2e5eb; + --color-popover: #14161d; + --color-popover-foreground: #e2e5eb; + --color-primary: #22d3ee; + --color-primary-foreground: #ffffff; + --color-secondary: #1c1f2a; + --color-secondary-foreground: #e2e5eb; + --color-muted: #1c1f2a; + --color-muted-foreground: #848b9b; + --color-accent-tw: #1c1f2a; + --color-accent-foreground: #e2e5eb; + --color-destructive: #f87171; + --color-destructive-foreground: #ffffff; + --color-border: #1e2130; + --color-input: #191c25; + --color-ring: #22d3ee; - --color-muted: oklch(0.22 0.008 264); - --color-muted-foreground: oklch(0.63 0.02 260); /* #8891a0 */ + /* ── Radii ─────────────────────────────────────── */ + --radius-sm: 5px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-xl: 16px; - --color-accent: oklch(0.22 0.008 264); - --color-accent-foreground: oklch(0.98 0.005 264); - - --color-destructive: oklch(0.55 0.22 15); /* rose #e63359 */ - --color-destructive-foreground: oklch(0.98 0.005 264); - - --color-border: oklch(0.22 0.008 264); - --color-input: oklch(0.22 0.008 264); - --color-ring: oklch(0.65 0.13 195); /* cyan, matches primary */ - - /* ── Radii ───────────────────────────────────────── */ - --radius-sm: 0.5rem; - --radius-md: 0.625rem; - --radius-lg: 0.75rem; - --radius-xl: 1rem; - - /* ── Fonts ───────────────────────────────────────── */ - --font-sans: - 'IBM Plex Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', - Roboto, sans-serif; + /* ── Fonts ─────────────────────────────────────── */ + --font-sans: 'IBM Plex Sans', system-ui, -apple-system, sans-serif; --font-heading: 'Bricolage Grotesque', system-ui, sans-serif; - --font-label: 'JetBrains Mono', monospace; + --font-mono: 'JetBrains Mono', monospace; + --font-label: 'JetBrains Mono', monospace; /* deprecated alias — remove in Phase 5 */ - /* ── Gradients ───────────────────────────────────── */ - --background-image-gradient-brand: linear-gradient( - 135deg, - oklch(0.65 0.13 195) 0%, - oklch(0.74 0.12 195) 100% - ); - --background-image-gradient-brand-hover: linear-gradient( - 135deg, - oklch(0.58 0.12 195) 0%, - oklch(0.65 0.13 195) 100% - ); - - /* ── Animations (keyframes inside @theme) ────────── */ + /* ── Animations ────────────────────────────────── */ --animate-fade-in: fade-in 200ms ease-out; --animate-fade-in-up: fade-in-up 200ms ease-out; --animate-slide-in-left: slide-in-from-left 200ms ease-out; --animate-slide-in-bottom: slide-in-from-bottom 200ms ease-out; --animate-scale-in: scale-in 150ms ease-out; - --animate-slide-down: slideDown 400ms ease-out; - --animate-slide-in-right: slideInRight 300ms ease-out; - --animate-fade-in-right: fadeInRight 400ms ease-out; - --animate-breathe-glow: breatheGlow 3s ease-in-out infinite alternate; - --animate-bell-wobble: bellWobble 500ms ease-in-out; --animate-fade: fadeIn 300ms ease forwards; @keyframes fade-in { - from { opacity: 0; } - to { opacity: 1; } + from { opacity: 0; } to { opacity: 1; } } - @keyframes fade-in-up { - from { opacity: 0; transform: translateY(4px); } - to { opacity: 1; transform: translateY(0); } + from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } } - @keyframes slide-in-from-left { - from { transform: translateX(-100%); } - to { transform: translateX(0); } + from { transform: translateX(-100%); } to { transform: translateX(0); } } - @keyframes slide-in-from-bottom { - from { opacity: 0; transform: translateY(16px); } - to { opacity: 1; transform: translateY(0); } + from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } } - @keyframes scale-in { - from { opacity: 0; transform: scale(0.95); } - to { opacity: 1; transform: scale(1); } + from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } - - @keyframes slideDown { - from { transform: translateY(-100%); opacity: 0; } - to { transform: translateY(0); opacity: 1; } - } - - @keyframes slideInRight { - from { transform: translateX(100%); } - to { transform: translateX(0); } - } - - @keyframes fadeInRight { - from { transform: translateX(30px); opacity: 0; } - to { transform: translateX(0); opacity: 1; } - } - @keyframes fadeIn { - from { opacity: 0; transform: translateY(6px); } - to { opacity: 1; transform: translateY(0); } - } - - @keyframes breatheGlow { - from { - box-shadow: - 0 8px 32px rgba(0, 0, 0, 0.3), - 0 0 20px oklch(0.65 0.13 195 / 0.04); - } - to { - box-shadow: - 0 8px 32px rgba(0, 0, 0, 0.3), - 0 0 30px oklch(0.65 0.13 195 / 0.12); - } - } - - @keyframes bellWobble { - 0% { transform: rotate(0deg); } - 20% { transform: rotate(8deg); } - 40% { transform: rotate(-6deg); } - 60% { transform: rotate(4deg); } - 80% { transform: rotate(-2deg); } - 100% { transform: rotate(0deg); } - } - - @keyframes pulse-dot { - 0%, 100% { box-shadow: 0 0 4px rgba(52,211,153,0.4); } - 50% { box-shadow: 0 0 8px rgba(52,211,153,0.7); } - } - - @keyframes stagger-fade-in { - from { opacity: 0; transform: translateY(8px); } - to { opacity: 1; transform: translateY(0); } + from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } } } -/* ── Root CSS variables (non-theme: glass, shadows, layout) ── */ :root { - /* App Shell tokens */ - --sidebar-w: 260px; - --sidebar-bg: oklch(0.13 0.013 264); - --sidebar-hover: var(--color-secondary); - --sidebar-active: oklch(0.65 0.13 195 / 0.10); - --text-dimmed: oklch(0.42 0.015 260); - - /* Glass system */ - --glass-bg: oklch(0.16 0.01 264 / 0.55); - --glass-bg-hover: oklch(0.16 0.01 264 / 0.7); - --glass-border: oklch(1 0 0 / 0.06); - --glass-border-hover: oklch(1 0 0 / 0.12); - --glass-blur: blur(16px); - --glass-blur-strong: blur(20px); - --glass-blur-light: blur(12px); - - /* Shadow system */ - --shadow-float: 0 8px 32px rgba(0, 0, 0, 0.3); - --shadow-float-hover: 0 12px 40px rgba(0, 0, 0, 0.4), 0 0 0 1px oklch(1 0 0 / 0.08); - --shadow-cyan-glow: 0 8px 32px oklch(0.65 0.13 195 / 0.08); - - /* Easing */ + --sidebar-w: 72px; + --sidebar-w-pinned: 260px; --ease-out-smooth: cubic-bezier(0.4, 0, 0.2, 1); } @@ -224,52 +142,91 @@ } } -/* ── Custom utilities ────────────────────────────────── */ -@utility btn-press { - @apply active:scale-[0.98] transition-transform; -} - -@utility text-gradient-brand { - @apply bg-gradient-brand bg-clip-text text-transparent; -} - +/* ── Deprecated shims — remove after Phase 3 sweep ── */ @utility glass-card { - background: var(--glass-bg); - backdrop-filter: var(--glass-blur); - -webkit-backdrop-filter: var(--glass-blur); - border: 1px solid var(--glass-border); - border-radius: 16px; - box-shadow: var(--shadow-float); - transition: - transform 200ms var(--ease-out-smooth), - border-color 200ms var(--ease-out-smooth), - box-shadow 200ms var(--ease-out-smooth); + background: var(--color-bg-card); + border: 1px solid var(--color-border-default); + border-radius: 8px; + transition: border-color 200ms ease; &:hover { - transform: scale(1.02); - border-color: var(--glass-border-hover); - box-shadow: var(--shadow-float-hover); + border-color: var(--color-border-hover); } } @utility glass-card-static { - background: var(--glass-bg); - backdrop-filter: var(--glass-blur); - -webkit-backdrop-filter: var(--glass-blur); - border: 1px solid var(--glass-border); - border-radius: 16px; - box-shadow: var(--shadow-float); + background: var(--color-bg-card); + border: 1px solid var(--color-border-default); + border-radius: 8px; +} + +@utility text-gradient-brand { + color: var(--color-accent-text); } @utility active-glow { - animation: breatheGlow 3s ease-in-out infinite alternate; + /* glow removed in v4 — kept as no-op shim */ + --_active-glow: 1; +} + +@utility bg-gradient-brand-hover { + &:hover { filter: brightness(1.1); } } @utility stagger-item { opacity: 0; - animation: stagger-fade-in 350ms var(--ease-out-smooth) forwards; + animation: fadeIn 350ms var(--ease-out-smooth) forwards; animation-delay: calc(var(--stagger-index, 0) * 50ms); } +@utility btn-press { + @apply active:scale-[0.98] transition-transform; +} + +/* ── New component classes (Design System v4) ───── */ +@utility card-flat { + background: var(--color-bg-card); + border: 1px solid var(--color-border-default); + border-radius: 8px; +} + +@utility card-interactive { + background: var(--color-bg-card); + border: 1px solid var(--color-border-default); + border-radius: 8px; + transition: border-color 200ms ease; + &:hover { + border-color: var(--color-border-hover); + } +} + +@utility btn-primary-v4 { + background: var(--color-accent); + color: #ffffff; + font-weight: 550; + border-radius: 5px; + padding: 9px 16px; + font-size: 13px; + transition: filter 150ms ease; + &:hover { + filter: brightness(1.1); + } +} + +@utility btn-ghost-v4 { + background: transparent; + color: var(--color-text-secondary); + border: 1px solid var(--color-border-default); + border-radius: 5px; + padding: 9px 16px; + font-size: 13px; + transition: background 150ms ease, color 150ms ease, border-color 150ms ease; + &:hover { + background: var(--color-bg-elevated); + color: var(--color-text-primary); + border-color: var(--color-border-hover); + } +} + @utility rdp-custom { @apply text-foreground; & .rdp-month { @apply w-full; } @@ -294,12 +251,16 @@ .app-shell { display: grid; grid-template-columns: var(--sidebar-w) 1fr; - grid-template-rows: 56px 1fr; + grid-template-rows: auto 1fr; height: 100vh; overflow: hidden; transition: grid-template-columns 200ms ease; } + .app-shell--pinned { + --sidebar-w: 260px; + } + .app-shell--collapsed { grid-template-columns: 56px 1fr; } @@ -387,7 +348,7 @@ /* ── React Flow dark theme overrides ─────────────────── */ /* React Flow v12 uses --xy-* CSS custom properties for theming. - Override the defaults to match our Slate & Ice design system. */ + Override the defaults to match our design system. */ .react-flow.dark { --xy-background-color-default: transparent; --xy-edge-stroke-default: var(--color-border); @@ -400,7 +361,7 @@ --xy-handle-background-color-default: var(--color-border); --xy-handle-border-color-default: var(--color-card); --xy-minimap-background-color-default: var(--color-card); - --xy-minimap-mask-background-color-default: oklch(0.22 0.008 264 / 0.6); + --xy-minimap-mask-background-color-default: rgba(28, 31, 42, 0.6); --xy-controls-button-background-color-default: var(--color-card); --xy-controls-button-background-color-hover-default: var(--color-accent); --xy-controls-button-color-default: var(--color-muted-foreground); -- 2.49.1 From 8efc44394987472e92909a6233712e5f46cebcbb Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Sun, 22 Mar 2026 00:26:19 -0400 Subject: [PATCH 05/37] refactor: implement icon rail sidebar for Design System v4 72px icon rail with hover flyouts, pin-to-expand toggle (260px), keyboard accessible, mobile hamburger overlay. Flat TopBar styling (no blur/glass). New BrandLogo mark (gradient square + lightning bolt). BrandWordmark uses solid text color instead of gradient. Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/components/common/BrandLogo.tsx | 57 +- .../src/components/common/BrandWordmark.tsx | 5 +- frontend/src/components/layout/AppLayout.tsx | 70 +-- frontend/src/components/layout/Sidebar.tsx | 511 +++++++++++++----- frontend/src/components/layout/TopBar.tsx | 66 ++- frontend/src/index.css | 1 + frontend/src/store/userPreferencesStore.ts | 4 + 7 files changed, 477 insertions(+), 237 deletions(-) diff --git a/frontend/src/components/common/BrandLogo.tsx b/frontend/src/components/common/BrandLogo.tsx index 9b952c9b..83e287a1 100644 --- a/frontend/src/components/common/BrandLogo.tsx +++ b/frontend/src/components/common/BrandLogo.tsx @@ -5,37 +5,36 @@ interface BrandLogoProps { className?: string } +/** + * Brand logo mark: gradient cyan square with rounded corners + * containing a white lightning bolt. + */ export function BrandLogo({ size = 'sm', className }: BrandLogoProps) { - const sizeClasses = size === 'sm' ? 'h-8 w-8' : 'h-20 w-20' - const strokeBase = size === 'sm' ? 1 : 2 - const strokeThick = size === 'sm' ? 1.25 : 2.5 - const dashArray = size === 'sm' ? '1 1.5' : '2 3' - const nodeR = size === 'sm' ? { outer: 2.5, inner: 2.75 } : { outer: 5, inner: 5.5 } - const hubR = size === 'sm' ? { glow: 5, solid: 3.5 } : { glow: 10, solid: 7 } - const vb = size === 'sm' ? '0 0 40 40' : '0 0 80 80' - const s = size === 'sm' ? 1 : 2 - const gradId = size === 'sm' ? 'logoGradSm' : 'logoGradLg' - const gradEnd = String(40 * (size === 'sm' ? 1 : 2)) + const dim = size === 'sm' ? 30 : 64 return ( - - - - - - - - - - - - - - - - - - - +
+ + + +
) } diff --git a/frontend/src/components/common/BrandWordmark.tsx b/frontend/src/components/common/BrandWordmark.tsx index bd0e9318..a5eadf82 100644 --- a/frontend/src/components/common/BrandWordmark.tsx +++ b/frontend/src/components/common/BrandWordmark.tsx @@ -9,13 +9,12 @@ export function BrandWordmark({ size = 'sm', className }: BrandWordmarkProps) { return ( - Resolution - Flow + ResolutionFlow ) } diff --git a/frontend/src/components/layout/AppLayout.tsx b/frontend/src/components/layout/AppLayout.tsx index cc870ab0..d9ea115f 100644 --- a/frontend/src/components/layout/AppLayout.tsx +++ b/frontend/src/components/layout/AppLayout.tsx @@ -1,6 +1,6 @@ import { useEffect, useState, useCallback } from 'react' import { useLocation, useNavigate, Link } from 'react-router-dom' -import { Menu, X, LayoutGrid, Clock, Network, AlertTriangle, Code2, Wand2, BarChart3, Settings, LogOut, Shield, Library } from 'lucide-react' +import { Menu, X, LayoutGrid, Clock, AlertTriangle, GitBranch, Code2, Wand2, BarChart3, Settings, LogOut, Shield, Layers } from 'lucide-react' import { useAuthStore } from '@/store/authStore' import { usePermissions } from '@/hooks/usePermissions' import { useUserPreferencesStore } from '@/store/userPreferencesStore' @@ -16,7 +16,7 @@ export function AppLayout() { const navigate = useNavigate() const { user, logout } = useAuthStore() const { effectiveRole } = usePermissions() - const sidebarCollapsed = useUserPreferencesStore(s => s.sidebarCollapsed) + const sidebarPinned = useUserPreferencesStore(s => s.sidebarPinned) const [mobileMenuOpen, setMobileMenuOpen] = useState(false) // Close mobile menu on route change @@ -54,8 +54,8 @@ export function AppLayout() { { path: '/', label: 'Dashboard', icon: LayoutGrid }, { path: '/sessions', label: 'Active Sessions', icon: Clock }, { path: '/escalations', label: 'Escalations', icon: AlertTriangle }, - { path: '/trees', label: 'Flows', icon: Network }, - { path: '/step-library', label: 'Step Library', icon: Library }, + { path: '/trees', label: 'Flows', icon: GitBranch }, + { path: '/step-library', label: 'Step Library', icon: Layers }, { path: '/scripts', label: 'Scripts', icon: Code2 }, { path: '/script-builder', label: 'Script Builder', icon: Wand2 }, { path: '/analytics', label: 'Analytics', icon: BarChart3 }, @@ -64,34 +64,8 @@ export function AppLayout() { return ( <> - {/* Atmosphere orbs — ambient light behind glass */}
-
- -
{/* Top Bar - spans full width */} @@ -104,8 +78,9 @@ export function AppLayout() { {/* Mobile hamburger - overlaid on topbar */} +
+ + ) + } + + /* Icon Rail (default) */ return ( diff --git a/frontend/src/components/layout/TopBar.tsx b/frontend/src/components/layout/TopBar.tsx index bc31852f..c463bdb5 100644 --- a/frontend/src/components/layout/TopBar.tsx +++ b/frontend/src/components/layout/TopBar.tsx @@ -35,7 +35,7 @@ export function TopBar() { return () => document.removeEventListener('mousedown', handleClickOutside) }, [userMenuOpen]) - // ⌘K / Ctrl+K global shortcut + // Cmd+K / Ctrl+K global shortcut const handleGlobalKeyDown = useCallback((e: KeyboardEvent) => { if ((e.metaKey || e.ctrlKey) && e.key === 'k') { e.preventDefault() @@ -55,12 +55,10 @@ export function TopBar() { return ( <>
{/* Logo area */} @@ -68,10 +66,9 @@ export function TopBar() { to="/" className="flex items-center gap-2.5 pr-4 transition-all duration-200" > - - - Resolution - Flow + + + ResolutionFlow @@ -84,17 +81,28 @@ export function TopBar() { className="hidden sm:relative sm:block w-full text-left" style={{ maxWidth: '480px' }} > - -
- Search flows, sessions, tags… + +
{ (e.currentTarget as HTMLElement).style.borderColor = '#2a2f3d' }} + onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.borderColor = '#1e2130' }} + > + Search flows, sessions, tags...
- - {navigator.platform?.toLowerCase().includes('mac') ? '⌘K' : 'Ctrl+K'} + + {navigator.platform?.toLowerCase().includes('mac') ? '\u2318K' : 'Ctrl+K'} @@ -125,18 +133,22 @@ export function TopBar() {
{userMenuOpen && ( -
-
-

{user?.name || user?.email}

+
+
+

{user?.name || user?.email}

{effectiveRole && effectiveRole !== 'engineer' && ( - + {effectiveRole === 'super_admin' ? 'Super Admin' : effectiveRole === 'owner' ? 'Owner' : 'Viewer'} @@ -145,7 +157,7 @@ export function TopBar() { setUserMenuOpen(false)} - className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-muted-foreground hover:bg-accent hover:text-foreground" + className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]" > Account @@ -154,18 +166,18 @@ export function TopBar() { setUserMenuOpen(false)} - className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-muted-foreground hover:bg-accent hover:text-foreground" + className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]" > Admin Panel )} -
+
+
+ + + {/* Drawer panel — full height, resizable */} + {activeFlyoutGroup && activeFlyoutGroup.children && ( +
- - Pin - -
- +
+ {/* Drawer header */} +
+

+ {activeFlyoutGroup.label} +

+
+ + {/* Drawer items */} +
+ {activeFlyoutGroup.children.map(child => ( + + {child.label} + {child.count !== undefined && ( + {child.count} + )} + + ))} +
+
+ + {/* Resize handle */} +
+
+ )} +
) } -- 2.49.1 From 6fb0d9bf812473f12a0da53610ef872eef72594b Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Sun, 22 Mar 2026 01:39:14 -0400 Subject: [PATCH 11/37] fix: increase drawer close delay to 400ms for usability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 120ms was too fast — mouse couldn't traverse the gap between rail icon and drawer panel without triggering close. Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/components/layout/Sidebar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/layout/Sidebar.tsx b/frontend/src/components/layout/Sidebar.tsx index ddf9b6e3..527bf6c2 100644 --- a/frontend/src/components/layout/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar.tsx @@ -178,7 +178,7 @@ export function Sidebar() { } const closeFlyout = () => { - flyoutTimeout.current = setTimeout(() => setFlyoutIndex(null), 120) + flyoutTimeout.current = setTimeout(() => setFlyoutIndex(null), 400) } const keepFlyout = () => { -- 2.49.1 From 585149fa94bf6b671d47d25becfe3e6fcbb5ca83 Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Sun, 22 Mar 2026 01:40:57 -0400 Subject: [PATCH 12/37] fix: drawer stays open when moving mouse from rail to drawer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove onMouseLeave from individual rail items — only the outer wrapper handles close. Items only handle onMouseEnter to switch which drawer is shown. Prevents premature drawer dismissal. Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/components/layout/Sidebar.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/src/components/layout/Sidebar.tsx b/frontend/src/components/layout/Sidebar.tsx index 527bf6c2..bb6184fc 100644 --- a/frontend/src/components/layout/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar.tsx @@ -246,13 +246,11 @@ export function Sidebar() { key={key} className="relative w-full" onMouseEnter={() => hasChildren && !sidebarPinned ? openFlyout(key) : undefined} - onMouseLeave={() => hasChildren && !sidebarPinned ? closeFlyout() : undefined} > prefetchForRoute(item.href)} onFocus={() => hasChildren && !sidebarPinned ? openFlyout(key) : undefined} - onBlur={() => hasChildren && !sidebarPinned ? closeFlyout() : undefined} className={cn( 'group relative flex flex-col items-center justify-center rounded-lg px-1 py-2 transition-all duration-150', active -- 2.49.1 From 97a20a422585e4819c79ba724674e935035dbe0f Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Sun, 22 Mar 2026 01:42:32 -0400 Subject: [PATCH 13/37] fix: drawer uses fixed positioning to overlay main content Grid cell was clipping the drawer at 72px. Now uses position: fixed with left: 72px so it overlays the main content area and links are clickable. Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/components/layout/Sidebar.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/layout/Sidebar.tsx b/frontend/src/components/layout/Sidebar.tsx index bb6184fc..339aeb0a 100644 --- a/frontend/src/components/layout/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar.tsx @@ -436,16 +436,18 @@ export function Sidebar() {
- {/* Drawer panel — full height, resizable */} + {/* Drawer panel — fixed position, full height, resizable, overlays main content */} {activeFlyoutGroup && activeFlyoutGroup.children && (
Date: Sun, 22 Mar 2026 01:56:27 -0400 Subject: [PATCH 14/37] refactor: migrate FlowPilot components to Design System v4 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../flowpilot/AISessionListItem.tsx | 12 ++-- .../flowpilot/ConfidenceIndicator.tsx | 8 +-- .../components/flowpilot/EscalateModal.tsx | 6 +- .../components/flowpilot/EscalationQueue.tsx | 26 ++++----- .../flowpilot/FlowPilotActionBar.tsx | 26 ++++----- .../components/flowpilot/FlowPilotIntake.tsx | 36 ++++++------ .../flowpilot/FlowPilotMessageBar.tsx | 12 ++-- .../components/flowpilot/FlowPilotOptions.tsx | 10 ++-- .../components/flowpilot/FlowPilotSession.tsx | 49 ++++++++--------- .../flowpilot/FlowPilotStepCard.tsx | 38 ++++++------- .../flowpilot/InSessionScriptGenerator.tsx | 26 ++++----- .../src/components/flowpilot/ProposalCard.tsx | 16 +++--- .../components/flowpilot/ProposalDetail.tsx | 55 +++++++++---------- .../components/flowpilot/SessionBriefing.tsx | 40 +++++++------- .../components/flowpilot/SessionDocView.tsx | 44 +++++++-------- .../flowpilot/SessionTicketCard.tsx | 16 +++--- .../components/flowpilot/SimilarSessions.tsx | 20 +++---- 17 files changed, 219 insertions(+), 221 deletions(-) diff --git a/frontend/src/components/flowpilot/AISessionListItem.tsx b/frontend/src/components/flowpilot/AISessionListItem.tsx index 0dc1852d..6a139b72 100644 --- a/frontend/src/components/flowpilot/AISessionListItem.tsx +++ b/frontend/src/components/flowpilot/AISessionListItem.tsx @@ -8,7 +8,7 @@ interface AISessionListItemProps { } const STATUS_CONFIG = { - active: { icon: Clock, color: 'text-primary', label: 'Active' }, + active: { icon: Clock, color: 'text-[#22d3ee]', label: 'Active' }, paused: { icon: Pause, color: 'text-amber-400', label: 'Paused' }, resolved: { icon: CheckCircle2, color: 'text-emerald-400', label: 'Resolved' }, escalated: { icon: ArrowUpRight, color: 'text-amber-400', label: 'Escalated' }, @@ -22,16 +22,16 @@ export function AISessionListItem({ session }: AISessionListItemProps) { return (
-

+

{session.problem_summary || 'Untitled session'}

{session.problem_domain && ( - + {session.problem_domain} )} @@ -39,7 +39,7 @@ export function AISessionListItem({ session }: AISessionListItemProps) { {config.label} - + {session.step_count} steps @@ -50,7 +50,7 @@ export function AISessionListItem({ session }: AISessionListItemProps) {
{session.session_rating && ( - + {'★'.repeat(session.session_rating)} )} diff --git a/frontend/src/components/flowpilot/ConfidenceIndicator.tsx b/frontend/src/components/flowpilot/ConfidenceIndicator.tsx index 484c2566..0db26e65 100644 --- a/frontend/src/components/flowpilot/ConfidenceIndicator.tsx +++ b/frontend/src/components/flowpilot/ConfidenceIndicator.tsx @@ -30,12 +30,12 @@ export function ConfidenceIndicator({ tier, score, className }: ConfidenceIndica return (
- {config.label} + {config.label} {/* Tooltip */} -
-

{config.description}

-

+

+

{config.description}

+

Confidence: {Math.round(score * 100)}%

diff --git a/frontend/src/components/flowpilot/EscalateModal.tsx b/frontend/src/components/flowpilot/EscalateModal.tsx index 4ba06fd7..49bbfd65 100644 --- a/frontend/src/components/flowpilot/EscalateModal.tsx +++ b/frontend/src/components/flowpilot/EscalateModal.tsx @@ -43,7 +43,7 @@ export function EscalateModal({ open, onClose, onEscalate, isProcessing, hasPsaT
-