Skip to content

feat(command palette): add View toggles (Sidebar, Active Agents, Canvas, Shelf, Show Diff)#294

Open
onevcat wants to merge 1 commit into
mainfrom
command-palette-view-toggles
Open

feat(command palette): add View toggles (Sidebar, Active Agents, Canvas, Shelf, Show Diff)#294
onevcat wants to merge 1 commit into
mainfrom
command-palette-view-toggles

Conversation

@onevcat
Copy link
Copy Markdown
Owner

@onevcat onevcat commented May 16, 2026

Summary

PR4 of the four-PR command palette plan (doc-onevcat/plans/2026-05-16-command-palette-architecture-plan.md). Surfaces the 5 view toggles that were previously hotkey-only.

Command Hotkey Category Suggested? Gating
Toggle Sidebar ⌘⌃S .view yes always
Toggle Active Agents Panel ⌘⌥P .view yes always
Toggle Canvas ⌘⌥↩ .view yes always
Toggle Shelf ⌘⇧↩ .view yes always
Show Diff ⌘⇧Y .view yes hidden unless a worktree is selected

Each is a one-liner through PR3's .appShortcut factory, with keyword aliases for fuzzy search (sidebar, agents, canvas, shelf, diff, etc.).

Architectural change: lift leftSidebarVisibility into AppFeature.State

Previously the main window's sidebar visibility lived as @State in ContentView, mutated via a FocusedValue closure invoked from the menu's "Toggle Left Sidebar" button. The palette can't reach scene-scoped FocusedValue closures from a reducer, so I lifted the state up:

  • AppFeature.State.leftSidebarVisibility: NavigationSplitViewVisibility
  • New actions: .toggleLeftSidebar, .showLeftSidebar, .setLeftSidebarVisibility(_) (last one backs the NavigationSplitView's columnVisibility binding)
  • ContentView constructs a Binding(get:set:) against the store
  • Animation moves from withAnimation { ... } (in the imperative closure) to .animation(.easeOut(duration: 0.2), value: store.leftSidebarVisibility) (on the view)
  • The diff window keeps its own per-scene columnVisibility — they're independent NavigationSplitViews, so this doesn't affect the diff sidebar's behavior

The FocusedValue closures (toggleLeftSidebarAction, revealInSidebarAction) still exist and now dispatch TCA actions instead of mutating local state — menu behavior unchanged.

Test plan

  • make build-app — green
  • make check (swift-format + swiftlint strict) — green
  • CommandPaletteFeatureTests + AppFeatureCommandPaletteTests + AppShortcutsTests — all pass
  • New tests:
    • commandPaletteItems_onlyGlobalWhenEmpty updated to include the 4 new always-on view commands
    • commandPaletteItems_includesShowDiffWhenWorktreeSelected
    • commandPaletteItems_omitsShowDiffWithoutSelectedWorktree
  • Manual UI verification — please confirm before merging:
    • Open Cmd+P → see 4 "Toggle X" commands and (when on a worktree) "Show Diff" in Suggested
    • Activate each — sidebar collapses/expands, canvas/shelf/agents panels toggle, diff window opens
    • Trigger ⌘⌃S directly (no palette) — sidebar still toggles via menu/FocusedValue path
    • Open the diff window, hit ⌘⌃S there — diff window's own sidebar toggles independently

…as, Shelf, Show Diff)

Surfaces the 5 view toggles that were previously hotkey-only:

- Toggle Sidebar (⌘⌃S)
- Toggle Active Agents Panel (⌘⌥P)
- Toggle Canvas (⌘⌥↩)
- Toggle Shelf (⌘⇧↩)
- Show Diff (⌘⇧Y) — only appears when a worktree is selected

All registered through the `.appShortcut` factory (PR3), so each is a
one-liner. They live in the new `.view` category, are suggested by default,
and ship with keyword aliases ("sidebar", "agents", "canvas", "shelf",
"diff", etc.).

Architectural change: lift `leftSidebarVisibility` from ContentView's
private @State into AppFeature.State, so the palette can dispatch
`.toggleLeftSidebar` and `.showLeftSidebar` actions via the existing
delegate-routing mechanism. The diff window keeps its own per-scene
column visibility — they're independent NavigationSplitViews.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant