Repository navigation
feat(tabs): arrange the tab strip by work folder or by status - #835
Open
Jonathan-Asher wants to merge 2 commits into
Open
Jonathan-Asher wants to merge 2 commits into
Jonathan-Asher wants to merge 2 commits into
Conversation
An "Arrange tabs" button beside the new-conversation button offers three layouts, remembered per device: - Manual order: drag to reorder, exactly as before. - Group by work folder: each folder's tabs sit together behind a chip in the folder's color, and each tab carries a thin top border in that color. Folders without a color get a stable automatic one, so every group can be told apart. - Sort by status: sessions waiting for you (a permission request, a question, or a plan awaiting approval) come first, then those awaiting your reply, then running ones, then the rest. Each band is labeled and colored like the tabs' status dots. "Waiting for you" is read on the client from each tab's live ACP connection (its pending permission, question, ask-question and plan-approval state), so a tab moves into that band as soon as a prompt appears and leaves it once the prompt is answered. The other bands follow the conversation status the tabs already show. The arrangement is display-only: the manual order and its persistence are untouched and come back as they were. Dragging is off while a derived layout is shown, and every strip, split groups included, follows the same choice.
dawNotPoi
reviewed
Sep 25, 2026
dawNotPoi
left a comment
Contributor
There was a problem hiding this comment.
I found one active-tab visibility regression in the new arrangements.
| ) | ||
| const attentionByTabId = useTabAttention(attentionTabIds) | ||
| const arranged = useMemo( | ||
| () => arrangeTabs(groupTabs, arrangeMode, attentionByTabId), |
Contributor
There was a problem hiding this comment.
When the strip overflows, changing Manual → Group by work folder can move the selected tab outside the visible area while its ID stays the same. The existing scrollIntoView effect below depends only on displayActiveId, so it does not run for this new order (the same happens when an active tab changes status/attention). The active tab then appears to disappear until another tab is selected. Please also react to changes in the active tab's displayed position / arrangement; a regression test can switch modes with a fixed active ID and assert that it remains visible.
The strip scrolled the active tab into view only when the active id changed. A derived layout moves the selected tab without changing its id: switching Manual to "Group by work folder" or "Sort by status", or the active tab changing status band (a prompt appearing or being answered). On an overflowing strip it could then land outside the visible area and look gone until another tab was selected. The reveal now also runs when the arrangement mode changes and, outside manual order, when the active tab's displayed slot changes. Manual order still keys on the id only: there the active tab moves only under the user's own drag, and the strip should not scroll mid-gesture. It runs as a layout effect, so it measures the new layout before the tabs' layout animation shifts moved tabs back toward their old spots for the first frame. tab-bar.test.tsx switches modes with a fixed active id, moves the active tab across status bands, and checks that neither another tab's band change nor a manual reorder scrolls the strip.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an "Arrange tabs" menu to the conversation tab strip with three layouts, remembered per device:
Behavior
rawTabs, persisted viasave_opened_tabs) is never rewritten, so switching back to Manual restores exactly the dragged order. Dragging (in-strip and cross-group) is off while a derived layout is shown; the trigger is tinted then.pendingPermission,pendingQuestion,pendingAskQuestion,pendingPlanApproval) through a newuseTabAttentionhook — a tab enters the band as soon as a prompt appears and leaves it once answered. Subscriptions exist only while Sort by status is active, and the map keeps its identity across streaming updates, so a busy session doesn't re-render the strip per token.pending_review/in_progress), colored like the status dots.Folder.tabsin all 10 locales.Verification
src/lib/tab-arrangement.test.ts— grouping, status bands, attention derivation, folder colors.src/hooks/use-tab-attention.test.tsx— maps blocked tabs, follows a prompt arriving and being answered, no re-render on streaming-only changes, unsubscribes on unmount.