Activity sidebar, project selectors, and the end of tabs - #40
Conversation
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>
|
Polish round (eb0657e), per wing's feedback:
🤖 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>
|
Two more fixes (45eceef):
🤖 Generated with Claude Code |
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>
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>
…h-project-selectors Activity sidebar, project selectors, and the end of tabs







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 @ devicewith 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.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_tabsis legacy, no longer read).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.Sessions without a project. The project picker's "Don't work in a project" row mints sessions with no project:
createChatnow takes an optionalspaceId+deviceId, the chat's cwd is stored as~and expanded on the host when the run spawns. They show as~ @ devicein the sidebar (first shot, third row).Refs are fixed at creation. Existing sessions can no longer change refs — the mid-session
switchRefpath 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 —
Spacerows,createSpace/renameSpaceops etc. keep their names, so no migration.Engine changes
Mutate createChat:spaceIdoptional, new optionaldeviceId(host for project-less chats); cwd defaults to~when no project.sessions::dispatch_innerexpands~/~/…against the host's home before resume-scoping and spawn.Notes
last_space_idrestore.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.