# 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 `<button>` elements (clickable to navigate to session) with descriptive `title` attributes
