Files
deepseek-harness/packages/client/ui-sidebar/README.md
imccyu 698f46b0c9 feat(gui): morph the sidebar collapse instead of swapping renders
The collapse read as a hard cut: only the track width animated while the
panel content swapped instantly and the rail icons bore no relation to the
expanded layout. Now the four control rows persist across the transition —
collapse toggle, new session, new workspace, search, the same top-down
order as their expanded rows — and morph their geometry (row heights,
paddings, margins, capsule borders) on the deepsuite curve, so each rail
icon is its expanded control converging onto the 56px axis. Wide-only
content (brand, labels, input, session tree) cross-fades over 200ms, stays
mounted while the collapse animates, and unmounts at the 300ms settle,
still dropping the sessions subscription. The search query moves up to the
root and survives the round trip; rail search focuses the surviving input
after expand instead of remount-autofocus.
2026-07-23 13:03:32 +08:00

2.2 KiB

@deepseek-ai/dsh-client-ui-sidebar

Sidebar plugin: session multi-level tree (cwd grouping + parentId nesting), search, by-workspace grouping, state dots, three creation entries. Collapse morphs the four control rows into the layout-owned 56px rail (expand / new session / new workspace / search — search expands and focuses the search box) plus the settings foot: geometry animates on the deepsuite curve while wide-only content cross-fades and unmounts at settle. Contract: the slot system standard.

src/client/contract/slots.ts is the single-domain contract file: SidebarRootInjected (the registrant's own injected share — plain service callbacks: onOpen/onCreate/onToggleSidebar) and SidebarRootComponentProps = PropsRuntime<'sidebar'> & SidebarRootInjected (owner {collapsed,width} plus the standard useSessions hook, resolved off ui-layout's SlotMap declaration, never re-stated). apply registers SidebarRoot cast-free against that composition; the inject factory closes over the plugin's own ctx.

There is no plugin store: rows derive in the component (useMemo over the useSessions snapshot + local expansion/search state) through the pure deriveRows in tree.ts.

The /client export surface is the plugin body (apply/inject) plus the contract types only — SidebarRoot, the row components, and the tree derivation are internal (the slot registration closes over them; tests import src paths directly).

Model Experience

None, as the sidebar renders the browser session list; nothing here reaches a model request.

KV Cache effect

None; this package neither assembles nor sends a provider request.

Known Limitations and Deferred Work

  • State dots have two live data states (running/none) — the done/error/amber sources arrive with P-II approvals and notifications; the four-color primitive is already wired.
  • Group-by menu ships by-workspace only — Update/Status grouping strategies are drawn without specs and deferred.
  • "New task completed" unread marking is local viewing state — completion-time > last-seen never reaches the host.