import React from 'react'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'; import { cn } from '@/lib/utils'; import { Icon } from "@/components/icon/Icon"; import { ArrowsMerge } from '@/components/icons/ArrowsMerge'; import { useSessionDisplayStore } from '@/stores/useSessionDisplayStore'; import { useSessionMultiSelectStore } from '@/stores/useSessionMultiSelectStore'; import { useI18n } from '@/lib/i18n'; import { updateDesktopSettings } from '@/lib/persistence'; type Props = { hideDirectoryControls: boolean; showProjectDisplayControls: boolean; showRecentControls: boolean; handleOpenDirectoryDialog: () => void; onOpenScheduled: () => void; onOpenMultiRun: () => void; canOpenMultiRun: boolean; onOpenArchive: () => void; headerActionIconClass: string; headerActionButtonClass: string; isSessionSearchOpen: boolean; setIsSessionSearchOpen: (open: boolean | ((prev: boolean) => boolean)) => void; sessionSearchInputRef: React.RefObject; sessionSearchQuery: string; setSessionSearchQuery: (value: string) => void; hasSessionSearchQuery: boolean; searchMatchCount: number; collapseAllProjects: () => void; expandAllProjects: () => void; }; export function SidebarHeader(props: Props): React.ReactNode { const { t } = useI18n(); const { hideDirectoryControls, showProjectDisplayControls, showRecentControls, handleOpenDirectoryDialog, onOpenScheduled, onOpenMultiRun, canOpenMultiRun, onOpenArchive, headerActionIconClass, headerActionButtonClass, isSessionSearchOpen, setIsSessionSearchOpen, sessionSearchInputRef, sessionSearchQuery, setSessionSearchQuery, hasSessionSearchQuery, searchMatchCount, collapseAllProjects, expandAllProjects, } = props; const selectionModeEnabled = useSessionMultiSelectStore((state) => state.enabled); const toggleSelectionMode = useSessionMultiSelectStore((state) => state.toggleMode); const showRecentSection = useSessionDisplayStore((state) => state.showRecentSection); const toggleRecentSection = useSessionDisplayStore((state) => state.toggleRecentSection); const projectSortOrder = useSessionDisplayStore((state) => state.projectSortOrder); const setProjectSortOrder = useSessionDisplayStore((state) => state.setProjectSortOrder); const sessionGroupingMode = useSessionDisplayStore((state) => state.sessionGroupingMode); const setSessionGroupingMode = useSessionDisplayStore((state) => state.setSessionGroupingMode); const stickyZoneHeaders = useSessionDisplayStore((state) => state.stickyZoneHeaders); const toggleStickyZoneHeaders = useSessionDisplayStore((state) => state.toggleStickyZoneHeaders); const projectDisplayMode = useSessionDisplayStore((state) => state.projectDisplayMode); const setProjectDisplayMode = useSessionDisplayStore((state) => state.setProjectDisplayMode); const isSingleProjectMode = showProjectDisplayControls && projectDisplayMode === 'single'; if (hideDirectoryControls) { return null; } return (
{/* Quiet toolbar under the New-session CTA: project/surface entry points at left, list controls at right. ml-[3px] compensates the icon inset inside the 24px buttons so the first glyph lines up with the New-session icon above (16px from the sidebar edge). */}

{t('sessions.sidebar.header.actions.addProject')}

{t('sessions.sidebar.header.actions.scheduledTasks')}

{t('sessions.sidebar.header.actions.newMultiRun')}

{t('sessions.sidebar.nav.archive')}

{t('sessions.sidebar.header.actions.searchSessions')}

{selectionModeEnabled ? t('sessions.sidebar.header.actions.exitSelection') : t('sessions.sidebar.header.actions.selectSessions')}

{t('sessions.sidebar.header.displayMode.label')}

{t('sessions.sidebar.header.actions.sortProjects')} {([ ['manual', 'sessions.sidebar.header.projectSort.manual'], ['a-z', 'sessions.sidebar.header.projectSort.aToZ'], ['z-a', 'sessions.sidebar.header.projectSort.zToA'], ['date-added', 'sessions.sidebar.header.projectSort.dateAdded'], ['recent', 'sessions.sidebar.header.projectSort.recent'], ] as const).map(([order, labelKey]) => ( { setProjectSortOrder(order); void updateDesktopSettings({ sidebarProjectSortOrder: order }); }} className="flex items-center justify-between" > {t(labelKey)} {projectSortOrder === order ? : null} ))} {showProjectDisplayControls ? ( <> {t('sessions.sidebar.header.projectDisplay.label')} {([ ['all', 'sessions.sidebar.header.projectDisplay.all'], ['single', 'sessions.sidebar.header.projectDisplay.single'], ] as const).map(([mode, labelKey]) => ( { setProjectDisplayMode(mode); void updateDesktopSettings({ sidebarProjectDisplayMode: mode }); }} className="flex items-center justify-between" > {t(labelKey)} {projectDisplayMode === mode ? : null} ))} ) : null} {t('sessions.sidebar.header.grouping.label')} {([ ['by-worktree', 'sessions.sidebar.header.grouping.byWorktree'], ['flat', 'sessions.sidebar.header.grouping.flat'], ] as const).map(([mode, labelKey]) => ( { setSessionGroupingMode(mode); void updateDesktopSettings({ sidebarSessionGroupingMode: mode }); }} className="flex items-center justify-between" > {t(labelKey)} {sessionGroupingMode === mode ? : null} ))} {showRecentControls && !isSingleProjectMode ? ( { toggleRecentSection(); void updateDesktopSettings({ sidebarShowRecentSection: !showRecentSection }); }} className="flex items-center justify-between" > {t('sessions.sidebar.header.displayMode.showRecent')} {showRecentSection ? : null} ) : null} {t('sessions.sidebar.header.displayMode.stickyHeaders')} {stickyZoneHeaders ? : null} {!isSingleProjectMode ? ( <> {t('sessions.sidebar.header.displayMode.collapseAll')} {t('sessions.sidebar.header.displayMode.expandAll')} ) : null}
{isSessionSearchOpen ? (
{hasSessionSearchQuery ? ( {searchMatchCount === 1 ? t('sessions.sidebar.header.search.matchCountSingle', { count: searchMatchCount }) : t('sessions.sidebar.header.search.matchCountPlural', { count: searchMatchCount })} ) : } {t('sessions.sidebar.header.search.escapeHint')}
setSessionSearchQuery(event.target.value)} placeholder={t('sessions.sidebar.header.search.placeholder')} className="h-8 w-full rounded-md border border-border bg-transparent pl-8 pr-8 typography-ui-label text-foreground outline-none focus-visible:ring-2 focus-visible:ring-primary/50" onKeyDown={(event) => { if (event.key === 'Escape') { event.stopPropagation(); if (hasSessionSearchQuery) { setSessionSearchQuery(''); } else { setIsSessionSearchOpen(false); } } }} /> {sessionSearchQuery.length > 0 ? ( ) : null}
) : null}
); }