Skip to content

Activity sidebar, project selectors, and the end of tabs - #40

Merged
wingleeio merged 21 commits into
mainfrom
comet/activity-sidebar-with-project-selectors
Aug 10, 2026
Merged

Activity sidebar, project selectors, and the end of tabs#40
wingleeio merged 21 commits into
mainfrom
comet/activity-sidebar-with-project-selectors

Conversation

@wingleeio

@wingleeio wingleeio commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Sidebar/composer restructure (t3 code-inspired), building on #14's spaces dropdown.

What changed

Sidebar is activity-first. Rows follow the t3 code card anatomy: line 1 is project @ device with a colored status word top-right (Working with live spinner / Input / Failed / Done — relative time when idle), line 2 the title, line 3 the harness mark + branch. The header dropdown filters by project (ported from #14, now labeled All projects), and the header + is New session — project creation moved into the dropdown's "New project…" row.

Activity sidebar with project @ device rows and status words

Horizontal tabs are gone. The titlebar names the selected session — harness icon + title, left-aligned. When the sidebar collapses, the new-session + fades into the titlebar riding the same width tween (UiSettings.open_tabs is legacy, no longer read).

Collapsed sidebar: + button and session title in the titlebar

Two new selectors under the composer. A device selector (defaults to the last selected device) and a project selector (defaults to the last selected project), persisted in composer-defaults.json. Checkout + ref chips only appear when a git project is selected, with checkout to the left of ref.

Project selector with New project and Don't work in a project rows Device selector

Sessions without a project. The project picker's "Don't work in a project" row mints sessions with no project: createChat now takes an optional spaceId + deviceId, the chat's cwd is stored as ~ and expanded on the host when the run spawns. They show as ~ @ device in the sidebar (first shot, third row).

No-project canvas: device + No project, no checkout/ref chips

Refs are fixed at creation. Existing sessions can no longer change refs — the mid-session switchRef path is deleted and the session footer renders read-only checkout/ref labels. Refs (and checkout kind, device, project) are chosen on the new-session canvas only.

Spaces → projects in all user-facing copy ("All projects", "New project…", "Search projects…", onboarding). Internal identifiers and the synced doc schema are untouched — Space rows, createSpace/renameSpace ops etc. keep their names, so no migration.

Engine changes

  • Mutate createChat: spaceId optional, new optional deviceId (host for project-less chats); cwd defaults to ~ when no project.
  • sessions::dispatch_inner expands ~/~/… against the host's home before resume-scoping and spawn.

Notes

  • Builds on Device-local tabs + spaces as a searchable sidebar filter #14 (merged into this branch); that PR's device-local-tabs half is superseded by removing tabs entirely — closing it in favor of this.
  • Boot lands on the most recent session (the old pre-tabs behavior); the "Don't work in a project" opt-out survives restarts and wins over last_space_id restore.
  • 382 UI + all engine tests pass; screenshots from the headless demo rig, hosted as user content (not in the repo).

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

wing-anara and others added 17 commits August 4, 2026 08:42
Tabs detach from session existence: a tab is a device-local viewport
onto a synced session (UiSettings.openTabs, the vec is the order).
Closing a tab is local-only — the session keeps running and stays in
the sidebar, where a click reopens it; archiving stays an explicit
sidebar-row action. The strip goes cross-space and gains a context
menu (close / close others / close left / right). Old files migrate
by seeding openTabs from the last space's sessions.

Spaces stop being a navigation spine: the sidebar section becomes a
searchable dropdown (ref-picker recipe) with "All spaces", filtering
only the session list and hosting space management. The new-session
canvas gains a space picker chip defaulting to the sidebar filter,
else the last selected space; picking a space re-keys the ref
selector and harness/model catalogs through the existing
selected_space observer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The label now flexes, so long space names ellipsize against the
trigger width instead of pushing the caret out of the row.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
anchored_menu pins to the trigger's top-left, which covered the
button. New anchored_menu_below primitive pins the floating layer to
the trigger's bottom edge — a dropdown proper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The selected row's wash (menu_row active styling) is the selection
signal; the trailing check fought the @device tag for the row end.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The selected row's wash (menu_row active styling) is the selection
signal everywhere — ref/checkout/model pickers, the canvas space
picker, and the account device menu — matching the space-filter
dropdown. menu_check retires with its last caller.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-down

Dropdowns/menus previously vanished the frame their state dropped. Every
menu state is now a popover::Popup<T> with an exit phase: close paths
funnel through a begin_close that keeps the card mounted ~100ms playing
menu-out (fade + 2px lift, interactivity deadened), then a reap timer
drops the state.

The exit progress reads the Popup's closing instant at render time
rather than with_animation's element-state clock — that clock replays
from 0 on a missed frame, which flashed the dying menu back to full
opacity. The frosted backdrop blur ignores element_opacity, so its
radius rides the same progress down to zero instead of popping off at
unmount.

Also: clicking an open trigger now just closes its menu (the outside-
click dismissal no longer immediately reopens via the same click), the
same just-dismissed guard the user menu already carried.

Converted: spaces filter dropdown, user menu, session/tab/space context
menus, composer pickers, settings device menu. The @-mention completion
stays instant on purpose (keystroke-driven dismissal would read as lag).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The host device was only visible inside the space pickers' rows. The
sidebar filter trigger now shows it right after the space name (caret
stays at the right edge), and the composer's space chip shows it as the
muted suffix — amber "· offline" when the host's heartbeat is stale,
same as the rows. Formatting shared via AppState::space_device_tag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both the sidebar filter dropdown and the composer space picker listed
spaces in sync-arrival order. They now share AppState::spaces_sorted
(case-insensitive by display name, id tie-break): search still ranks
prefix matches first — alphabetical within each rank — and the picker's
opening highlight indexes the sorted order.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…met/activity-sidebar-with-project-selectors

# Conflicts:
#	crates/ui/src/pickers.rs
#	crates/ui/src/state.rs
… open_kind() accessors

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…awn); UI state grows device pick + no-project opt-out

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Device picker (defaults to last selected, persisted in composer-defaults) and
project picker with New project… / Don't work in a project rows. Checkout+ref
chips only render for git projects, checkout left of ref. Existing sessions
get read-only labels — the mid-session switchRef path is gone. Project-less
sends mint the chat on the picked device with cwd ~.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-first

Titlebar (chat route) now shows harness icon + session title with a new-session
+ that fades in as the sidebar collapses. Sidebar header + mints sessions (project
creation moved into the dropdown); rows read 'project @ device' with a t3-style
status word (Working/Input/Failed/Done) top-right, time when idle. Boot lands on
the most recent session; open_tabs is legacy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r project/device

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r status text

- Status corner: medium-weight text with a check glyph on Done (t3code look);
  hovering a row swaps it for an Archive button (t3code settle-on-hover).
- New-session + loses its active wash.
- Device popover gains the search box; 'Don't work in a project' wears an x.
- Session footer always names device (+ project when the session has one) as
  read-only labels beside the locked checkout/ref pair; project label absent
  on project-less sessions.
- Boot canvas defaults follow a set sidebar filter (project AND its device),
  beating last-selected and the no-project opt-out.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wingleeio

Copy link
Copy Markdown
Contributor Author

Polish round (eb0657e), per wing's feedback:

  • Status text restyled — medium weight, check glyph on Done; hovering a row swaps the status/time for an Archive button (t3 code's settle-on-hover):

    Restyled status text and always-visible session footer labels Archive button on row hover
  • Device + project are always visible under the composer on sessions too — read-only labels beside the locked checkout/ref pair (wing-mbp · comet … Local checkout · main above). Project label is omitted when the session has no project.

  • Device popover gains a search box; "Don't work in a project" wears an ×; the new-session + lost its active wash:

    Project popover with icons Device popover with search
  • Sidebar filter drives canvas defaults: with a project filter set, a new session defaults to that project and its device (beats last-selected and the no-project opt-out).

🤖 Generated with Claude Code

…over only

The collapsed-sidebar new-session + now renders inside the control cluster
(same 24px slot, same 2px rhythm) instead of floating 10px off it, and the
session title budgets one button slot as it fades in. The sidebar row's
Archive button now appears only when the STATUS CORNER itself is hovered —
hovering the row body keeps the status word readable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wingleeio

Copy link
Copy Markdown
Contributor Author

Two more fixes (45eceef):

  • Titlebar + spacing — the collapsed-sidebar new-session + now renders inside the window-control cluster (same 24px slot, same 2px gap as sidebar/back/forward) instead of floating 10px off it:

    + aligned with the control cluster
  • Archive is corner-hover only — hovering the row body keeps the status word readable; the swap happens only over the status/time itself:

    Row body hover: status stays Corner hover: Archive

🤖 Generated with Claude Code

Wing and others added 2 commits August 10, 2026 16:11
createChat over the UI's exact wire shape (deviceId, no spaceId) lands a
space-less chat row with cwd ~, the run spawns from the expanded home dir,
and no phantom space row is minted — the two pre-#40-engine failure modes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The conversation loses its inset card: the transcript spans the full window
height, scrolling under the glass titlebar and a frosted (backdrop-blurred)
composer, fading per-pixel at both chrome edges (gpui fork: per-edge fade
bands, per-pixel EdgeFade for quads/images, Porter-Duff window alpha,
object-fit tile-UV cropping — pins bumped to a5b59b5).

Sidebar: t3code's settled-shelf port for archived sessions (slim rows,
hover-swapped Unarchive, Show-more paging, open by default), row-hover
archive swap, muted non-done status colors with dots (spinner rides the
row's bottom-right), no Sessions header, no selection ring.

New-session canvas: device + project selectors under the logo (device-
scoped project picker), checkout left / ref right in the footer, no
titlebar text; sessions title as "name /project @ device". Working loader
lives under the streaming reply. Offline reads as a wifi-off glyph.
Transcript attachments shield from image-cache eviction while mounted;
cover-fit thumbnails round via their own radii.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wingleeio
wingleeio merged commit 59e65a9 into main Aug 10, 2026
1 check passed
guilhermexp pushed a commit to guilhermexp/comet that referenced this pull request Aug 30, 2026
createChat over the UI's exact wire shape (deviceId, no spaceId) lands a
space-less chat row with cwd ~, the run spawns from the expanded home dir,
and no phantom space row is minted — the two pre-zeronsh#40-engine failure modes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
guilhermexp pushed a commit to guilhermexp/comet that referenced this pull request Aug 30, 2026
…h-project-selectors

Activity sidebar, project selectors, and the end of tabs
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.

2 participants