mirror of
https://github.com/stablyai/orca.git
synced 2026-09-21 16:02:20 +00:00
Replaces the DropdownMenu-based repo filter with a Command/Popover combo that supports live search, All/None bulk actions, and a Clear all footer. Scales to large repo sets without scroll friction. Design doc added at docs/sidebar-filter-redesign.md. Co-authored-by: Orca <help@stably.ai>
4.2 KiB
4.2 KiB
Sidebar Repo Filter Redesign
Problem
The current sidebar filter UI does not scale beyond a small repo count. Rendering every repo as a checkbox row in a menu creates poor scanability, high click cost, and clipping/scroll friction.
Constraints from current code:
- Filter semantics are store-driven (
showActiveOnly,hideDefaultBranchWorkspace,filterRepoIds) and consumed bycomputeVisibleWorktreeIds. searchRepos()already provides ranking (display name first, path fallback).- The trigger badge is the primary “filters active” affordance and must stay.
Goals
- Make repo filtering usable with large repo sets.
- Keep toggle filters one click.
- Add fast bulk actions (
All,None,Clear all). - Preserve existing filter semantics and badge behavior.
Non-goals
- No semantic changes to filtering logic in
visible-worktrees.ts. - No sticky-all persistence model like
RepoMultiCombobox. - No store schema migration.
Correctness Notes (from code audit)
searchRepos()is not debounced; it is synchronoususeMemofiltering.- Popover wheel rescue in
popover.tsxonly runs when the wheel handler is attached to aPopoverContentelement that has classpopover-scroll-content. Putting that class on an inner div does not activate the rescue path. command.tsxalready includes a wheel fallback onCommandListfor scroll-locked Radix Dialog parents.- Sidebar filters are persisted via
window.api.ui.set(debounced inApp.tsx) and restored from persisted UI on launch.
Proposed UI
Use Popover and keep trigger button/badge unchanged.
Popover sections:
- Header:
Filters+Clear all(shown only when any filter is active). - Toggle rows:
Active only,Hide default branch. - Repo section (only when
repos.length > 1):- Label + selected count.
AllandNoneactions.- Search box (
Search repos...). - Scrollable repo list with checkmark, repo dot/name, and SSH badge when
connectionIdexists. - Secondary path line for disambiguation when names collide.
- Bottom action:
Add projectpinned below repo list.
Implementation Decision: cmdk vs plain input
Use Command primitives (as in repo-multi-combobox.tsx) with shouldFilter={false} and feed pre-ranked searchRepos() results.
Why:
- Better keyboard behavior out of the box (arrow navigation, enter selection).
- Existing
CommandListwheel fallback handles scroll-lock contexts that currently break plain inner-scroll regions. - Consistent behavior with an existing repo selector pattern in the app.
Edge Cases / Invalidation
- Repo removed while popover is open: selection count and rows derive from live
repos; stale ids must not count toward badge or selected count. - Repo added while open:
Allshould include the new repo immediately (derive from currentreposeach render). - External repo mutations (sync/import) during search: filtered list updates from live
repos; empty-state must not hideAdd project. - SSH repos: show SSH indicator to avoid ambiguity with local repos of same display name.
- 0 or 1 repo: hide repo filter section. Keep
Add projectvisible outside the repo-count gate so users can still recover from low-repo states. - Multi-window: filter state is window-local; this redesign does not introduce cross-window synchronization.
Accessibility / Focus
- Do not use
role="menuitemcheckbox"unless the container is a true menu. Use semantic buttons or cmdk items with explicitaria-selected/checked indicators. - Autofocus search on open.
- Esc closes via Radix Popover default.
- Ensure focus returns to trigger on close.
Rollout
- Replace sidebar filter content with Popover + Command-based repo list.
- Keep
searchRepos()as the only ranking source. - Keep current filter setters and badge derivation semantics.
- Ensure scroll behavior works inside dialog parents by using
CommandList(or by moving wheel handling to the actual scroll container). - Validate with
pnpm typecheckandpnpm lint.
Test Scope
- Unit coverage remains in
visible-worktreesfor filter semantics. - Add/adjust component tests for:
- keyboard navigation and selection,
- stale repo id handling,
All/Nonebehavior with live repo mutations,Add projectvisibility at repo count 0/1.