diff --git a/src/renderer/src/components/sidebar/GroupControls.tsx b/src/renderer/src/components/sidebar/GroupControls.tsx
deleted file mode 100644
index 90e58a1e844..00000000000
--- a/src/renderer/src/components/sidebar/GroupControls.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import React from 'react'
-import { useAppStore } from '@/store'
-import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
-
-const GroupControls = React.memo(function GroupControls() {
- const groupBy = useAppStore((s) => s.groupBy)
- const setGroupBy = useAppStore((s) => s.setGroupBy)
-
- return (
-
- {
- if (v) {
- setGroupBy(v as typeof groupBy)
- }
- }}
- variant="outline"
- size="sm"
- className="h-6 flex-1 justify-start"
- >
-
- All
-
-
- PR Status
-
-
- Repo
-
-
-
- )
-})
-
-export default GroupControls
diff --git a/src/renderer/src/components/sidebar/SearchBar.tsx b/src/renderer/src/components/sidebar/SearchBar.tsx
index 23d30e2b1b2..4ba4757da60 100644
--- a/src/renderer/src/components/sidebar/SearchBar.tsx
+++ b/src/renderer/src/components/sidebar/SearchBar.tsx
@@ -1,5 +1,5 @@
import React, { useCallback } from 'react'
-import { Search, X, Activity, FolderTree, FolderPlus } from 'lucide-react'
+import { Search, X, Activity, ListFilter, FolderPlus } from 'lucide-react'
import { useAppStore } from '@/store'
import { Input } from '@/components/ui/input'
import { Button } from '@/components/ui/button'
@@ -8,6 +8,7 @@ import {
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuItem,
+ DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
@@ -37,30 +38,39 @@ const SearchBar = React.memo(function SearchBar() {
[filterRepoIds, setFilterRepoIds]
)
- const repoTriggerLabel =
- selectedRepos.length === 0 ? (
-
-
- All
-
- ) : selectedRepos.length === 1 ? (
-
- ) : (
-
-
- {selectedRepos.length} repos
-
- )
-
const handleClear = useCallback(() => setSearchQuery(''), [setSearchQuery])
const handleToggleActive = useCallback(
() => setShowActiveOnly(!showActiveOnly),
[showActiveOnly, setShowActiveOnly]
)
+ const canFilterRepos = repos.length > 1
+ const hasRepoFilter = canFilterRepos && selectedRepos.length > 0
+ const hasAnyFilter = showActiveOnly || hasRepoFilter
+ const activeFilterCount = (showActiveOnly ? 1 : 0) + (hasRepoFilter ? selectedRepos.length : 0)
+
+ const filterSummary = (() => {
+ if (!hasAnyFilter) {
+ return null
+ }
+ if (showActiveOnly && !hasRepoFilter) {
+ return (
+
+
+ Active
+
+ )
+ }
+ if (!showActiveOnly && hasRepoFilter && selectedRepos.length === 1) {
+ return (
+
+ )
+ }
+ return {activeFilterCount} filters
+ })()
return (
@@ -78,71 +88,87 @@ const SearchBar = React.memo(function SearchBar() {
)}
-
-
-
-
-
- {showActiveOnly ? 'Show all' : 'Active only'}
-
-
- {repos.length > 1 && (
-
-
-
-
-
- {
- setFilterRepoIds([])
- }}
- >
- All repos
-
- {repos.map((r) => (
- handleToggleRepo(r.id)}
- onSelect={(event) => event.preventDefault()}
+
+
+
+
+
- ))}
-
- {
- addRepo()
- }}
- >
-
- Add repo
-
-
-
- )}
+
+ {filterSummary}
+
+
+
+
+ {hasAnyFilter ? 'Edit filters' : 'Filter worktrees'}
+
+
+
+ Status
+ event.preventDefault()}
+ >
+
+ Active only
+
+ {canFilterRepos && (
+ <>
+
+ Repositories
+ {repos.map((r) => (
+ handleToggleRepo(r.id)}
+ onSelect={(event) => event.preventDefault()}
+ >
+
+
+ ))}
+ >
+ )}
+ {hasAnyFilter && (
+ <>
+
+ {
+ setShowActiveOnly(false)
+ setFilterRepoIds([])
+ }}
+ >
+
+ Clear filters
+
+ >
+ )}
+ {canFilterRepos && (
+ <>
+
+ {
+ addRepo()
+ }}
+ >
+
+ Add repo
+
+ >
+ )}
+
+
diff --git a/src/renderer/src/components/sidebar/SidebarHeader.tsx b/src/renderer/src/components/sidebar/SidebarHeader.tsx
index fb71576f3a5..e8f00eec774 100644
--- a/src/renderer/src/components/sidebar/SidebarHeader.tsx
+++ b/src/renderer/src/components/sidebar/SidebarHeader.tsx
@@ -3,6 +3,7 @@ import { Plus, SlidersHorizontal } from 'lucide-react'
import { useAppStore } from '@/store'
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip'
+import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
import { isGitRepoKind } from '../../../../shared/repo-kind'
import {
DropdownMenu,
@@ -16,6 +17,12 @@ import {
} from '@/components/ui/dropdown-menu'
import type { WorktreeCardProperty } from '../../../../shared/types'
+const GROUP_BY_OPTIONS = [
+ { id: 'none', label: 'All' },
+ { id: 'pr-status', label: 'PR Status' },
+ { id: 'repo', label: 'Repo' }
+] as const
+
const PROPERTY_OPTIONS: { id: WorktreeCardProperty; label: string }[] = [
{ id: 'status', label: 'Terminal status' },
{ id: 'unread', label: 'Unread indicator' },
@@ -44,6 +51,8 @@ const SidebarHeader = React.memo(function SidebarHeader() {
const toggleWorktreeCardProperty = useAppStore((s) => s.toggleWorktreeCardProperty)
const sortBy = useAppStore((s) => s.sortBy)
const setSortBy = useAppStore((s) => s.setSortBy)
+ const groupBy = useAppStore((s) => s.groupBy)
+ const setGroupBy = useAppStore((s) => s.setGroupBy)
return (
@@ -69,7 +78,34 @@ const SidebarHeader = React.memo(function SidebarHeader() {
View options
-
+
+ Group by
+
+ {
+ if (v) {
+ setGroupBy(v as typeof groupBy)
+ }
+ }}
+ variant="outline"
+ size="sm"
+ className="h-6 w-full justify-start"
+ >
+ {GROUP_BY_OPTIONS.map((opt) => (
+
+ {opt.label}
+
+ ))}
+
+
+
+
Sort by
-
{/* Virtualized scrollable list */}