Skip to content

feat(workspaces): prototype the panel components on the UI tree - #1077

Draft
EhabY wants to merge 6 commits into
feat/ui-tree-hoversfrom
feat/devex-621-workspaces-panel-mvp
Draft

feat(workspaces): prototype the panel components on the UI tree#1077
EhabY wants to merge 6 commits into
feat/ui-tree-hoversfrom
feat/devex-621-workspaces-panel-mvp

Conversation

@EhabY

@EhabY EhabY commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Prototype for DEVEX-621 on top of the Tree stack (#1065#1079#1078): the Workspaces panel rendered in the experimental coder.workspacesPanel test webview with mock data, so the row/panel components can be exercised before the real IPC wiring lands.

What's in the MVP

  • WorkspacesPanel — toolbar + tree + state panels; owns the filter/search state. No IPC yet.
  • WorkspaceFilterSelect — Mine / All / Shared radio menu on a secondary Button; Shared gated by isOwner.
  • Workspace and agent rows as rich Tree labels with status StatusPills and hover-revealed inline actions (open/dashboard/settings; terminal/logs).
  • Inline App Statuses and Agent Metadata sections under agents; metadata values carry a collected-at Tooltip.
  • Live-filter SearchInput, plus LoadingState / ErrorState / EmptyState branches.
  • Mock data lives in mockData.ts (local fixtures; @repo/mocks is lint-restricted from runtime code).

Notes

  • @repo/ui becomes a webview dependency — this webview is its first production bundler. The shared Vite config aliases its TypeScript source and #cx/#codicons subpath imports; index.css imports the UI codicon stylesheet and tokens (theme-matched via --vscode-*).
  • Intentionally out of scope: useWorkspaceData/IPC, Storybook stories, welcome/auth states, keyboard-nav acceptance tests — all belong to the full DEVEX-621 implementation.

Validation

  • pnpm typecheck, pnpm lint, pnpm format:check
  • pnpm build (all webviews + extension)
  • pnpm test:webview — 46 files, 390 tests passed (incl. new WorkspacesPanel.test.tsx)
  • pnpm test:extension — 120 files, 2113 tests passed
Implementation plan

Decisions (confirmed)

Changes

Wiring

  • packages/workspaces: add @repo/ui dependency; add @repo/ui tsconfig path; index.css imports codicon/tokens CSS; index.tsx wraps in TooltipProvider.
  • packages/webview-shared/createWebviewConfig.ts: alias @repo/ui source and its package-internal subpath imports for bundlers.
  • vitest.config.mts + test/tsconfig.json: @repo/workspaces path for tests.

Prototype components (packages/workspaces/src/)

  • mockData.ts — local SDK-typed fixtures (own/shared/other-owner workspaces, agents with apps/statuses/metadata).
  • WorkspacesPanel.tsx — top level; filter/search state, mock→TreeNode[] mapping, toolbar + Tree (sticky scroll) + state panels.
  • WorkspaceFilterSelect.tsx — Mine / All / Shared radio menu.
  • rows.tsxworkspaceNode / agentNode / appStatusSection / metadataSection builders with rich labels, pills, and hover actions.
  • WorkspacesPanel.css — toolbar/tree layout.

Tests

  • test/webview/workspaces/WorkspacesPanel.test.tsx — tree rendering, filter select, live search, empty/loading/error states, inline sections, hover actions.

Not in scope (MVP)

  • Real IPC / useWorkspaceData / handler wiring.
  • Storybook stories, pixel snapshots, keyboard-nav acceptance tests.
  • Welcome/auth states, real command execution behind inline actions.

This pull request was created by Coder Agents on behalf of @EhabY.

@linear-code

linear-code Bot commented Aug 13, 2026

Copy link
Copy Markdown

DEVEX-621

@EhabY
EhabY force-pushed the feat/devex-621-workspaces-panel-mvp branch from 1e94086 to 60736ac Compare August 14, 2026 13:24
@EhabY
EhabY force-pushed the feat/devex-621-workspaces-panel-mvp branch 3 times, most recently from aabaa01 to 6edf54d Compare August 14, 2026 14:59
@EhabY
EhabY force-pushed the feat/devex-621-workspaces-panel-mvp branch from 6edf54d to 2626381 Compare August 14, 2026 15:41
@EhabY
EhabY changed the base branch from feat/ui-tree-suite to feat/ui-tree-hovers August 14, 2026 16:17
EhabY added 2 commits August 14, 2026 19:20
A controlled Tree that follows current VS Code workbench behavior: every
visible node renders as a flat `treeitem` row with declared aria-level,
posinset, and setsize, while keyboard navigation keeps DOM focus on the
container and names the active row with `aria-activedescendant`. Focus and
selection stay independent, as they do natively.

Arrow keys, Home, and End move the active row; Arrow Right and Left walk
into and out of branches; Enter, Space, and the twistie follow VS Code's
split between selecting and expanding, under either expand mode. Rows are
22px with the native twistie gutter and indent guides, and `variant="explorer"`
aligns leaf icons with branch twisties for icon-less file trees.

The model, the input policy, and the interaction transitions are pure
modules; `useTreeAdapter` is the only place React state and the DOM meet.
The flat projection leaves room for windowing later.

Closes #1037
Multi-selection with `selectedItemIds`, ranges anchored the way the native
list anchors them, Ctrl/Cmd toggling under either `multiSelectModifier`,
and Ctrl/Cmd+A scoped to the active sibling group before widening to its
parent, which is what `list.selectAll` does for a tree.

Buffered prefix and fuzzy type navigation, PageUp and PageDown measured
against the scroller's viewport, and sticky scroll: ancestors pin against
the nearest scrolling ancestor with VS Code's pinned-count and 40% viewport
caps, the deepest row sliding out as its subtree ends, and its own tab stop
for keyboard reveal.
@EhabY
EhabY force-pushed the feat/devex-621-workspaces-panel-mvp branch from 2626381 to 71cb46c Compare August 14, 2026 16:26
EhabY and others added 4 commits August 14, 2026 19:45
Rows hover with their text value, as VS Code's tree falls back to the
label when an item has no tooltip; `tooltip` overrides it and null opts
out. Ctrl+K Ctrl+I opens the focused row's hover, the chord bound to
list.showHover, and IconButton hints with its label like an action bar
item.

One bubble serves a whole tree rather than one per trigger, the way a
list hands a single hover delegate to its rows and their action bars.
Rows report the element under the pointer through `HoverDelegateScope`
and an invisible anchor moves to it. That single widget is also the only
place a delay rule can live, and native's rule needs one: each new target
waits out `workbench.hover.delay`, except inside a row's action bar, the
dense cluster native grants an instant handoff.

A managed hover always uses hoverPosition 2, whatever the widget's own
default, so the bubble sits 2px into the bottom edge of its target rather
than above it. Placement then splits on the delegate: an element-placed
hover, which is what an action bar button gets, centers under it, while a
mouse-placed one, which is what a row gets, follows the cursor.

Measured in Chrome: label to a button 513ms, button to button 19ms, and
mounting 2,000 rows 189ms against 515ms for a Radix root per row. Also
pins the sticky container at native's z-index 13, below the hover's 40,
so pinned rows no longer paint over a bubble, and drops the menu parity
story's trigger button so both menus line up.
MVP for DEVEX-621: render the Workspaces panel in the experimental
coder.workspacesPanel webview using the @repo/ui Tree from #1065 so the
row and panel components can be exercised with mock data before the real
IPC wiring lands.

- WorkspacesPanel with SearchInput live filtering and the Mine / All /
  Shared WorkspaceFilterSelect (Shared gated by isOwner)
- Workspace and agent rows as rich Tree labels with status pills and
  hover-revealed inline actions
- Inline App Statuses and Agent Metadata sections under agents, with a
  collected-at tooltip on metadata values
- Loading / error / empty state panels over the mock data
- @repo/ui becomes a webview dependency; the shared Vite config aliases
  its TypeScript source and package-internal subpath imports

This pull request description was generated by Coder Agents.
Keep the native My/Shared/All Workspaces views registered so both
implementations stay visible side by side while the prototype is tested.
… matches

- Row labels are flex rows; each child shrank and truncated on its own,
  splitting the ellipsis across words. Only the name span truncates now;
  owner text and pills keep their natural width.
- Search now marks the first case-insensitive match in workspace and
  agent names, mirroring the native views' highlight.
@EhabY
EhabY force-pushed the feat/devex-621-workspaces-panel-mvp branch from 71cb46c to a048143 Compare August 14, 2026 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant