feat(desktop): back and forward through plans and Settings, with ⌘[ / ⌘] and title-bar buttons

Merged
DA
8d ago
+885-52

What

  • One in-memory history for the window, browser-style: what's behind, the current place, and what's ahead. A new visit clears what's ahead, the history holds at most 50 places, and it isn't kept across launches. A place is a plan (by id, so renaming it changes nothing), the new-plan page, or Settings.

  • Settings is one step (decided with Dean). Opening Settings adds one entry. Choosing another Settings page changes that entry's page in place and adds nothing. So Back from any Settings page returns to where Settings was opened, and Forward brings Settings back on the last page you had open.

  • The history records where the window is, not each control that moved it. useWindowHistory in navigation-history.ts watches the window's location, so every way of moving counts the same: sidebar, ⌘N, ⌥⌘↑/↓, starting a plan, deleting the open one, ⌘, and the account button. Choosing the place you're already on adds nothing.

  • PlansControl.boundFor: the plan a press asked for, until the host answers. Without it, ⌘N from Settings would record a moment on the old plan before the host closed it.

  • A deleted plan is skipped in both directions, so Back never lands on "This plan no longer exists". If the plan list itself fails to read, nothing is skipped. A plan whose document fails to read is still a place, and it shows its own error.

  • ← → buttons (new arrow glyphs ArrowLeftIcon / ArrowRightIcon in @sidecar/panel, drawn in the panel's own stroke weight) at the right of the left column's title-bar row, level with the traffic lights. They're in the plans sidebar and in Settings' page list. They sit inside the column after its drag strip, so they stay pinned to its right edge while it's resized and slide away when it folds. They're dimmed, not hidden, when there's nothing back or forward. Tooltips read Back ⌘[ and Forward ⌘]. At the 200px minimum width they still end short of the sidebar-toggle cluster.

  • ⌘[ / ⌘] are in the shared shortcut table. They appear in a new Go menu (Back, Forward, as in Finder and Safari) and on the Keyboard shortcuts page under a new Navigation group. They work while the sidebar is folded. The mouse's back and forward buttons do the same. There is no trackpad swipe, per Dean.

  • Escape exits Settings, replacing the old ⌘[ "Back to plans". It goes back to where Settings was opened, or to the plans if nothing is behind it. The order of what Escape closes is unchanged:

    1. A menu (it consumes its own Escape).
    2. A dialog. App's Escape now respects defaultPrevented, so a confirm dialog's Escape no longer falls through.
    3. The settings search (it clears the query, then lets go of the caret).
    4. Settings itself.

    Escape no longer steps from a Settings page to General first. Settings' Back row does exactly what Escape does (agreed with the orchestrator) and shows Esc. The Keyboard shortcuts page lists "Exit settings · Esc".

  • The PANEL_TAB_CHANGE analytics event fires as before, through changeTab, whenever a move changes the tab. SETTINGS_VIEW_OPEN still counts only presses on page rows.

Screenshots

Headless Chrome, rendering the real DesktopShell over the planning fixture and the real history. The traffic lights are drawn in by the stand-in page. On Linux the ⌘ glyph renders as a box.

Expanded (Back enabled, Forward dimmed)Collapsed (buttons fold away with the sidebar)
expandedcollapsed
Settings (same place in the page list)Minimum width 200px (clear of the toggle)
settingsmin width

Tests

  • navigation-history.test.ts drives the real DesktopShell and useWindowHistory:
    • Back and forward order, and a new visit clearing forward.
    • Choosing the current place records nothing.
    • Settings as one step, with its pages changing in place.
    • Deleted plans skipped both ways.
    • Buttons dimmed at the ends and their chords unclaimed there. The sidebar fold makes the buttons inert while ⌘[ still works. The tooltip reads Back⌘[.
    • Settings' own buttons.
    • The Escape order: the search clears first, then Settings exits to where it was opened. The Back row does the same, and with nothing behind, Escape opens the plans.
    • Mouse buttons 3/4 and the Go menu commands.
  • use-plans-tab.test.ts: boundFor follows a press immediately, falls back when the select is refused, and follows the host's own move.
  • app-menu.test.ts: Go holds Back ⌘[ and Forward ⌘], and choosing either sends its command to the window.
  • Existing shell, sidebar, settings, and pane tests were updated for the new history prop and the ⌘[ → Escape change.

Verification

  • ./scripts/check.sh exits 0.
  • CI could not verify the Mac UI, and ./scripts/verify.sh was not run. This was built on a Linux cloud VM, and LUKE-159 is the manual Mac pass. The screenshots above are headless Chrome, not Electron.

🤖 Generated with Claude Code


Open workspace in Conductor


Devin Review