# Sidebar Redesign — Design Spec > **Date:** 2026-03-15 > **Branch:** `design/sidebar-icon-concepts` > **Status:** Approved for implementation --- ## Overview Redesign the ResolutionFlow sidebar from a flat nav list with a pinned flows section into a structured, activity-aware navigation organized around engineer workflow stages. The sidebar becomes a "shift dashboard" — showing what you're working on, how your day is going, and organizing tools by what you do with them. ## Goals 1. **Surface active work** — engineers should see their in-progress sessions and CW ticket context without navigating away 2. **Organize by workflow** — group nav items into Resolve (working tickets) / Build (authoring flows) / Insights (reviewing results) 3. **Provide daily pulse** — lightweight stats (resolved today, active, time in session) visible at a glance 4. **Clarify AI tools** — split the single "AI Assistant" into two purpose-specific tools (FlowPilot for troubleshooting, Flow Assist for authoring) 5. **Remove low-value features** — pinned/quick access flows are too static for the dynamic MSP workflow ## Full Sidebar Layout (top to bottom) ``` ┌─────────────────────────┐ │ Stats Bar │ ← 3 counters: Resolved / Active / In Session │ [7 done] [2 open] [2h] │ ├─────────────────────────┤ │ ● Activity │ ← "Activity" label with emerald clock icon │ ● O365 Mail Flow #4829 │ ← green dot = active, blue ticket # │ ● DHCP Scope #4828 │ ← amber dot = paused/idle │ · · · · · · · · · · · │ ← subtle sub-divider │ · DNS Resolution 2h │ ← muted dot + relative time │ · Printer Spooler 5h │ ├─────────────────────────┤ ← glass-border divider │ ▣ Dashboard │ ← standalone, no group label │ │ │ RESOLVE │ ← group label (JetBrains Mono, uppercase) │ ◷ Sessions [3] │ │ ⬡ All Flows [32] │ │ ◉ FlowPilot │ │ Script Library │ │ │ │ BUILD │ │ 🔧 Flow Editor │ │ ✦ Flow Assist │ │ ⊞ Step Library │ │ 💡 KB Accelerator │ │ │ │ INSIGHTS │ │ 📄 Exports │ │ 📊 Analytics │ │ │ │ ── flex spacer ── │ ← pushes footer to bottom ├─────────────────────────┤ ← glass-border divider │ 📖 User Guides │ │ 💬 Feedback │ │ ⚙ Account │ │ ◁ Collapse │ └─────────────────────────┘ ``` No brand/logo section at top (unchanged from current). Dashboard sits below the divider with no group label — it's visually separated from the activity zone by the divider and from the "Resolve" label by standard spacing (same as current "first nav item before first group" pattern). ## What Changes ### Removed - **Pinned Flows section** — the entire `PinnedFlowsSection` component, `pinnedFlowsStore`, and `pinnedFlows` API module. MSP engineers' work is too dynamic for static pinning; the activity feed replaces this. - **Single "AI Assistant" nav item** — replaced by two distinct items ### Added #### 1. Daily Stats Bar (top of sidebar) Three compact counters in a horizontal row (`display: flex; gap: 2px`), each counter is a flex-1 cell. | Stat | Color | Source | |------|-------|--------| | Resolved | `#34d399` (emerald) | Count of sessions completed today with `outcome = 'resolved'` | | Active | `#22d3ee` (cyan) | Count of sessions where `completed_at IS NULL` | | In Session | `#8891a0` (muted) | Sum of time spent in active sessions today (new metric — snapshot, acceptable to be stale) | **Dimensions:** `padding: 8px 12px 4px` on the container. Each stat cell: `padding: 6px 4px`, `border-radius: 6px`, `background: rgba(255,255,255,0.02)`. Value: `JetBrains Mono, 14px, font-weight: 600`. Label: `JetBrains Mono, 7px, uppercase, letter-spacing: 0.1em, color: #3d4350`. Stats reset daily. "In Session" is a snapshot value computed server-side — it does not live-update as a timer. #### 2. Activity Feed (below stats bar) Two sub-sections separated by a subtle divider (`1px solid rgba(255,255,255,0.03)`): **Active sessions (max 5):** - Green pulsing dot — currently active session - Amber dot (`#f59e0b`, design system amber) — paused/idle session (started but not interacted with recently) - Flow name (truncated, `13px`, `color: #e2e8f0`) - ConnectWise ticket number in blue (`#60a5fa`, `JetBrains Mono, 9px`) — only shown if the user's team has a PSA connection AND the session is linked to a ticket - If more than 5 active sessions, show a "View all in Sessions →" link styled as `text-muted-foreground, 11px, hover:text-foreground` **Green pulsing dot animation:** ```css .active-dot { width: 7px; height: 7px; border-radius: 50%; background: #34d399; box-shadow: 0 0 6px rgba(52,211,153,0.5); animation: pulse-dot 2s ease-in-out infinite; } @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); } } ``` **Recent completions:** - Small muted dot (`4px`, `#3d4350`) - Flow name in muted text (`11.5px`, `color: #6b7280`) - Relative timestamp (`JetBrains Mono, 9px`, `color: #5a6170`) - Show last 3 completed sessions from today The activity section has an "Activity" header: `JetBrains Mono, 9px, uppercase, letter-spacing: 0.12em, color: #5a6170`, with a small emerald clock SVG icon (10px). **Activity feed height:** The zone scrolls with the rest of the sidebar — no independent scroll container. The overall sidebar already has `handleSidebarWheel` for scroll forwarding. With max 5 active + 3 recent, the zone is ~280px max which is acceptable. **Refresh:** Data fetches on mount (same as current). No polling. Navigating back to a page that renders the sidebar triggers a re-mount/re-fetch. A future enhancement could add polling or WebSocket updates but that's out of scope. #### 3. Nav Grouping (Concept A3) Dashboard stands alone at the top (no group label, no special treatment — just a regular `NavItem` above the first group label). **Resolve** — what engineers do when working tickets: - Sessions (Clock, emerald `#34d399`, badge: active count) - All Flows (Network, violet `#a78bfa`, badge: total count, with type sub-items) - FlowPilot (Brain, fuchsia `#e879f9`) — NEW: in-session AI copilot - Script Library (Code2, teal `#2dd4bf`) **Build** — authoring and improving flows: - Flow Editor (Wrench, amber `#f59e0b`) - Flow Assist (WandSparkles, pink `#f472b6`) — NEW: conversational flow builder AI - Step Library (Library, orange `#fb923c`) - KB Accelerator (Lightbulb, rose `#fb7185`) **Insights** — reviewing results: - Exports (FileOutput, blue `#60a5fa`) - Analytics (BarChart3, sky `#38bdf8`) Group labels use `JetBrains Mono`, `0.5625rem`, uppercase, `letter-spacing: 0.12em`, `color: #5a6170`, `padding: 14px 12px 5px` (first group: `padding-top: 8px`). #### 4. AI Assistant Split | Nav Item | Group | Icon | Color | Purpose | Route | |----------|-------|------|-------|---------|-------| | FlowPilot | Resolve | Brain | `#e879f9` (fuchsia) | In-session AI copilot — suggests next steps, explains errors, provides ticket context during active troubleshooting | `/assistant` (existing route, rename label in UI only) | | Flow Assist | Build | WandSparkles | `#f472b6` (pink) | Conversational flow builder — standalone page with a chat interface for generating flows from natural language. Renders a full-page chat UI (similar to `AssistantChatPage`) that creates flows via the AI chat service with `flow_type` selection. NOT a modal wrapper — it's a dedicated page. | `/flow-assist` (new route + new page component `FlowAssistPage`) | Both names are already in use internally (FlowPilot in the copilot panel, Flow Assist in the editor AI panel). This just promotes them to top-level navigation. **Note:** `Wand2` is an alias for `WandSparkles` in lucide-react@0.563.0. Use `WandSparkles` as the canonical import. ### Footer (unchanged structure) - User Guides (BookOpen, lime `#a3e635`) - Feedback (MessageSquareText, indigo `#818cf8`) - Account (Settings, no color) - Collapse (PanelLeftClose, no color) ### Collapsed Sidebar When collapsed, the stats bar and activity feed are hidden. Icon-only nav items are shown in a flat list (no group labels). The collapsed view includes all 13 nav items including the two new AI items: - Dashboard (LayoutGrid, cyan) - Sessions (Clock, emerald) - All Flows (Network, violet) - FlowPilot (Brain, fuchsia) - Script Library (Code2, teal) - Flow Editor (Wrench, amber) - Flow Assist (WandSparkles, pink) - Step Library (Library, orange) - KB Accelerator (Lightbulb, rose) - Exports (FileOutput, blue) - Analytics (BarChart3, sky) - User Guides (BookOpen, lime) - Feedback (MessageSquareText, indigo) Account and Collapse remain in the footer section of the collapsed view (same as current). ## Data Requirements ### New Backend Endpoint **`GET /api/v1/sessions/sidebar-stats`** — lightweight endpoint for sidebar data, returns: ```json { "resolved_today": 7, "active_count": 2, "total_session_minutes_today": 134, "active_sessions": [ { "session_id": "uuid", "tree_name": "O365 Mail Flow", "tree_id": "uuid", "tree_type": "troubleshooting", "started_at": "2026-03-15T14:30:00Z", "ticket_number": "#48291" } ], "recent_completions": [ { "session_id": "uuid", "tree_name": "DNS Resolution", "tree_id": "uuid", "tree_type": "troubleshooting", "completed_at": "2026-03-15T12:15:00Z" } ] } ``` **Query parameters:** - `tz_offset` (integer, required): Client's UTC offset in minutes (e.g., `-300` for EST). Used to compute "today" boundaries. Frontend sends `new Date().getTimezoneOffset()`. **Backend logic:** - `resolved_today`: `SELECT COUNT(*) FROM sessions WHERE user_id = :uid AND completed_at >= :today_start AND outcome = 'resolved'` - `active_count`: `SELECT COUNT(*) FROM sessions WHERE user_id = :uid AND completed_at IS NULL` - `total_session_minutes_today`: Sum of `EXTRACT(EPOCH FROM (COALESCE(completed_at, now()) - started_at)) / 60` for all sessions where `started_at >= :today_start` - `active_sessions`: Up to 5, ordered by `started_at DESC`, with joined tree name/type - `recent_completions`: Up to 3 completed today, ordered by `completed_at DESC` - `ticket_number`: Populated from PSA connection context if available (depends on CW integration state — nullable) - `today_start`: Computed as midnight in the client's timezone, converted to UTC using `tz_offset` **Sessions spanning midnight:** A session started yesterday that is still active today counts toward `total_session_minutes_today` for its full duration (from `started_at`, not from midnight). It also appears in `active_sessions`. This matches user intuition — "I've been on this for 3 hours" regardless of when midnight fell. ### Frontend Components **New components:** - `SidebarStatsBar` — three-stat row component - `SidebarActivityFeed` — active sessions + recents feed with "Activity" header - `ActivityItem` — single activity row (dot + name + ticket/timestamp) - `FlowAssistPage` — standalone page for conversational flow building **Modified components:** - `Sidebar.tsx` — major restructure: remove PinnedFlowsSection, add stats bar + activity feed, reorganize nav into groups with labels, add FlowPilot + Flow Assist items, update collapsed view icon set - `router.tsx` — add `/flow-assist` route - `NavItem.tsx` — no changes needed (already supports `iconColor` prop) **Removed:** - `PinnedFlowsSection.tsx` - `pinnedFlowsStore.ts` - `api/pinnedFlows.ts` (if it exists) - Related pinning UI in flow cards/pages (pin buttons, pin actions) ## Visual Reference Mockups created during brainstorming are in `.superpowers/brainstorm/` (HTML files, open in browser). The approved composite is `a3-full-sidebar.html` showing the "With AI Split" variant. ## Out of Scope - ConnectWise ticket deep-linking (future — just display the number for now) - Team activity feed (showing what other engineers are doing — potential future enhancement) - Removing the pinned flows backend API/database tables (just remove frontend usage; backend cleanup is separate) - Changes to the analytics pages themselves - Mobile/responsive sidebar behavior (current behavior unchanged) - Polling/WebSocket for live activity updates (fetch on mount only) ## Edge Cases - **No active sessions:** Stats bar shows "0" for Active and "0m" for In Session. Activity section shows only recents (or "No activity today" placeholder if no recents either). - **No CW integration:** Ticket numbers simply don't appear. Activity items show flow name only. - **Many active sessions:** Activity feed caps at 5 active sessions with a "View all in Sessions →" link below. - **Midnight rollover:** Stats reset based on client timezone offset passed to the API. Frontend sends `tz_offset` on each sidebar fetch. - **Sessions spanning midnight:** Count full duration from `started_at`, not partial duration from midnight. - **New user / no sessions ever:** Stats bar shows all zeros. Activity section shows an empty state: "No activity today". ## Accessibility - Pulsing green dot: add `aria-label="Active session"` to the dot element - Amber dot: `aria-label="Paused session"` - Stats bar values: wrap in elements with `aria-label` combining value + label (e.g., "7 resolved today") - Activity items: render as `