diff --git a/apps/desktop/src/app/chat/sidebar/index.tsx b/apps/desktop/src/app/chat/sidebar/index.tsx index 472ef8fdb18..6dcbff1d5af 100644 --- a/apps/desktop/src/app/chat/sidebar/index.tsx +++ b/apps/desktop/src/app/chat/sidebar/index.tsx @@ -1502,49 +1502,27 @@ function SidebarWorkspaceGroup({ style={style} {...rest} > -
- - {(onNewSession || isProfileGroup) && ( - - - - )} -
+ /> + ) + } + count={isProfileGroup ? countLabel(visibleSessions.length, totalCount) : group.sessions.length} + dragging={dragging} + dragHandleProps={dragHandleProps} + icon={leadingIcon} + label={group.label} + onToggle={() => setOpen(value => !value)} + open={open} + reorderable={reorderable} + /> {open && ( <> {renderRows(visibleSessions)} @@ -1637,44 +1615,22 @@ function SidebarWorkspaceParent({ style={style} {...rest} > -
- - {onNewSession && (newSessionPath || soleWorktree) && ( - - - - )} -
+ onNewSession?.(newSessionPath)} /> + ) + } + count={parent.sessionCount} + dragging={dragging} + dragHandleProps={dragHandleProps} + emphasis + icon={} + label={parent.label} + onToggle={() => setOpen(value => !value)} + open={open} + reorderable={reorderable} + /> {open && (soleWorktree ? ( // Collapsed: the repo's sessions hang straight off the header. @@ -1784,6 +1740,89 @@ function WorkspaceReorderHandle({ ) } +// "+" affordance shared by repo and worktree headers — reveals on header hover. +function WorkspaceAddButton({ label, onClick }: { label: string; onClick: () => void }) { + return ( + + + + ) +} + +// Collapsible header shared by the repo (emphasis) and worktree levels: a +// toggle button whose leading glyph doubles as the reorder handle, plus an +// optional trailing action (the +). +function WorkspaceHeader({ + action, + count, + dragHandleProps, + dragging = false, + emphasis = false, + icon, + label, + onToggle, + open, + reorderable = false +}: { + action?: React.ReactNode + count: React.ReactNode + dragHandleProps?: React.HTMLAttributes + dragging?: boolean + emphasis?: boolean + icon: React.ReactNode + label: string + onToggle: () => void + open: boolean + reorderable?: boolean +}) { + const { t } = useI18n() + + return ( +
+ + {action} +
+ ) +} + interface SortableSessionRowProps { session: SessionInfo isPinned: boolean