feat(app): SessionDetail polish + library-feed home#128
Merged
Conversation
b7da818 to
26a7f6e
Compare
…ta quality - Sidebar: full-width search trigger, collapsible PROJECTS, sync+settings at bottom, hide 0-session projects - LibraryLanding: replace project card grid with global Pinned + Recent feed (Today/Yesterday/Earlier This Week/Earlier buckets); rows show project name - SessionRow: optional showProject prop for cross-project context - ProjectView: drop redundant SearchTrigger from header (sidebar owns it) - Hide compact-bar SearchBar when ProjectView active (was showing both) - Window size 1180x780 (was 960x620) - Filter empty (0-message) sessions from listRecentSessions / listSessionsByIdentity / listPinnedSessions / listPinnedSessionsByIdentity - New listPinnedSessions core query + spool:list-pinned-sessions IPC for global pinned feed
- in:project scope actually filters: thread identityKey through searchFragments + spool:search IPC - Search results header shows scope label (in <project> / all projects) - Cmd+K overlay: agent selector slot appears when Agent mode active - Cmd+K overlay: clickable "View all results" footer with ⇧↵ shortcut hint - LibraryLanding + ProjectView: section headers (PINNED / TODAY / RECENT / etc.) collapsible; hover reveals chevron - Sidebar PROJECTS toggle: chevron next to label, hover-only - ProjectView header: project path below title in subdued mono - SessionRow: action group aligned to first line; Menu adds "Copy resume command" - New Menu component (reusable dropdown with click-outside + esc handling) - e2e: helpers use search-trigger click; agent / project-view sort / fast-search updated for new UI
Live FTS in the overlay correctly filtered by identityKey, but doSearch (invoked by "View all results" / Shift+Enter) called window.spool.search without the scope arg. Result: scope chip said "in <project>" but the results page showed sessions from every project. Now doSearch reads searchScope + activeProjectKey and passes scopedKey through, matching the overlay's behavior.
Replaces two-row stack (path / title+meta+actions) with a clean single row: back · source chip (● claude) · title · pin · Resume · ⋯, plus a subdued meta line (path · N messages · time) below. Right-side actions now vertical-center with the title instead of bottom-aligning under a stacked block. - Source chip uses short label + color dot; model dropped (noisy) - Copy ID / Copy resume command moved into ⋯ menu - MessageBubble x-padding bumped to px-6 so avatars align with back arrow - e2e updated for the new actions menu
- FragmentResults: replace native <select> sort with Menu (matches ProjectView)
- SearchOverlay: render Tab as a <kbd> chip ("Tab to switch")
- Sidebar: outline folder icon prefix on each project row
- PinButton (sm): shrink button to w-6 h-6, icon to 11px (less heavy next to ⋯)
- SessionRow ⋯: preventDefault on mousedown so click doesn't keep focus —
fixes pin/⋯ staying visible after clicking the menu and moving the cursor
- LibraryLanding: tighten header (pt-5, text-xl, smaller subtitle) so it
aligns with the sidebar wordmark and fills less empty space
Sidebar wordmark, LibraryLanding header, ProjectView header, and SessionDetail header now all start at the same vertical position. Previous mix of pt-5 / pt-6 left noticeable empty bands at the top of each pane and made the sidebar and main pane look misaligned.
… actions Sidebar listProjectGroups was only fetched at mount, so newly-indexed sessions never showed up in project counts until the user reopened the window. Now re-fetches on every sync phase change — cheap (single SQL query) and lets the user watch counts climb during indexing. SessionDetail header: source chip moves from row 1 (next to title) to the end of the meta line. Right-side action group (pin / Resume / ⋯) pulled out of the title row and pinned with self-end so its baseline aligns with the meta line, not the title — gives the title room to breathe and groups the actions visually with the second-row metadata.
…inline - PinButton: replace tilted clipboard-pin glyph with Tabler-style angled pushpin (head + diagonal shaft + tip). Cleaner at small sizes. - Standardize icon sizes onto a 9 / 11 / 13 / 14 / 16 scale: bump the 10px overlay arrow to 9 (matches sort caret), trim the 12px overlay mode toggles + session-detail back to 11 (matches small actions). - Sidebar status text: drop the verbose 'Synced N ago · X sessions' template — green dot already conveys synced state. Now reads 'X sessions · 5m' (count first, short relative time, no 'ago'), fits comfortably even with 6-digit counts. - ProjectView source filter: collapse the separate pill row into the meta line. Source labels themselves become toggle buttons; non-active sources dim to 40% opacity, default state (no filter) shows all at full opacity. Saves one row of vertical space and removes redundant display of source names twice.
Settings → General → Sidebar gains two toggles, both default on: - Show source dots (the colored CLI indicators on each project row) - Show session count (the trailing number on each project row) Both flags persist on AgentsConfig (the existing JSON-backed user prefs on disk), so they roam across app restarts. Avoid a flicker on Settings open: GeneralTab now waits for getAgentsConfig before rendering instead of seeding from default values and then animating the toggles to their real state. Sidebar bottom is restructured: settings moves from a full-width row to a compact icon button right of the sync status line. The whole status footer is now one row: green dot + 'X sessions · 5m' on the left, gear icon on the right. Gear sized down to 12px with warm-faint color so it visually matches the status text instead of competing with it.
…count column Hide the sidebar list scrollbar entirely (scroll-by-wheel/trackpad still works) — same pattern as Linear/Notion/Slack nav. Reserved scrollbar gutter looked like an unsightly empty band; auto-toggling gutter caused content to shift when the list grew or shrank. With no gutter at all, the right edge is stable and clean. Settings gear now sits at pr-1.5 in the bottom row. Math: project row count's right edge is 16px from the container right (px-2 of scrollable + px-2 of button). With pr-1.5 (6px) + the gear button's centering (half of (24-12)=6) + the SVG's internal whitespace, the gear's visual right edge lands roughly at the count column's right edge — slightly right of perfectly mathematical alignment, which reads better given the icon's optical weight.
…ht, refined pill
- show recent sessions (scope-aware) in empty query state, Notion-style
- stabilize body height with min-h/max-h range so mode/scope toggles don't jitter
- mode-aware placeholder ('Search…' vs 'Ask anything…') to guide users
- move agent selector to scope row; Tab hint anchored to scope chips
- keep input focus when opening agent menu (mousedown.preventDefault)
- redesign SegmentedPill: drop border/shadow, accent-tinted active, a11y roles
- export bucketSessionsByDate helper for overlay reuse
05a324b to
7463b74
Compare
This was referenced Apr 30, 2026
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.
Why
Once the rest of the stack landed and the team started dogfooding, three pain points emerged together:
in:projectscope was a real bug. The chip was plumbed through the UI in the search-migration PR, but the IPC handler ignored theidentityKeyargument — search returned global results regardless of what the user picked.Bundling them keeps each diff small while letting reviewers see the design pass as one cohesive change.
What this PR does
SessionDetail — header + actions
path · N messages · time · ● source(source dot+label moved here from a separate chip; saves vertical space and groups all metadata)self-end): Pin · Resume in Terminal · ⋯MessageBubblerows pad topx-6so message avatars line up with the back arrowLibrary home — global feed
Sidebar shell
<count> sessions · <relative>(e.g.420 sessions · 5m)scrollbar-none) — Linear/Notion-style; kept overlay scroll behavior for trackpadsproject_groups_vwhenever sync phase changes, so newly-synced projects appear without a manual reloadCmd+K overlay polish
in:projectis selected) bucketed by date — Notion-stylemin-h-[220px] max-h-[min(420px,55vh)]body so the overlay doesn't jitter when toggling Fast/Agent or scope, and doesn't get absurdly tall on small windowsrole="tablist"+aria-selectedin:project↔ All togglemousedown.preventDefaultso opening the menu doesn't steal focus from the input — Tab keyboard nav keeps working after closing the menuin:projectIPC fix — the missing piece.searchFragmentsand the IPC handler now accept and apply theidentityKeyarg;doSearchpasses it through when committing from the overlay; the results page header displays the active scope so the user can verifyPin + ProjectView refinements
PinButtonredrawn (Tabler-style angled pushpin) with two sizes — md (16px in detail) and sm (11px in rows) so it doesn't out-weigh adjacent ⋯ menusMenucomponent asFragmentResults, for consistencyAlignment + small polish
pt-3 px-6across panes so the sidebar wordmark, project header, library feed title, and session detail all start at the same vertical positionmousedown.preventDefaultso a click doesn't keep focus and leave the action group stuck visibleMenucomponent (reusable dropdown with click-outside + escape handling)Test plan
pnpm --filter @spool/app exec playwright test— all suites pass