Repository navigation
Conversation
An opt-in toggle in the Home sessions header switches the list between the existing date groups and per-project groups. Project groups show the project's avatar and name, order by most recent session, resolve worktree and sandbox sessions to their parent project, and collapse individually. Grouped rows drop the per-row project suffix; search results keep it. The mode and collapsed groups persist per user. Refs anomalyco#55446
The project group header's avatar and name started further right than the session rows below it, so the tree read inverted. The header chevron now sits in a fixed-width column and grouped rows indent by the same column, aligning each row's avatar under its group's project avatar in both normal and rename layouts.
An opt-in Settings > General preference clusters session tabs under their project in the tab strip, in both horizontal and vertical layouts, like browser tab groups. Group headers show the project avatar and name and collapse individually per window; collapsed members leave the visible-tab cycle. Membership derives from each tab's session directory (or the draft's directory), so groups need no management: the grouped view is a stable partition of the persisted order and drag-reorder pauses while grouping is on, restoring the user's own order when off. Refs anomalyco#51759
…ped drag Groups now key by the resolved project instead of the session directory, so worktree, sandbox, and draft tabs join their project's group instead of splitting it. Horizontal groups badge with a stable project color and member tabs carry it as an accent strip; vertical groups drop the per-tab project avatar (the header names the project), shrink their headers to 20px, and gain an on/off toggle on the panel that shares the Settings preference. Drag and drop works while grouped: dragging a header reorders its whole project and dragging a tab reorders it within its group, with cross-group drops snapping back.
Adds reorder tests for the boundary contracts the review flagged: a tab dropped at a foreign group boundary is rejected, a tab dragged to its group's first and last slot reorders it, and a header drop that leaves the header order unchanged is a no-op. Documents the one-frame visibility window in the sortable sequence and the vertical/horizontal header design split.
Horizontal tab groups show a compact one-character badge — the project mark in the group color — with the project name on hover; the tooltip wraps the badge mark because the header's own expanded state suppresses tooltips on its trigger. Grouping toggles use the standard 16px icon, matching the New session affordances they sit beside. Home project headers compress to 20px with 11px labels and the grouped rows pack close: one pixel of lead-in and 8px between groups.
The badge's hover tooltip rendered Kobalte's div trigger inside the group header button, which the HTML content model forbids. Tooltip gains a triggerAs option and the badge passes "span", keeping the trigger phrasing content. Declined with rationale: the post-click tooltip block is the component's behavior on every tooltipped control, and the badge avatar stays aria-hidden because the button's aria-label carries the name.
Contributor
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 72 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
Contributor
|
Thanks for putting this together, @liambreen. The grouping logic, tests and screenshots are really thorough! At ~950 changed lines (not counting tests), this is too big to review well as one pull request. It also contains two features that work on their own. Could you split it into smaller, focused pull requests? For example:
You're welcome to open those, and you can link back here and to #55446 for context. |
3 of 6 tasks
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.
Sessions and tabs grouped by project, opt-in on both surfaces.
Summary
Two default-off features, both driven by feedback in #55446 and #51759:
1. Group session tabs by project (
Settings → General → Group tabs by project)Session tabs cluster under per-project headers in the tab strip, in both horizontal and vertical layouts — like browser tab groups. All three strip mounts (titlebar, vertical sidebar, mobile drawer) share the implementation.
Membership is derived from data, never managed by hand: each tab resolves through the project inventory (loaded session → persisted
tabs.infofallback; drafts → their directory), so worktree and sandbox tabs join their parent project's group instead of splitting it. Group ids include the server, so the same path on two servers stays separate. Unresolvable tabs trail the groups unheadered.Drag and drop keeps working while grouped: dragging a header reorders its whole project (collapsed members follow); dragging a tab reorders it within its group. Cross-group drops snap back — a tab cannot change projects by dragging. The grouped view is a stable partition of the persisted tab order, so turning grouping off restores the user's own arrangement exactly.
Group colors use the project's own icon color when set, otherwise a stable per-group hash onto the non-gray avatar palette, exposed via a
data-project-variantattribute so badges and tab accents reuse the avatar tokens.Tooltipgains atriggerAsoption: the horizontal badge's hover-name needs a trigger inside a button, which Kobalte's defaultdivtrigger would make invalid HTML, and wrapping the button itself would trip the tooltip component's expanded-disclosure suppression.2. Group Home sessions by project
A folder-icon toggle in the Home search row switches the sessions list between the existing date groups and per-project groups: collapsible compact (20px) headers, groups ordered by most recent session, rows packed tight and indented under their header's chevron column. Grouped rows drop the per-row project suffix (search results keep it — that list spans projects). Mode and collapsed state persist per user.
Closes #55446. Refs #51759 (this clusters the strip; that issue's "projects as top-level tabs" IA is a larger change).
Screenshots
Tab groups, horizontal — one-char badges, color-matched accent strips:
Horizontal badge with the project name on hover:
Tab groups, vertical — compact headers, icon-free rows, panel toggle:
Vertical with one group collapsed:
Home sessions grouped by project:
Implementation notes
shell/titlebar/tab-groups.ts(partition, identity, variant hashing, constrained reorder) andhome/sessions/grouping.ts(Home partition).Indexso group rebuilds never recreate tab slots mid-gesture, and a sequence memo mirrors the rendered order to keep sortable indexes and drag results in sync with the DOM.reorderGroupedStripreturns the full key order orundefinedto snap back), reusing the existingonReorderpath; ungrouped drag behavior is untouched.Testing
tabs.spec.tsgains clustering/collapse/cycle-skip/reload cases plus a pointer-driven drag case (within-group reorder, header-drag group swap, cross-group snap-back) in both layouts;home.spec.tsgains the toggle/order/collapse/persistence case with compact-header assertions;settings.spec.tsgains the preference row case.bun run checkis green at HEAD; app and ui typechecks green. On this dev machine the only failing keepers are five keybind-driven tests that fail identically ondev(mac chromium environment; they pass in CI's Linux runner).Notes for review