Files
resolutionflow/UI-DESIGN-SYSTEM.md
Michael Chihlas 58a55f4d88 feat: remove workspace system, add pinned flows and label renames
Replace workspace system with pinned flows API (pin/unpin/list/reorder).
Rename user-facing labels: Tree→Flow, Procedure→Project. Add sidebar
nav sub-items for flow type filtering. Remove 11 workspace files,
add migrations 037-038, clean all workspace references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:06:10 -05:00

807 lines
28 KiB
Markdown

# ResolutionFlow UI Design System & Layout Architecture
> **Purpose:** This document defines the app-shell layout, design tokens, component patterns, and navigation architecture for ResolutionFlow. It is the single source of truth for all frontend UI work going forward.
> **Last Updated:** February 15, 2026
> **Status:** Approved for implementation (v2 — workspace system removed, replaced with flat nav + type sub-items)
> **Reference Mockup:** `docs/mockups/resolutionflow-workspaces-mockup.html` (interactive — note: mockup shows old workspace switcher design which has been superseded by this document)
---
## IMPORTANT: Changes from Previous Version
This is version 2 of the design system. The following changes were made based on UX research and product decisions:
1. **Workspace system REMOVED.** The workspace switcher, workspace table, workspace API, `workspaceStore`, and all workspace-related components should be removed. Workspaces added unnecessary cognitive overhead and context-switching cost for the current scale of the product.
2. **"Procedures" renamed to "Projects"** in all user-facing labels. The `tree_type` database column retains the value `'procedural'` — only UI labels change.
3. **"Trees" renamed to "Flows"** in all user-facing labels. "Tree" is an internal/technical term. Users see "Flows" everywhere.
4. **Flow type filtering** is handled via nav sub-items (All Flows → Troubleshooting / Projects), not workspaces.
5. **Pinned Flows** section added to sidebar for quick access to favorites.
6. **Folder sidebar panel REMOVED** from the flow library page. Folders remain in the database and API but are not displayed as a persistent second panel. Folder organization is deferred to a future release.
7. **Search bar centered** in the top bar (flex spacers on both sides).
8. **Keyboard shortcut badge** is platform-aware: `⌘K` on Mac, `Ctrl+K` on Windows/Linux.
### Files to Remove or Deprecate
These files were created for the workspace system and should be **deleted**:
```
frontend/src/store/workspaceStore.ts → DELETE (replace with flowFilterStore.ts)
frontend/src/api/workspaces.ts → DELETE
frontend/src/types/workspace.ts → DELETE (remove Workspace type)
frontend/src/components/workspace/ → DELETE entire directory
frontend/src/constants/workspaceLabels.ts → DELETE (replace with flowLabels.ts)
backend/app/models/workspace.py → DELETE
backend/app/api/endpoints/workspaces.py → DELETE
backend/app/schemas/workspace.py → DELETE (if exists)
```
### Database Migration
Create a new migration that:
1. Drops the `workspace_id` column from `trees` table (if added)
2. Drops the `workspace_id` column from `tree_categories` table (if added)
3. Drops the `workspaces` table
4. **Does NOT touch** the existing `tree_type` column — it stays as-is
Remove the workspace router from `backend/app/api/router.py`.
---
## Table of Contents
1. [Layout Architecture](#1-layout-architecture)
2. [Design Tokens](#2-design-tokens)
3. [Naming & Terminology](#3-naming--terminology)
4. [Sidebar Components](#4-sidebar-components)
5. [Top Bar](#5-top-bar)
6. [Main Content Area](#6-main-content-area)
7. [Component Patterns](#7-component-patterns)
8. [Icon System](#8-icon-system)
9. [Animation & Transitions](#9-animation--transitions)
10. [Migration Strategy](#10-migration-strategy)
11. [Implementation Phases](#11-implementation-phases)
---
## 1. Layout Architecture
### Overview
ResolutionFlow uses a **persistent sidebar + top bar + main content** layout. This mirrors the UX patterns MSP engineers already use in ConnectWise Automate, Datto RMM, and HaloPSA.
### Shell Structure
```
┌──────────────────────────────────────────────────────┐
│ TOP BAR (56px) — Logo, ── Search (centered) ──, User│
├──────────────┬───────────────────────────────────────┤
│ SIDEBAR │ MAIN CONTENT AREA │
│ (260px) │ │
│ │ Page Header + Actions │
│ Pinned │ Quick Stats Row │
│ Flows │ Filters Bar │
│ │ Content Sections │
│ Navigation │ (flow list, sessions, etc.) │
│ + sub-items │ │
│ │ │
│ Categories │ │
│ Tags │ │
│ │ │
│ ─────────── │ │
│ Team │ │
│ Settings │ │
└──────────────┴───────────────────────────────────────┘
```
### CSS Grid Implementation
```tsx
// AppLayout.tsx
<div className="app-shell">
<header className="topbar">...</header>
<nav className="sidebar">...</nav>
<main className="main-content">
<Outlet />
</main>
</div>
```
```css
.app-shell {
display: grid;
grid-template-columns: 260px 1fr;
grid-template-rows: 56px 1fr;
height: 100vh;
overflow: hidden;
}
.topbar {
grid-column: 1 / -1; /* spans full width */
}
.sidebar {
overflow-y: auto;
}
.main-content {
overflow-y: auto;
}
```
### CSS Variable for Sidebar Width
```css
:root {
--sidebar-w: 260px;
}
```
---
## 2. Design Tokens
### Existing Tokens (Already in tailwind.config.js and index.css)
These are already implemented and MUST be used. Do NOT introduce new color values that duplicate or conflict with these.
#### Brand Colors (from tailwind.config.js)
| Token | Value | Usage |
|-------|-------|-------|
| `brand.gradient.from` | `#818cf8` | Gradient start, primary accent |
| `brand.gradient.to` | `#a78bfa` | Gradient end |
| `brand.dark.DEFAULT` | `#09090b` | App background (dark mode) |
| `brand.dark.card` | `#18181b` | Card backgrounds |
| `brand.dark.surface` | `#12121c` | Elevated surface |
| `brand.text.primary` | `#ffffff` | Primary text |
| `brand.text.secondary` | `#a1a1aa` | Secondary text |
| `brand.text.muted` | `#52525b` | Muted/dim text |
| `brand.border` | `#27272a` | Standard borders |
#### Tailwind Utilities (from index.css)
| Utility | Description |
|---------|-------------|
| `bg-gradient-brand` | `linear-gradient(90deg, #818cf8, #a78bfa)` |
| `bg-gradient-brand-hover` | `linear-gradient(90deg, #6366f1, #9333ea)` |
| `text-gradient-brand` | Gradient text effect (uses bg-clip-text) |
| `font-heading` | Plus Jakarta Sans |
| `font-sans` | Inter |
| `font-label` | Outfit |
#### shadcn/ui CSS Variables (from index.css)
All shadcn component tokens are defined via HSL CSS variables (`--background`, `--foreground`, `--card`, `--primary`, etc.) in `:root`. The app is dark-only — all tokens live in `:root`, not `.dark`.
### App Shell Tokens (in index.css `:root`)
```css
:root {
/* App Shell tokens */
--sidebar-bg: 240 10% 4.5%;
--sidebar-hover: 240 6% 12%;
--sidebar-active: 243 75% 59% / 0.08;
--border-subtle: 240 6% 12%;
--text-dimmed: 240 4% 24%;
}
```
### Semantic Status Colors
| Status | Color | Tailwind Class | Usage |
|--------|-------|---------------|-------|
| Success / Resolved | `#22c55e` | `text-green-500` / `bg-green-500` | Completed sessions, resolved |
| Warning / In Progress | `#f59e0b` | `text-amber-500` / `bg-amber-500` | Open/active sessions |
| Error / Critical | `#ef4444` | `text-red-500` / `bg-red-500` | Failed, critical priority |
| Info | `#3b82f6` | `text-blue-500` / `bg-blue-500` | Informational, default |
### Category Colors
```typescript
// constants/categoryColors.ts
export const CATEGORY_COLORS = [
'#3b82f6', // blue
'#22c55e', // green
'#f59e0b', // amber
'#ef4444', // red
'#8b5cf6', // violet
'#06b6d4', // cyan
'#ec4899', // pink
'#f97316', // orange
'#14b8a6', // teal
'#6366f1', // indigo
] as const;
```
> **Migration needed:** Add `color` column to `tree_categories`:
> ```sql
> ALTER TABLE tree_categories ADD COLUMN color VARCHAR(7) DEFAULT '#3b82f6';
> ```
---
## 3. Naming & Terminology
### User-Facing Labels
| Internal / Database | User-Facing Label | Context |
|--------------------|--------------------|---------|
| `tree` | **Flow** | Universal term for all flow types |
| `tree_type = 'troubleshooting'` | **Troubleshooting** | Branching decision-tree flows |
| `tree_type = 'procedural'` | **Project** | Linear step-by-step flows (onboarding, migrations, etc.) |
| `tree_structure` | Flow structure | Internal — never shown to users |
| `tree_editor` | **Flow Editor** | The editor page |
| `session` | **Session** (troubleshooting) / **Run** (projects) | Active use of a flow |
### Label Constants
Replace `workspaceLabels.ts` with a simpler type-based label system:
```typescript
// constants/flowLabels.ts
export interface FlowTypeLabels {
navLabel: string;
newButton: string;
editorLabel: string;
searchPlaceholder: string;
}
export const FLOW_TYPE_LABELS: Record<string, FlowTypeLabels> = {
all: {
navLabel: 'All Flows',
newButton: '+ Create Flow',
editorLabel: 'Flow Editor',
searchPlaceholder: 'Search flows, sessions, tags…',
},
troubleshooting: {
navLabel: 'Troubleshooting',
newButton: '+ New Troubleshooting Flow',
editorLabel: 'Flow Editor',
searchPlaceholder: 'Search troubleshooting flows…',
},
procedural: {
navLabel: 'Projects',
newButton: '+ New Project',
editorLabel: 'Flow Editor',
searchPlaceholder: 'Search projects, runbooks…',
},
};
export function getFlowLabels(typeFilter: string): FlowTypeLabels {
return FLOW_TYPE_LABELS[typeFilter] || FLOW_TYPE_LABELS.all;
}
```
### Where Labels Appear
- Sidebar nav: "All Flows" (parent), "Troubleshooting" (sub), "Projects" (sub)
- Page title on flow library: "Flow Library" (always — does not change with filter)
- "+ Create Flow" button in page header (adapts based on active type filter)
- Search bar placeholder in top bar (adapts based on active type filter)
- Flow Editor nav item: Always "Flow Editor"
---
## 4. Sidebar Components
### Structure (top to bottom)
```
1. ─── PINNED FLOWS ─── (section, collapsible)
- Pinned flow items (star icon, click to start session)
- "Pin a flow…" hint if empty
2. ─── divider ───
3. Primary Navigation
- Dashboard (LayoutGrid icon)
- All Flows (Box icon) [badge: total count]
├─ Troubleshooting (sub-item, indented)
└─ Projects (sub-item, indented)
- Flow Editor (PenLine icon)
- Sessions (Clock icon) [badge: active count]
- Exports (FileText icon)
- Step Library (Bookmark icon) [dot: new items]
4. ─── divider ───
5. Categories Section
- Section label: "CATEGORIES"
- Category items with color dots and counts
6. ─── divider ───
7. Tags Section
- Section label: "POPULAR TAGS"
- Tag chips in a flex-wrap cloud
8. ─── spacer (flex-grow) ───
9. Footer (pinned to bottom)
- Team (Users icon)
- Settings (Settings icon)
```
### Pinned Flows Section
```tsx
interface PinnedFlow {
id: string;
name: string;
treeType: 'troubleshooting' | 'procedural';
categoryEmoji?: string;
}
interface PinnedFlowsSectionProps {
pinnedFlows: PinnedFlow[];
onFlowClick: (id: string) => void;
onUnpin: (id: string) => void;
}
```
**Visual design:**
- Section label: `PINNED` in `font-label text-[0.6875rem] uppercase tracking-wide text-muted-foreground`
- Each pinned flow: single line with emoji/icon + flow name (truncated) + quick-start button on hover
- Max 10 pinned flows visible; if more, show "View all pinned" link
- Empty state: subtle hint text "Star a flow to pin it here" with `text-muted-foreground text-xs`
- Collapsible via section header chevron
**Data model:**
- New junction table: `user_pinned_trees` (user_id UUID, tree_id UUID, pinned_at TIMESTAMPTZ, display_order INTEGER)
- API: `POST /api/v1/trees/{id}/pin`, `DELETE /api/v1/trees/{id}/pin`, `GET /api/v1/trees/pinned`
- Store: add `pinnedFlows` array to existing auth or a new lightweight `pinnedStore`
**Pin/unpin interaction:**
- Pin via: star icon on flow cards in library, three-dot menu → "Pin to sidebar", right-click context menu
- Unpin via: right-click pinned item → "Unpin", or three-dot menu on flow card
- Toast on pin: "📌 Pinned **Flow Name** to sidebar"
- Toast on unpin: "Unpinned **Flow Name**"
### Nav Item Component
```tsx
interface NavItemProps {
href: string;
icon: LucideIcon;
label: string;
badge?: number | 'dot';
isActive?: boolean;
children?: NavSubItem[]; // for expandable sub-items
}
interface NavSubItem {
href: string;
label: string;
count?: number;
isActive?: boolean;
}
```
**Active state styling:**
- Background: `var(--sidebar-active)` (brand purple at 8% opacity)
- Left border accent: 3px gradient bar (brand gradient, rounded right corners)
- Text: `text-foreground` (white)
- Icon: full opacity
**Inactive state styling:**
- Background: transparent
- Text: `text-muted-foreground`
- Icon: 70% opacity
- Hover: `var(--sidebar-hover)` background
### Nav Sub-Items (Flow Type Filter)
Sub-items appear indented under "All Flows":
```
📦 All Flows 47
🔧 Troubleshooting 29
📋 Projects 18
```
**Sub-item styling:**
- Indented: `pl-9` (aligns text with parent label, past the icon)
- No icon of their own (the emoji/text suffices, or use a small dot)
- Font: `text-[0.8125rem] text-muted-foreground`
- Active: same purple highlight as parent but without the left accent bar
- Count: right-aligned in `font-label text-xs text-muted-foreground`
**Behavior:**
- Clicking "All Flows" navigates to `/flows` (or `/trees` — use existing route) with no type filter
- Clicking "Troubleshooting" navigates to `/flows?type=troubleshooting`
- Clicking "Projects" navigates to `/flows?type=procedural`
- The active state highlights whichever is currently selected
- When a sub-item is active, the parent "All Flows" stays visually highlighted (dimmer) to show context
- Sub-items are always visible (not collapsible) — there are only 2
**Flow library page behavior:**
- Reads `type` from URL search params (already implemented in `TreeLibraryPage.tsx`)
- Filters the flow list accordingly
- Updates the page subtitle and "Create" button label via `getFlowLabels(typeFilter)`
- Categories, tags, stats, and sessions in the sidebar do NOT change — they show data across all types
### Category Item Component
```tsx
interface CategoryItemProps {
name: string;
color: string; // hex color for the dot
count: number;
onClick: () => void;
}
```
Renders as: `[●] Category Name .............. 12`
- 8px color dot (rounded full)
- Name in `text-sm text-muted-foreground`
- Count right-aligned in `font-label text-xs`
- Hover: `var(--sidebar-hover)` background, text brightens
### Tag Cloud Component
```tsx
interface TagCloudProps {
tags: string[];
onTagClick: (tag: string) => void;
activeTags?: string[];
}
```
- Background: `bg-card`, Border: `border-border`
- Text: `font-label text-xs` (Outfit)
- Active: purple-tinted background and border
- Gap: 4px
---
## 5. Top Bar
### Structure (left to right)
```
[Logo + Wordmark] | ──flex grow── | [Search Input (Ctrl+K / ⌘K)] | ──flex grow── | [Quick Launch] [Notifications] [Avatar]
```
The search bar is **centered** between the logo and action buttons using flex spacers on both sides.
### Logo Area
- Width: fits content (not fixed to sidebar width)
- Contains: ResolutionFlow logo SVG (32x32) + branded wordmark
- Wordmark: "Resolution" in white + "Flow" in gradient text
### Search Bar
- Width: 100%, max-width 480px
- **Centered** in the top bar via `flex-1` spacers on both sides
- Placeholder: "Search flows, sessions, tags…" (static — does NOT change with type filter)
- Left icon: magnifying glass (Lucide `Search`)
- Right badge: platform-aware keyboard shortcut hint
```tsx
{navigator.platform?.toLowerCase().includes('mac') ? '⌘K' : 'Ctrl+K'}
```
- Border: `border-border`, focus: `border-primary/30`
### Action Buttons
| Button | Icon | Behavior |
|--------|------|----------|
| Quick Launch | `Zap` (Lucide) | Opens quick-launch modal to start a session fast |
| Notifications | `Bell` (Lucide) | Opens notification panel. Red dot badge when unread |
| User Avatar | Initials circle | Opens user menu dropdown (profile, settings, logout) |
Avatar: 32px circle with brand gradient background, white initials in `font-heading text-xs font-bold`.
---
## 6. Main Content Area
### Page Structure
```
1. Page Header (title + action buttons)
2. Quick Stats Row (4 cards)
3. Filters Bar (chips)
4. Content Sections (flow list, sessions panel)
```
Not every page uses all sections. Dashboard/Flow Library uses all four. Flow Editor uses only the header.
### Quick Stats Row
4 stat cards in a CSS grid (`grid-template-columns: repeat(4, 1fr)`).
Each card:
- Background: `bg-card`
- Border: `border` (subtle, brightens on hover)
- Border radius: `rounded-xl`
- Padding: 16px 18px
- Label: `font-label text-[0.6875rem] uppercase tracking-wide text-muted-foreground`
- Value: `font-heading text-2xl font-bold`
- Meta: `text-[0.6875rem] text-[var(--text-dimmed)]`
Stat cards for the Flow Library page:
| Stat | Label | Value Source |
|------|-------|-------------|
| 1 | Active Flows | Total published flows (use `text-gradient-brand`) |
| 2 | Sessions Today | Sessions started today (number) |
| 3 | Open Sessions | In-progress sessions (use `text-amber-500` if > 0) |
| 4 | Docs Generated | Export count this month |
### Filters Bar
```
[All] [Recently Used] [My Flows] [Team Flows] [Defaults] | [⊗ More Filters]
```
Active chip: purple-tinted background/border.
> **Note:** The "Troubleshooting" / "Projects" type filter is handled by the **sidebar sub-items**, NOT by filter chips in this bar. The filters bar is for orthogonal filters (ownership, recency, status).
### Flow List Items
Grid layout per item:
```
grid-template-columns: 40px 1fr 130px 80px 100px 40px
icon info category uses updated actions
```
Each item:
- Background: `bg-card`, transparent border
- Hover: `border-border`, `bg-[var(--sidebar-hover)]`
- Border radius: `rounded-lg`
- Padding: 12px 16px
**Pin star:** Show a subtle star icon (Lucide `Star`) on hover, filled if pinned. Click to toggle pin.
**Actions three-dot menu includes:**
- Start Session
- Edit
- Duplicate
- Pin to Sidebar / Unpin from Sidebar
- Share
- Delete
### Sessions Panel
Contained card with header and rows:
```
┌ Recent Sessions ──────── [View All] ┐
│ ● DNS Resolution Failure → step 4/12 TKT-4821 12 min ago │
│ ● Account Lockout → step 6/18 TKT-4819 45 min ago │
│ ✓ Mail Flow ✓ Resolved TKT-4815 Yesterday │
└──────────────────────────────────────┘
```
Status dot colors: `bg-amber-500` (in-progress), `bg-green-500` (completed).
---
## 7. Component Patterns
### Buttons
| Variant | Background | Text | Shadow | Hover |
|---------|-----------|------|--------|-------|
| Primary | `bg-gradient-brand` | white | `shadow-lg shadow-primary/20` | Lift + stronger shadow |
| Secondary | `bg-card` | `text-muted-foreground` | border only | Border brightens |
Both: `rounded-lg px-4 py-2 text-sm font-semibold`, with icon support (16px Lucide icon + 6px gap).
### Badges
- **Count badge:** `bg-card border border-border rounded-full px-2 text-[0.6875rem] font-label`
- **Active count badge:** purple-tinted background/border
- **Dot badge:** 6px circle, `bg-brand-gradient-from`
- **Notification badge:** 8px red circle with sidebar-bg border
### Toast Notifications
Fixed-position, **top-right** (current Sonner config — keep as-is):
- Background: `bg-card`
- Border: brand gradient border
- Border radius: `rounded-xl`
- Auto-dismiss: 2000ms
---
## 8. Icon System
### Primary Source: Lucide React
| Context | Size |
|---------|------|
| Nav items | 18px |
| Buttons | 16px |
| Top bar actions | 18px |
| Section headers | 14px |
| Filter chips | 14px |
### Navigation Icon Mapping
| Nav Item | Lucide Icon |
|----------|-------------|
| Dashboard | `LayoutGrid` |
| All Flows | `Box` |
| Flow Editor | `PenLine` |
| Sessions | `Clock` |
| Exports | `FileText` |
| Step Library | `Bookmark` |
| Team | `Users` |
| Settings | `Settings` |
| Search | `Search` |
| Quick Launch | `Zap` |
| Notifications | `Bell` |
| Create Flow | `Plus` |
| Pin/Favorite | `Star` |
| More Actions | `MoreHorizontal` |
### Category Emoji Icons
Default emoji per common categories:
- Networking: 🌐, Active Directory: 🔒, Email/Exchange: 📧, Server Issues: 🖥️
- VPN/Remote: 🔌, Printers: 🖨️, Backup/DR: 🔄, Onboarding: 👤, Security: 🔐
---
## 9. Animation & Transitions
### Page/Section Load
Staggered fade-in with incrementing `animation-delay`:
- Stats row: 50ms
- Filters: 100ms
- Section 1: 150ms
- Section 2: 200ms
### Interactive Elements
| Element | Property | Duration | Easing |
|---------|----------|----------|--------|
| Nav item hover | background-color | 120ms | ease |
| Button hover | transform, box-shadow | 150ms | ease |
| Flow item hover | background, border-color | 120ms | ease |
| Dropdown open | opacity, transform | 150ms | ease |
| Action buttons (three-dot) | opacity | 120ms | ease |
| Toast appear/disappear | opacity, transform | 300ms | ease |
| Pin star toggle | scale + color | 200ms | ease |
---
## 10. Migration Strategy
### What to Remove
1. **WorkspaceSwitcher component** and all workspace UI
2. **workspaceStore.ts** — replace with `flowFilterStore.ts` (or just use URL params, which `TreeLibraryPage.tsx` already does)
3. **workspaceLabels.ts** — replace with `flowLabels.ts`
4. **Workspace API** (`backend/app/api/endpoints/workspaces.py`) and model
5. **Folder sidebar panel** from `TreeLibraryPage` — remove `FolderSidebar` import and the column it occupies. The `UserFolder` model, API, and database table remain untouched for future use.
6. All `workspace_id` references in queries
### What to Add
1. **Pinned flows** — `user_pinned_trees` table, API endpoints, sidebar section
2. **Nav sub-items** — update `Sidebar.tsx` to render "Troubleshooting" and "Projects" as indented children of "All Flows"
3. **flowLabels.ts** — simple type-based label lookup
4. **Pin star** on flow cards in the library grid/list views
### What to Keep (Already Built)
1. **AppLayout.tsx** CSS Grid shell — keep as-is
2. **TopBar.tsx** — keep, but verify search is centered and keyboard shortcut is platform-aware (already fixed)
3. **Sidebar.tsx** — keep structure, remove workspace switcher, add pinned flows section and nav sub-items
4. **NavItem.tsx** — keep, extend to support `children` sub-items
5. **CategoryList, TagCloud** — keep as-is
6. **All existing pages** — keep rendering inside the shell
### Label Replacements (Global Find & Replace)
In all frontend files:
| Find | Replace With |
|------|-------------|
| `All Trees` | `All Flows` |
| `Tree Editor` | `Flow Editor` |
| `New Tree` | `Create Flow` |
| `All Procedures` | `Projects` |
| `New Procedure` | `New Project` |
| `Flow Library` (page title) | `Flow Library` (keep) |
In `Sidebar.tsx` nav items:
- Remove workspace switcher
- Add pinned flows section at top
- "All Flows" with sub-items "Troubleshooting" and "Projects"
---
## 11. Implementation Phases
### Phase A: Cleanup & Labels
1. Remove workspace-related files (see list above)
2. Create down-migration to drop workspace tables/columns
3. Remove workspace router from `backend/app/api/router.py`
4. Create `constants/flowLabels.ts`
5. Update all UI labels: Trees → Flows, Procedures → Projects
6. Remove `FolderSidebar` from `TreeLibraryPage` (keep folder model/API)
7. Verify search bar is centered and shortcut is platform-aware in `TopBar.tsx`
### Phase B: Nav Sub-Items
1. Extend `NavItem` component to support `children` sub-items
2. Update `Sidebar.tsx` to render "All Flows" with "Troubleshooting" and "Projects" children
3. Sub-items link to `/trees?type=troubleshooting` and `/trees?type=procedural`
4. Verify `TreeLibraryPage.tsx` correctly reads `type` from URL params (already does)
5. Add flow counts to sub-item badges
### Phase C: Pinned Flows
1. Create `user_pinned_trees` table and Alembic migration
2. Create pin/unpin API endpoints (`POST /api/v1/trees/{id}/pin`, `DELETE /api/v1/trees/{id}/pin`, `GET /api/v1/trees/pinned`)
3. Create Pydantic schemas for pinned flows
4. Build `PinnedFlowsSection` sidebar component
5. Add pin star to flow cards in library (visible on hover, filled if pinned)
6. Add "Pin to Sidebar" / "Unpin" to flow card three-dot menu
7. Toast notifications for pin/unpin actions
### Phase D: Polish
1. Add category color column migration + backfill
2. Verify all animations and transitions
3. Responsive breakpoints (collapse sidebar on mobile)
4. E2E testing of navigation flow
5. Performance testing
---
## Appendix A: File Structure for New/Modified Components
```
frontend/src/
├── components/
│ ├── layout/
│ │ ├── AppLayout.tsx (keep — CSS Grid shell)
│ │ ├── TopBar.tsx (keep — search centered, shortcut fixed)
│ │ ├── Sidebar.tsx (MODIFY — remove workspace switcher, add pinned + sub-items)
│ │ ├── NavItem.tsx (MODIFY — add children sub-item support)
│ │ └── ProtectedRoute.tsx (keep)
│ ├── sidebar/
│ │ ├── PinnedFlowsSection.tsx ← NEW
│ │ ├── CategoryList.tsx (keep or move from workspace/)
│ │ └── TagCloud.tsx (keep or move from workspace/)
│ ├── workspace/ ← DELETE entire directory
│ ├── dashboard/
│ │ ├── QuickStats.tsx (keep)
│ │ ├── FiltersBar.tsx (keep)
│ │ └── ...
│ └── common/
│ └── ...
├── store/
│ ├── workspaceStore.ts ← DELETE
│ └── ...
├── api/
│ ├── workspaces.ts ← DELETE
│ ├── pinnedFlows.ts ← NEW
│ └── ...
├── constants/
│ ├── workspaceLabels.ts ← DELETE
│ ├── flowLabels.ts ← NEW
│ └── categoryColors.ts (keep)
└── types/
└── ... (remove Workspace type if exists)
```
## Appendix B: Typography Quick Reference
| Element | Font | Weight | Size | Tracking |
|---------|------|--------|------|----------|
| Page titles | Plus Jakarta Sans (`font-heading`) | 700 | 1.375rem (22px) | -0.01em |
| Section titles | Plus Jakarta Sans | 700 | 0.8125rem (13px) | 0.04em, uppercase |
| Nav items | Inter (`font-sans`) | 500 | 0.8125rem (13px) | normal |
| Nav sub-items | Inter (`font-sans`) | 400 | 0.8125rem (13px) | normal |
| Flow names | Plus Jakarta Sans | 600 | 0.875rem (14px) | -0.005em |
| Stat values | Plus Jakarta Sans | 700 | 1.5rem (24px) | -0.02em |
| Stat labels | Outfit (`font-label`) | 600 | 0.6875rem (11px) | 0.05em, uppercase |
| Badges/counts | Outfit | 400 | 0.6875rem (11px) | normal |
| Timestamps | Inter | 400 | 0.6875rem (11px) | normal |
| Tags/chips | Outfit | 400 | 0.625rem (10px) | normal |
| Pinned flow names | Inter | 500 | 0.8125rem (13px) | normal |
| Search input | Inter | 400 | 0.8125rem (13px) | normal |