Skip to content

refactor(app): share the workspace submenu with the missing-location menu - #55665

Merged
Brendonovich merged 5 commits into
devfrom
workspace-submenu
Oct 17, 2026
Merged

Brendonovich merged 5 commits into
devfrom
workspace-submenu

Conversation

@Brendonovich

@Brendonovich Brendonovich commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Summary

Moves the new-session picker's "Existing workspace" submenu into a shared WorkspaceSubmenu component (packages/app/src/workspaces/submenu.tsx) and uses it in the "Choose worktree" menu shown when a session's directory is missing.

The move also changes some behavior:

  • The search field (shown with 10 or more workspaces) stays pinned while the workspace list scrolls under it, and "View all" stays pinned at the bottom.
  • Arrow Up/Down in the search field move focus to the last or first workspace in the list.
  • The search clears when the submenu closes.
  • New optional disabled and onViewAll props cover menus that block selection while busy or have no "View all" page.
  • Opening the submenu by click or keyboard reliably focuses the search field. Kobalte autofocuses the submenu's content or first item a tick after it opens, which could take focus from the old double-requestAnimationFrame focus. The submenu now sends that focus back to the search field until the pointer moves into the submenu or the user arrows out of the field. Opening it by hover still leaves focus alone.

Missing-location "Choose worktree" menu

  • "New worktree" stays at the top level. Existing worktrees move into the shared "Worktree" submenu, with disabled={move.isPending} and no "View all". This adds search for 10+ worktrees, where the old menu was a flat max-h-80 list without search.
  • Worktree rows use outline-worktree instead of workspace-isolated and no longer show a full-path title tooltip.
  • The "Loading" row stays at the top level while the first worktree list is empty.

Before / After

Desktop web, 1280×640, new-session draft with 14 worktrees.

Before After
Submenu open Worktree submenu at the top of its list Worktree submenu at the top of its list with View all pinned
Scrolled to the end Worktree submenu scrolled to its end with View all cut off Worktree submenu scrolled with search and View all pinned

Testing

  • packages/app: bun typecheck
  • packages/app: e2e/regression/session-location-sync.spec.ts and e2e/regression/new-session.spec.ts (23 passed). The missing-location recovery test now opens the "Worktree" submenu first.
  • Ran a temporary focus check 4 times against both menus, with 14 worktrees, opening by click, keyboard, hover then click, and hover alone (32/32 passed). It checked that the search field gets focus and that filtering and arrow-key movement work. Before the fix, opening the missing-location menu by click lost search focus in 3 of 5 runs.

@Brendonovich
Brendonovich requested a review from Hona as a code owner October 15, 2026 08:47

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extraction looks right, and bun typecheck passes in packages/app. I couldn't run the app here (there's no browser), so I checked it by reading the code, including Kobalte's menu focus handling. Before/after screenshots or a short clip of the submenu with 10+ workspaces would help, especially arrow-key navigation through a long list.

Public API: unchanged. WorkspaceSubmenu is internal to packages/app.

One likely regression, explained inline: when the list overflows, arrow-key navigation probably no longer scrolls the focused workspace into view.

/>
</div>
</Show>
<div ref={list} data-slot="workspace-submenu-list" class="min-h-0 overflow-y-auto overscroll-contain">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably breaks keyboard scrolling for long lists. Kobalte moves focus between menu items with focusWithoutScrolling, then scrolls only the menu content element: scrollIntoView(ref, item) in createSelectableCollection, and MenuContentBase passes no separate scrollRef. Before this change, SubContent was overflow-y-auto, so that call scrolled it. Now SubContent is overflow-hidden and never overflows, because this inner div does the scrolling. Arrowing past the ~9 visible workspaces would move focus to items that stay out of view.

The native .focus() in the search field's ArrowUp/Down handler does scroll, but every arrow press after that wouldn't. Could you scroll this list into view when the focused item changes, for example with onFocusIn calling scrollIntoView({ block: "nearest" }) on the target?

@opencode-agent opencode-agent Bot changed the title refactor(app): extract the workspace submenu refactor(app): share the workspace submenu with the missing-location menu Oct 15, 2026
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