# Investibook Frontend — Flexible Sources/Studio Panels (Fold + Splitter)

Date: 2026-03-12

## Summary

Make the **Sources (left)** and **Studio (right)** panels on the Investibook workspace page:

1) **Resizable** via drag splitters (gutters) between columns, and  
2) **Collapsible/expandable** via icon buttons in each panel header.

This applies to **desktop layout only**. Mobile remains tab-based (Sources/Chat/Studio).

## Goals

- Let users allocate space between Sources / Chat / Studio quickly.
- Provide one-click “focus” modes by collapsing side panels.
- Keep UI clean: **no icons** on splitters; show drag affordance only on hover.
- Persist layout (widths + collapsed state) locally per browser.

## Non-goals

- No change to mobile navigation/layout behavior.
- No server-side persistence (no DB schema/API changes).
- No new global layout system; this is scoped to the workspace three-column view.

## Current State (Desktop)

- Sources has fixed width (`280px`).
- Chat uses remaining space (`flex: 1`).
- Studio uses remaining space (`flex: 1`).
- No resizing and no folding controls.

## UX / Behavior

### Columns

- Sources | Chat | Studio (three columns).
- Two gutters:
  - Left gutter adjusts **Sources width**.
  - Right gutter adjusts **Studio width**.

### Resizing (Splitters)

- Gutter hit area: ~`8–10px` wide.
- Visuals:
  - Default: gutter is visually “quiet” (no handle icon).
  - Hover: show subtle highlight + `col-resize` cursor.
  - Drag: highlight remains visible during drag.
- Constraints:
  - Sources min expanded width: `240px`.
  - Studio min expanded width: `360px`.
  - Chat min width: `420px`.
  - Collapsed width is handled separately (see below).

### Folding (Collapse/Expand)

- Sources panel header contains a **collapse-left** icon (e.g. chevron pointing toward the edge).
- Studio panel header contains a **collapse-right** icon.
- Clicking collapses the panel to a **minimum collapsed width** (not zero).

### Collapsed State

- Collapsed width: `64px`.
- The panel keeps a minimal header row and shows an **expand** icon in the header so users can restore it
  (Sources: expand-right; Studio: expand-left).
- When collapsed:
  - The panel content area can be hidden or replaced by a minimal placeholder (implementation choice), but the header remains visible.
  - The last **expanded** width is preserved, so expanding returns the panel to its previous expanded width (clamped if needed).

### Defaults

- Default Sources width: `280px` (matches current).
- Default Studio width: `420px` (new explicit default).
- Both uncollapsed by default.

### Persistence

Persist locally using `localStorage` (per browser):

- Sources width (expanded width)
- Studio width (expanded width)
- Sources collapsed flag
- Studio collapsed flag

If persisted values are invalid (NaN/out of range), fall back to defaults.

Recommended keying:

- Key prefix: `investibook.workspace.layout.desktop.v1`
- Include `workspaceId` to avoid cross-workspace coupling unless explicitly desired:
  - Example key: `investibook.workspace.layout.desktop.v1:${workspaceId}`

## Accessibility

- Collapse/expand buttons use proper `aria-label` (e.g., “Collapse Sources”, “Expand Studio”).
- Gutters:
  - Cursor change on hover (`col-resize`) and highlight for discoverability.
  - (Optional future) keyboard resizing is out of scope for this iteration.

## Implementation Sketch (Frontend)

### Where

- Desktop layout lives in `platform/investibook/frontend/app/workspace/[id]/page.tsx`.

### How (High-level)

- Replace fixed-width wrappers with a small “layout controller” that:
  - Tracks `sourcesWidth`, `studioWidth`, `sourcesCollapsed`, `studioCollapsed`.
  - Adds two draggable gutter components.
  - Applies inline styles to left/right column containers based on state.
  - Writes/reads layout state from `localStorage`.

### Panel Header Buttons

- Prefer using existing UI primitives (`ActionIcon`, `Tooltip`) from `@tidbcloud/uikit`.
- Add a small optional prop to `SourcesPanel` / `StudioPanel` to render header actions (or wrap them externally in the workspace page).
  - Keep changes minimal and consistent with existing inline styling convention.

## Edge Cases

- If both side panels are expanded to widths that violate the chat minimum width, clamp the last-adjusted side to satisfy chat min width.
- If both panels are collapsed, chat becomes the main area (still clamped by viewport).
- On very small desktop widths, clamping may force one panel to its collapsed width even if “expanded”; in that case keep state but render clamped width.

## Testing / Verification

- Manual verification (local dev):
  - Drag left gutter: Sources width changes; chat reacts; no jitter.
  - Drag right gutter: Studio width changes; chat reacts.
  - Collapse/expand each panel; collapsed width is `64px`.
  - Refresh page: persisted widths/collapsed state restored.
  - Mobile viewport: tab-based UI remains unchanged.

- Lightweight unit tests are optional; if tests exist for layout helpers, add coverage for clamp/persist logic.
