859 lines
29 KiB
Markdown
859 lines
29 KiB
Markdown
# ResolutionFlow UI Design System & Layout Architecture
|
|
|
|
> **Purpose:** This document defines the new app-shell layout, design tokens, component patterns, and workspace 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
|
|
> **Reference Mockup:** `docs/mockups/resolutionflow-workspaces-mockup.html` (interactive, open in browser)
|
|
> **Note:** If the mockup file is not yet in the repo, it should be placed at the path above. The mockup is also available as a project output artifact.
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
1. [Layout Architecture](#1-layout-architecture)
|
|
2. [Design Tokens](#2-design-tokens)
|
|
3. [Workspace System](#3-workspace-system)
|
|
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. [Data Model Changes](#10-data-model-changes)
|
|
11. [Migration Strategy](#11-migration-strategy)
|
|
12. [Implementation Phases](#12-implementation-phases)
|
|
|
|
---
|
|
|
|
## 1. Layout Architecture
|
|
|
|
### Overview
|
|
|
|
ResolutionFlow transitions from a top-nav + full-width content layout to a **persistent sidebar + top bar + main workspace** layout. This mirrors the UX patterns MSP engineers already use in ConnectWise Automate, Datto RMM, and HaloPSA.
|
|
|
|
### Shell Structure
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ TOP BAR (56px) — Logo, Search, Quick Actions, User │
|
|
├──────────────┬───────────────────────────────────────┤
|
|
│ SIDEBAR │ MAIN CONTENT AREA │
|
|
│ (260px) │ │
|
|
│ │ Page Header + Actions │
|
|
│ Workspace │ Quick Stats Row │
|
|
│ Switcher │ Filters Bar │
|
|
│ │ Content Sections │
|
|
│ Navigation │ (trees/flows list, sessions, etc.) │
|
|
│ │ │
|
|
│ Categories │ │
|
|
│ Tags │ │
|
|
│ │ │
|
|
│ ─────────── │ │
|
|
│ Team │ │
|
|
│ Settings │ │
|
|
└──────────────┴───────────────────────────────────────┘
|
|
```
|
|
|
|
### CSS Grid Implementation
|
|
|
|
```tsx
|
|
// AppLayout.tsx - new shell structure
|
|
<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;
|
|
}
|
|
```
|
|
|
|
This variable should be used consistently for sidebar width, logo area width calculations, and responsive breakpoints.
|
|
|
|
---
|
|
|
|
## 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.) with both light and dark mode values. Continue using these for shadcn components.
|
|
|
|
### NEW Design Tokens for App Shell
|
|
|
|
These are already added to `index.css` within the `:root` block (the app is dark-only, all tokens live in `:root`):
|
|
|
|
```css
|
|
:root {
|
|
/* Existing tokens... */
|
|
|
|
/* App Shell tokens */
|
|
--sidebar-bg: 240 10% 4.5%; /* #0c0c0f - slightly lighter than app bg */
|
|
--sidebar-hover: 240 6% 12%; /* #1e1e23 */
|
|
--sidebar-active: 243 75% 59% / 0.08; /* brand purple at 8% opacity */
|
|
--border-subtle: 240 6% 12%; /* #1f1f23 - lighter border for sections */
|
|
--text-dimmed: 240 4% 24%; /* #3f3f46 - very dim text for timestamps */
|
|
}
|
|
```
|
|
|
|
### Semantic Status Colors
|
|
|
|
These map to session/tree status indicators and MUST be used consistently:
|
|
|
|
| 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
|
|
|
|
Categories use a fixed palette of distinguishable colors for their dot indicators:
|
|
|
|
```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;
|
|
```
|
|
|
|
Categories are assigned colors based on their creation order (index % length). Colors are stored on the category model in the database.
|
|
|
|
> **Migration needed:** The `tree_categories` table already has `display_order` and `is_active` columns. Add a `color` column:
|
|
> ```sql
|
|
> ALTER TABLE tree_categories ADD COLUMN color VARCHAR(7) DEFAULT '#3b82f6';
|
|
> ```
|
|
> Backfill existing categories with colors from the palette based on their `display_order`.
|
|
|
|
---
|
|
|
|
## 3. Workspace System
|
|
|
|
### Concept
|
|
|
|
Workspaces are the top-level organizational context. They sit **above** the existing folder system — a workspace scopes which trees/flows are visible, while user folders remain available within each workspace for personal organization. When a user switches workspace, the sidebar categories, tags, stats, filters, and main content all adapt.
|
|
|
|
> **Important:** Workspaces do NOT replace the existing `UserFolder` system. Folders are per-user personal organization that continue to work within the active workspace context. The folder sidebar, drag-and-drop, and folder-tree junction table are preserved. Workspaces filter what content is available; folders organize it.
|
|
|
|
The layout, navigation structure, and component patterns stay identical — only the DATA changes.
|
|
|
|
### Workspace Types (Initial Set)
|
|
|
|
| Workspace | Description | Icon | Accent Color |
|
|
|-----------|-------------|------|-------------|
|
|
| Troubleshooting | Break/fix decision trees | 🔧 | `#ef4444` (red) |
|
|
| Procedures | Step-by-step operational flows | 📋 | `#3b82f6` (blue) |
|
|
| Policies | Compliance & policy builders | 📜 | `#8b5cf6` (violet) |
|
|
| Finance | Billing & procurement flows | 💰 | `#22c55e` (green) |
|
|
|
|
**Users and admins can create custom workspaces.** The four above are defaults.
|
|
|
|
### Workspace Switcher Component
|
|
|
|
Located at the top of the sidebar, below the nav section label. It's a dropdown that shows:
|
|
|
|
1. **Current workspace** — icon, name, description, chevron
|
|
2. **Dropdown options** — all available workspaces with flow counts
|
|
3. **"Add workspace…"** — link at bottom to create new
|
|
|
|
```
|
|
┌─────────────────────────────┐
|
|
│ 🔧 Troubleshooting │
|
|
│ Break/fix decision trees │
|
|
│ ▼ │
|
|
├─────────────────────────────┤
|
|
│ 🔧 Troubleshooting 42 │ ← active (highlighted)
|
|
│ 📋 Procedures 18 │
|
|
│ 📜 Policies 7 │
|
|
│ 💰 Finance 4 │
|
|
│─────────────────────────────│
|
|
│ + Add workspace… │
|
|
└─────────────────────────────┘
|
|
```
|
|
|
|
### Behavior on Workspace Switch
|
|
|
|
When the user selects a new workspace:
|
|
|
|
1. Sidebar content fades out (200ms opacity transition)
|
|
2. Data updates:
|
|
- Categories list → filtered to workspace
|
|
- Tags cloud → filtered to workspace
|
|
- Nav badge counts → reflect workspace totals
|
|
- "All Trees" label → changes (e.g., "All Procedures")
|
|
- "Tree Editor" label → changes (e.g., "Flow Editor")
|
|
- Search placeholder → adapts
|
|
3. Main content fades out/in (200ms opacity transition)
|
|
- Page title changes
|
|
- Stats row updates
|
|
- Filter chips update
|
|
- Tree/flow list filters to workspace
|
|
- Sessions panel filters to workspace
|
|
4. "New Tree" button label → adapts (e.g., "New Procedure")
|
|
5. Toast notification confirms switch: "Switched to **Procedures**"
|
|
|
|
### Data Model
|
|
|
|
See [Section 10: Data Model Changes](#10-data-model-changes) for backend schema.
|
|
|
|
---
|
|
|
|
## 4. Sidebar Components
|
|
|
|
### Structure (top to bottom)
|
|
|
|
```
|
|
1. Workspace Switcher (dropdown)
|
|
2. ─── divider ───
|
|
3. Primary Navigation
|
|
- Dashboard (grid icon)
|
|
- All Trees/Flows (cube icon) [badge: count]
|
|
- Tree/Flow Editor (pencil icon)
|
|
- Sessions (clock icon) [badge: active count]
|
|
- Exports (file 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 (gear icon)
|
|
```
|
|
|
|
### Nav Item Component
|
|
|
|
```tsx
|
|
interface NavItemProps {
|
|
href: string;
|
|
icon: LucideIcon;
|
|
label: string;
|
|
badge?: number | 'dot';
|
|
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 in dark mode)
|
|
- Icon: full opacity
|
|
|
|
**Inactive state styling:**
|
|
- Background: transparent
|
|
- Text: `text-muted-foreground`
|
|
- Icon: 70% opacity
|
|
- Hover: `var(--sidebar-hover)` background
|
|
|
|
### 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` (Outfit font)
|
|
- Hover: `var(--sidebar-hover)` background, text brightens
|
|
|
|
### Tag Cloud Component
|
|
|
|
```tsx
|
|
interface TagCloudProps {
|
|
tags: string[];
|
|
onTagClick: (tag: string) => void;
|
|
activeTags?: string[];
|
|
}
|
|
```
|
|
|
|
Renders as flex-wrap container of small chip elements:
|
|
- 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] | [Search Input (⌘K)] | ──flex grow── | [Quick Launch] [Notifications] [Avatar]
|
|
```
|
|
|
|
### Logo Area
|
|
|
|
- Width: `calc(var(--sidebar-w) - 40px)` — aligns with sidebar content
|
|
- Contains: ResolutionFlow logo SVG (32x32) + branded wordmark
|
|
- Wordmark: "Resolution" in white + "Flow" in gradient text
|
|
|
|
### Search Bar
|
|
|
|
- Flex: 1, max-width 480px
|
|
- Placeholder adapts to workspace context (e.g., "Search trees, sessions, tags…")
|
|
- Left icon: magnifying glass (Lucide `Search`)
|
|
- Right badge: keyboard shortcut hint `⌘K` (styled as small pill)
|
|
- Border: `border-border`, focus: `border-brand-gradient-from`
|
|
|
|
### 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
|
|
|
|
Every page in the main content follows this vertical flow:
|
|
|
|
```
|
|
1. Page Header (title + action buttons)
|
|
2. Quick Stats Row (4 cards)
|
|
3. Filters Bar (chips)
|
|
4. Content Sections (grouped lists, panels)
|
|
```
|
|
|
|
Not every page needs all sections. The Dashboard uses all four. The Tree Editor page would only use the page header and then the editor workspace.
|
|
|
|
### 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` (10px)
|
|
- 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)]`
|
|
|
|
Special value styles:
|
|
- `.gradient` → `text-gradient-brand`
|
|
- Colored → direct color style (e.g., amber for warnings)
|
|
|
|
### Filters Bar
|
|
|
|
Horizontal row of filter chips with a divider before "More Filters":
|
|
|
|
```
|
|
[All*] [Recently Used] [My Trees] [Team Trees] [Defaults] | [⊗ More Filters]
|
|
```
|
|
|
|
Active chip: purple-tinted background/border (same as sidebar tag active state).
|
|
|
|
### Section Groups
|
|
|
|
Collapsible sections with header:
|
|
|
|
```
|
|
[●] SECTION TITLE 5 [▼]
|
|
─────────────────────────────
|
|
```
|
|
|
|
- Dot: 8px gradient circle
|
|
- Title: `font-heading text-[0.8125rem] font-bold uppercase tracking-wide`
|
|
- Count: pill with `bg-surface` background
|
|
- Collapse: chevron button (toggles section visibility)
|
|
|
|
### Tree/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
|
|
|
|
**Icon box:** 36x36px rounded-lg with category-tinted background and emoji.
|
|
|
|
**Info column:**
|
|
- Name: `font-heading text-sm font-semibold`
|
|
- Meta row: tags (small chips) + step/solution count
|
|
|
|
**Category column:** color dot + name in `font-label text-xs`
|
|
|
|
**Actions:** Three-dot menu, opacity 0 until row hover.
|
|
|
|
### 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 │
|
|
└──────────────────────────────────────┘
|
|
```
|
|
|
|
Session row grid:
|
|
```
|
|
grid-template-columns: 8px 1fr 140px 80px 100px
|
|
dot name progress ticket time
|
|
```
|
|
|
|
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 (creates "cut out" effect)
|
|
|
|
### Toast Notifications
|
|
|
|
Fixed-position toast notification (current app uses top-right via Sonner — keep this position for consistency):
|
|
- Background: `bg-card`
|
|
- Border: brand gradient border
|
|
- Border radius: `rounded-xl`
|
|
- Shadow: `shadow-xl` with heavy dark shadow
|
|
- Content: emoji icon + message text (supports `<strong>` for emphasis)
|
|
- Auto-dismiss: 2000ms with fade out
|
|
|
|
---
|
|
|
|
## 8. Icon System
|
|
|
|
### Primary Source: Lucide React
|
|
|
|
All icons use [Lucide React](https://lucide.dev) at consistent sizes:
|
|
|
|
| Context | Size | Lucide Prop |
|
|
|---------|------|-------------|
|
|
| Nav items | 18px | `size={18}` |
|
|
| Buttons | 16px | `size={16}` |
|
|
| Top bar actions | 18px | `size={18}` |
|
|
| Section headers | 14px | `size={14}` |
|
|
| Filter chips | 14px | `size={14}` |
|
|
|
|
### Navigation Icon Mapping
|
|
|
|
| Nav Item | Lucide Icon |
|
|
|----------|-------------|
|
|
| Dashboard | `LayoutGrid` |
|
|
| All Trees/Flows | `Box` |
|
|
| Tree/Flow Editor | `PenLine` |
|
|
| Sessions | `Clock` |
|
|
| Exports | `FileText` |
|
|
| Step Library | `Bookmark` |
|
|
| Team | `Users` |
|
|
| Settings | `Settings` |
|
|
| Search | `Search` |
|
|
| Quick Launch | `Zap` |
|
|
| Notifications | `Bell` |
|
|
| New Tree | `Plus` |
|
|
| Import | `Upload` |
|
|
| Filter | `Filter` |
|
|
| Collapse | `ChevronDown` |
|
|
| More Actions | `MoreHorizontal` |
|
|
|
|
### Category Emoji Icons
|
|
|
|
Categories in the tree list use emoji as visual anchors inside tinted icon boxes. These are set per-tree or per-category and stored as a string field.
|
|
|
|
Default emoji per common categories:
|
|
- Networking: 🌐
|
|
- Active Directory: 🔒
|
|
- Email/Exchange: 📧
|
|
- Server Issues: 🖥️
|
|
- VPN/Remote: 🔌
|
|
- Citrix/RDS: 🖥️
|
|
- Printers: 🖨️
|
|
- Backup/DR: 🔄
|
|
- Onboarding: 👤
|
|
- Security: 🔐
|
|
|
|
---
|
|
|
|
## 9. Animation & Transitions
|
|
|
|
### Page/Section Load
|
|
|
|
Staggered fade-in using CSS animation:
|
|
|
|
```css
|
|
.fade-in {
|
|
animation: fadeIn 0.3s ease forwards;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; transform: translateY(6px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
```
|
|
|
|
Apply with incrementing `animation-delay` on child sections:
|
|
- Stats row: 50ms
|
|
- Filters: 100ms
|
|
- Section 1: 150ms
|
|
- Section 2: 200ms
|
|
|
|
### Workspace Switch
|
|
|
|
Coordinated fade transition:
|
|
1. Sidebar content: `opacity → 0` (200ms)
|
|
2. Main content: `opacity → 0` (200ms)
|
|
3. Data swap (instant)
|
|
4. Both: `opacity → 1` (200ms)
|
|
|
|
### Interactive Elements
|
|
|
|
| Element | Property | Duration | Easing |
|
|
|---------|----------|----------|--------|
|
|
| Nav item hover | background-color | 120ms | ease |
|
|
| Button hover | transform, box-shadow | 150ms | ease |
|
|
| Tree 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 |
|
|
|
|
### Workspace Dropdown
|
|
|
|
```css
|
|
@keyframes dropIn {
|
|
from { opacity: 0; transform: translateY(-4px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 10. Data Model Changes
|
|
|
|
### New: `workspaces` Table
|
|
|
|
```sql
|
|
CREATE TABLE workspaces (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name VARCHAR(100) NOT NULL,
|
|
slug VARCHAR(100) NOT NULL UNIQUE,
|
|
description TEXT,
|
|
icon VARCHAR(10), -- emoji character
|
|
accent_color VARCHAR(7), -- hex color (e.g., '#ef4444')
|
|
account_id UUID REFERENCES accounts(id) ON DELETE CASCADE,
|
|
is_default BOOLEAN DEFAULT FALSE,
|
|
sort_order INTEGER DEFAULT 0,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
```
|
|
|
|
**Default workspaces (seeded):**
|
|
|
|
| name | slug | icon | accent_color | is_default |
|
|
|------|------|------|-------------|------------|
|
|
| Troubleshooting | troubleshooting | 🔧 | #ef4444 | true |
|
|
| Procedures | procedures | 📋 | #3b82f6 | false |
|
|
| Policies | policies | 📜 | #8b5cf6 | false |
|
|
| Finance | finance | 💰 | #22c55e | false |
|
|
|
|
### Modified: `trees` Table
|
|
|
|
Add column:
|
|
|
|
```sql
|
|
ALTER TABLE trees ADD COLUMN workspace_id UUID REFERENCES workspaces(id);
|
|
```
|
|
|
|
All existing trees get assigned to the "troubleshooting" workspace via data migration.
|
|
|
|
> **Note:** The `trees` table already has a `tree_type` column with values `'troubleshooting'` and `'procedural'`. The workspace system is a superset of this — `tree_type` controls tree behavior (branching vs linear), while `workspace_id` controls organizational context. Both fields coexist. The data migration should map existing `tree_type='troubleshooting'` trees to the Troubleshooting workspace and `tree_type='procedural'` trees to the Procedures workspace.
|
|
|
|
### Modified: `tree_categories` Table
|
|
|
|
Add column:
|
|
|
|
```sql
|
|
ALTER TABLE tree_categories ADD COLUMN workspace_id UUID REFERENCES workspaces(id);
|
|
```
|
|
|
|
Categories become workspace-scoped. A category belongs to one workspace. The existing `account_id` column remains for tenancy — `workspace_id` is an additional organizational dimension within an account.
|
|
|
|
### Modified: `tree_tags` Table
|
|
|
|
Tags remain global (cross-workspace) but the popular tags query filters by workspace context. The existing `account_id` scoping on tags is preserved.
|
|
|
|
### API Changes
|
|
|
|
**New endpoints:**
|
|
|
|
```
|
|
GET /api/v1/workspaces -- list all workspaces for user's account
|
|
POST /api/v1/workspaces -- create workspace (admin)
|
|
PATCH /api/v1/workspaces/{id} -- update workspace
|
|
DELETE /api/v1/workspaces/{id} -- soft delete workspace
|
|
```
|
|
|
|
**Modified endpoints:**
|
|
|
|
```
|
|
GET /api/v1/trees?workspace_id={uuid} -- add workspace filter
|
|
GET /api/v1/categories?workspace_id={uuid} -- categories are a separate router (categories.py)
|
|
GET /api/v1/sessions?workspace_id={uuid}
|
|
```
|
|
|
|
> **Note:** Categories have their own dedicated router at `/api/v1/categories` (not nested under `/trees/categories`). Tags are at `/api/v1/tags`. Folders are at `/api/v1/folders`. See `backend/app/api/router.py` for the full route registry.
|
|
|
|
### Frontend State
|
|
|
|
```typescript
|
|
// store/workspaceStore.ts
|
|
interface WorkspaceState {
|
|
workspaces: Workspace[];
|
|
activeWorkspaceId: string | null;
|
|
setActiveWorkspace: (id: string) => void;
|
|
// Persisted in localStorage as 'active-workspace-id'
|
|
}
|
|
```
|
|
|
|
All tree/session/category queries include the active workspace ID as a filter parameter.
|
|
|
|
---
|
|
|
|
## 11. Migration Strategy
|
|
|
|
### From Current Layout to App Shell
|
|
|
|
The current `AppLayout.tsx` uses a top-nav bar with horizontal nav links and an `<Outlet>` for full-width page content. The migration:
|
|
|
|
1. **AppLayout.tsx** → Complete rewrite to CSS Grid shell (topbar + sidebar + main)
|
|
2. **BrandLogo + BrandWordmark** → Move into topbar logo area
|
|
3. **Nav links** → Move into sidebar as vertical nav items with icons
|
|
4. **ThemeToggle** → Move into sidebar footer or top bar
|
|
5. **User menu** → Avatar in top bar with dropdown
|
|
6. **Outlet** → Renders inside `<main>` grid cell
|
|
|
|
### Page-by-Page Adaptation
|
|
|
|
| Page | Changes Needed |
|
|
|------|---------------|
|
|
| TreeLibraryPage | Becomes the "Dashboard" or "All Trees" view in main content area. Add stats row, filters, and grouped list layout |
|
|
| TreeNavigationPage | Renders in main content. Scratchpad overlay unchanged (fixed position) |
|
|
| TreeEditorPage | Renders in main content. Full-width editor workspace |
|
|
| SessionHistoryPage | Renders in main content. Add filters and session list |
|
|
| SessionDetailPage | Renders in main content. Minimal changes |
|
|
| SettingsPage | Renders in main content. Minimal changes |
|
|
| LoginPage / RegisterPage | **No change** — these render outside the app shell (no sidebar) |
|
|
|
|
---
|
|
|
|
## 12. Implementation Phases
|
|
|
|
### Phase A: Foundation (Backend + Shell)
|
|
|
|
1. Create `workspace` table, model, schemas, migration
|
|
2. Add `workspace_id` to `tree` and `tree_category` tables
|
|
3. Seed default workspaces
|
|
4. Data migration: assign all existing trees to "troubleshooting" workspace
|
|
5. Create workspace API endpoints
|
|
6. Create `workspaceStore` (Zustand + localStorage)
|
|
7. **Rewrite `AppLayout.tsx`** to CSS Grid shell with topbar + sidebar + main
|
|
8. Move existing nav items into sidebar
|
|
9. Add workspace switcher component (static, no data yet)
|
|
|
|
### Phase B: Sidebar Components
|
|
|
|
1. Build `NavItem` component with active state + badge
|
|
2. Build `CategoryList` component with color dots
|
|
3. Build `TagCloud` component
|
|
4. Build `WorkspaceSwitcher` dropdown with animations
|
|
5. Wire workspace switcher to `workspaceStore`
|
|
6. Update tree/session queries to include workspace filter
|
|
|
|
### Phase C: Main Content Redesign
|
|
|
|
1. Build `QuickStats` row component
|
|
2. Build `FiltersBar` component
|
|
3. Build `SectionGroup` collapsible component
|
|
4. Build `TreeListItem` component (grid layout)
|
|
5. Build `SessionsPanel` component
|
|
6. Redesign `TreeLibraryPage` as Dashboard using new components
|
|
7. Add search bar with ⌘K shortcut
|
|
|
|
### Phase D: Polish & Integration
|
|
|
|
1. Add workspace switch animations (fade transitions)
|
|
2. Add toast notifications for workspace switch
|
|
3. Responsive breakpoints (collapse sidebar on mobile)
|
|
4. Update all page components to work within new shell
|
|
5. E2E testing of workspace switching flow
|
|
6. Performance testing (workspace switch should be <200ms)
|
|
|
|
---
|
|
|
|
## Appendix A: File Structure for New Components
|
|
|
|
```
|
|
frontend/src/
|
|
├── components/
|
|
│ ├── layout/
|
|
│ │ ├── AppLayout.tsx ← REWRITE (CSS Grid shell)
|
|
│ │ ├── TopBar.tsx ← NEW
|
|
│ │ ├── Sidebar.tsx ← NEW
|
|
│ │ ├── NavItem.tsx ← NEW
|
|
│ │ └── ProtectedRoute.tsx (unchanged)
|
|
│ ├── workspace/
|
|
│ │ ├── WorkspaceSwitcher.tsx ← NEW
|
|
│ │ ├── CategoryList.tsx ← NEW
|
|
│ │ └── TagCloud.tsx ← NEW
|
|
│ ├── dashboard/
|
|
│ │ ├── QuickStats.tsx ← NEW
|
|
│ │ ├── FiltersBar.tsx ← NEW
|
|
│ │ ├── SectionGroup.tsx ← NEW
|
|
│ │ ├── TreeListItem.tsx ← NEW
|
|
│ │ └── SessionsPanel.tsx ← NEW
|
|
│ └── common/
|
|
│ ├── Toast.tsx ← NEW
|
|
│ └── ... (existing)
|
|
├── store/
|
|
│ ├── workspaceStore.ts ← NEW
|
|
│ └── ... (existing)
|
|
├── api/
|
|
│ ├── workspaces.ts ← NEW
|
|
│ └── ... (existing)
|
|
├── types/
|
|
│ ├── workspace.ts ← NEW
|
|
│ └── ... (existing)
|
|
└── constants/
|
|
└── categoryColors.ts ← NEW
|
|
```
|
|
|
|
## 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 |
|
|
| Tree 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 |
|
|
| Search input | Inter | 400 | 0.8125rem (13px) | normal |
|
|
|
|
## Appendix C: Workspace-Specific Adaptations
|
|
|
|
When a workspace is active, these elements adapt:
|
|
|
|
| Element | Troubleshooting | Procedures | Policies | Finance |
|
|
|---------|----------------|------------|----------|---------|
|
|
| "All ___" nav label | All Trees | All Procedures | All Policies | All Finance Flows |
|
|
| Editor nav label | Tree Editor | Flow Editor | Policy Editor | Flow Editor |
|
|
| New button label | New Tree | New Procedure | New Policy | New Flow |
|
|
| Search placeholder | Search trees, sessions, tags… | Search procedures, runbooks… | Search policies, compliance… | Search billing, procurement… |
|
|
| Stat 1 label | Active Trees | Active Procedures | Active Policies | Active Flows |
|
|
| Stat 2 label | Sessions Today | Runs This Week | Pending Review | Runs This Month |
|
|
| Stat 3 label | Open Sessions | In Progress | Compliance Score | Cost Saved |
|
|
| Stat 4 label | Docs Generated | Avg Completion | Last Audit | Pending Approvals |
|