refactor(desktop): cleaner, compact inline agent/port sections in v2 sidebar

Merged
KI
4mo ago
+306-143

Summary

  • Restyles the inline agent and port pills under workspace rows (and the bottom Ports section) as compact, neutral Linear/Notion-style tags, replacing the tinted bg-primary chips.
  • Splits ports and agents into separate collapsible sections with independently persisted collapse state, instead of one merged "2 ports · 1 agent" toggle.
  • Adds adaptive chip layout: one row while chips fit, a two-row grid on overflow, then horizontal scroll two rows deep.
  • Reworks port pill interactions: click opens the port in the browser; a hover-revealed ⋮ menu holds Open in External Browser / Open in Superset Browser / Go to Workspace / Close Port.

Why / Context

The inline agent/port UI read as loud colored CTAs, pills were oversized with phantom trailing space (invisible hover icons reserved ~28px each), rows misaligned with the section toggle, and hover made pills grow and push their neighbors.

How It Works

  • Pills (DashboardSidebarPortBadge, DashboardSidebarWorkspaceAgentBadge): bg-muted/60 neutral tags at text-[11px] with mono tabular port numbers; status color is reserved for the agent status dot.
  • Sections (DashboardSidebarWorkspaceDetails): each detail section renders its own toggle row; useWorkspaceDetailsStore now keys collapse state by ${workspaceId}:${sectionKey} (previously per-workspace); a persist migration (v0 → v1) expands each old per-workspace collapsed flag into both section keys.
  • Layout (new DashboardSidebarChipStrip): measures chips' natural widths against the container (every render + ResizeObserver) and toggles between a flex row and a grid-rows-2 column-flow grid, wrapped in OverflowFadeContainer for the scroll fade. Pure-CSS child growth intentionally doesn't re-measure, so hover can't flip the layout.
  • Port actions: the ⋮ trigger is always rendered and hidden via opacity, so pill geometry never changes on hover. Kill-pending swaps ⋮ for a spinner and dims the pill.
  • Section chevrons are hidden until hover (opacity, slot reserved); chip rows are left-aligned with the section summary label.

Manual QA Checklist

  • Ports and agents show as separate "N ports" / "N agents" sections under a workspace row
  • Collapsing one section leaves the other open; state persists after app restart
  • Chips: single row when few, two rows when overflowing, horizontal scroll (with right fade) beyond that; resizing the sidebar reflows correctly
  • Hovering a port pill reveals ⋮ without any pill/neighbor movement
  • Click on a local port opens per Settings → Links → Ports preference; remote port click jumps to the workspace
  • ⋮ menu: Open in External Browser + Open in Superset Browser (local only), Go to Workspace, Close Port (destructive); Close shows spinner while pending
  • Collapse state from a pre-PR build carries over (v0 → v1 store migration)
  • "Close all ports" hover action still works on the ports section header
  • Agent pill click focuses the bound terminal; status dot shows working/permission/review
  • Bottom "Ports" list groups behave the same (adaptive rows, new pill styling)

Testing

  • bun run typecheck
  • bunx biome check . (root bun run lint additionally shells out to ripgrep, which isn't installed on this machine; Biome itself is clean)
  • Manual testing in dev mode

Design Decisions

  • ⋮ menu instead of inline hover icons: inline icons either reserve phantom width (misaligned idle pills) or expand on hover (layout shift). An opacity-revealed ⋮ keeps geometry constant; destructive close moves behind a menu.
  • Measured 1→2-row layout instead of pure CSS: CSS can't express "wrap once, then scroll horizontally", so DashboardSidebarChipStrip compares natural chip widths to the container width.

Known Limitations

  • The ⋮ slot is ~20px of invisible space at the end of each idle port pill (the cost of shift-free hover).
  • Menu wording ("External Browser" / "Superset Browser") differs from Settings → Links wording ("default browser" / "in-app browser").

Follow-ups

  • v1 WorkspaceSidebar ports UI intentionally untouched (v1 is sunset).

Open in Stage

Summary by cubic

Refactors the v2 sidebar ports/agents UI with compact neutral tags, per-section collapsible groups, and a measured two-row chip layout. Port pills open per preference on click; the menu separates External vs Superset in‑app open, and existing collapse state is preserved.

  • New Features

    • Compact neutral tags for ports and agents; agent status stays a colored dot.
    • Separate collapsible “Ports” and “Agents” with per‑section persisted state.
    • Port click opens per Settings → Links → Ports; remote ports open the workspace. Menu: Open in External Browser, Open in Superset Browser, Go to Workspace, Close.
    • Adaptive chip layout via DashboardSidebarChipStrip: single row, then two‑row grid on overflow, then horizontal scroll without hover shifts.
  • Refactors

    • Added DashboardSidebarChipStrip to measure chip widths and choose 1‑row/2‑row/scroll; bottom “Ports” list uses the same layout. Grid uses justify‑items‑start to avoid stretched chips inflating measurements.
    • Chevron appears on hover; chips align with the section summary label.
    • Persisted state keys are now ${workspaceId}:${sectionKey} with a migration from v0 collapsedWorkspaceIds to per‑section keys (existing collapsed workspaces map to collapsed Ports and Agents).
    • Narrowed store selector to this workspace’s section keys to avoid sidebar‑wide re‑renders.

Summary by CodeRabbit

  • New Features

    • Sidebar lists now use an adaptive chip strip that automatically switches between multi-row and single-row layouts, scrolling horizontally when space is limited.
    • Workspace details are now expandable/collapsible independently per section (instead of one shared state).
  • Bug Fixes / UX Improvements

    • Port badge interactions are simplified to a primary click plus a dropdown with “open” options and “Go to Workspace”, with updated tooltip text and a pending-safe “Close Port”.
  • Style

    • Improved badge and chevron presentation for a cleaner, more consistent sidebar look.