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