improve(ui): unify new-thread folder and where pickers into one place picker#112035
Conversation
… picker The new-thread draft asked for one decision (where does this thread run) through two chips with separate popovers, a dead-end target-list panel with a disabled back button, and a machine menu that rendered even when the Gateway was the only choice. One chip now carries the (destination, folder) pair; its popover stacks a root menu (workspace, recent places derived from the session list, browse, places, worktree) over the folder browser, back and Escape pop one level, and the destination axis only appears when there is a real choice or an existing selection.
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: improve(ui): unify new-thread folder and where pickers into one place picker This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
…gate Knip's production scan rejects test-only exports; the recents derivation moves to recent-places.ts, imported by the place picker, and the unit test follows it.
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: improve(ui): unify new-thread folder and where pickers into one place picker This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: improve(ui): unify new-thread folder and where pickers into one place picker This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
|
Merged via squash.
|
… picker (openclaw#112035) * improve(ui): unify new-thread folder and where pickers into one place picker The new-thread draft asked for one decision (where does this thread run) through two chips with separate popovers, a dead-end target-list panel with a disabled back button, and a machine menu that rendered even when the Gateway was the only choice. One chip now carries the (destination, folder) pair; its popover stacks a root menu (workspace, recent places derived from the session list, browse, places, worktree) over the folder browser, back and Escape pop one level, and the destination axis only appears when there is a real choice or an existing selection. * fix(ui): give recentPlaces a production consumer module for the knip gate Knip's production scan rejects test-only exports; the recents derivation moves to recent-places.ts, imported by the place picker, and the unit test follows it. * fix(ui): drop stale place-picker.test.ts left behind by the rename
What Problem This Solves
Resolves a set of interaction traps in the new-thread draft's "where does this thread run" controls:
Gateway · localwas the only target; its back button was disabled at that root, so the only way forward was clicking the sole entry and confirming with "Use this folder" — a modal dead end for a non-decision.Why This Change Was Made
One primitive instead of two: a single place chip (
openclaw · Gateway · local) opens a single popover with stack navigation.User Impact
Picking where a thread works is now one chip and mostly one click (recents), the machine axis disappears when it is a non-decision, and back/Escape always work. Offline devices no longer appear as disabled browser rows (they were already absent from the "Run on" menu); exec-only nodes keep manual path entry. The mock dev harness (
pnpm dev:ui:mock) now exercises the full picker (fs.listDir, branches, cloud profile, recents).Before — two chips; forced target list with one real choice, disabled back, modal confirm:
After — one place chip; recents as pairs, Places only when there is a choice, browse straight into the listing:
Evidence
node scripts/run-vitest.mjs ui/src/pages/new-session— 11 files, 74 passed (includes newplace-picker.test.tscovering recents dedupe/cap/workspace-skip/unknown-node-skip).node scripts/run-vitest.mjs ui/src/e2e/new-session-page.e2e.test.ts— 32 passed, including three new tests: destination axis hidden for a single-place Gateway (with the runs-on note), a recent (folder, node) pair applied in one click and asserted in thesessions.createpayload, and browse-root back returning to the place menu (button and Escape).gpt-5.6-sol) ran to clean across three cycles; the accepted findings (destination-axis visibility under failed node discovery, admin-gate hiding an existing selection, missing root-menu scroll region) are all fixed in this diff.canSubmit, cloud recovery, worktree forcing, branch-token discipline) are untouched; the change is presentation/interaction plus two small visibility-predicate fixes.renderFolderSelect,renderWhereSelect,folder-browser.ts, ~580 lines) collapsed into oneplace-picker.tsmodule;new-session-page.tsshrank 1,417 → 1,362 lines.