Skip to content

improve(ui): unify new-thread folder and where pickers into one place picker#112035

Merged
steipete merged 3 commits into
mainfrom
steipete/storage-selector-design-1cb535
Jul 21, 2026
Merged

improve(ui): unify new-thread folder and where pickers into one place picker#112035
steipete merged 3 commits into
mainfrom
steipete/storage-selector-design-1cb535

Conversation

@steipete

Copy link
Copy Markdown
Contributor

What Problem This Solves

Resolves a set of interaction traps in the new-thread draft's "where does this thread run" controls:

  • The decision is one value — a (destination, folder) pair — but the UI split it across two chips ("Folder" and "Where") with separate popovers.
  • The folder popover opened a target-list panel ("Where" header) even when Gateway · local was 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.
  • The "Run on" menu chip rendered even when there was nothing to choose.
  • There was no way to restore a recently used folder/machine combination; every draft started from scratch.

Why This Change Was Made

One primitive instead of two: a single place chip (openclaw · Gateway · local) opens a single popover with stack navigation.

  • Root view: workspace row, recent places (derived from the session list — each row restores folder and destination in one click), a browse row, a Places section, and the worktree controls (a folder-axis concept, now grouped with folders).
  • Progressive disclosure: Places renders only when there is a real choice (nodes or cloud profiles discovered) or an existing selection. With only the Gateway, the menu shows a quiet "Runs on Gateway · local" note instead of a one-option picker. An existing node/cloud selection always keeps the destination axis visible, even if discovery fails or auth degrades — the chip can never misreport a remote-targeted draft as local.
  • Never a dead end: browsing opens directly in the current destination's listing (the target-list panel is deleted); the back button walks up directories and then returns to the root menu; Escape inside the browser pops one level instead of closing the popover.

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

  • Unit: node scripts/run-vitest.mjs ui/src/pages/new-session — 11 files, 74 passed (includes new place-picker.test.ts covering recents dedupe/cap/workspace-skip/unknown-node-skip).
  • E2E (mock gateway, Playwright): 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 the sessions.create payload, and browse-root back returning to the place menu (button and Escape).
  • Structured review (Codex 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.
  • All submission invariants (canSubmit, cloud recovery, worktree forcing, branch-token discipline) are untouched; the change is presentation/interaction plus two small visibility-predicate fixes.
  • Net prod LOC is negative: the two-popover plumbing (renderFolderSelect, renderWhereSelect, folder-browser.ts, ~580 lines) collapsed into one place-picker.ts module; new-session-page.ts shrank 1,417 → 1,362 lines.

… 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.
@steipete
steipete marked this pull request as ready for review July 21, 2026 03:19
@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui scripts Repository scripts size: XL maintainer Maintainer-authored PR labels Jul 21, 2026
@clawsweeper

clawsweeper Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

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

clawsweeper Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

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

clawsweeper Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

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.

@steipete
steipete merged commit 94b3345 into main Jul 21, 2026
102 checks passed
@steipete
steipete deleted the steipete/storage-selector-design-1cb535 branch July 21, 2026 05:00
@steipete

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 21, 2026
… 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui maintainer Maintainer-authored PR scripts Repository scripts size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant