TUI: group sidebar cards by project, collapsible #124
Closed
opened 2026-08-25 12:18:23 +01:00 by naps62-yolo
·
0 comments
No Branch/Tag Specified
main
chorale
upbeat
tritone-2
fermata-4
android-app/271-theme-apk
blitz/android-app
android-app/270-command-bar
android-app/268-app-shell
android-app/267-structured
android-app/266-terminal
android-app/269-spawn-form
android-app/265-sidebar
android-app/264-daemon-connection
android-app/263-api-client
android-app/262-project-scaffold
rhapsody
dominant-2
animato-2
glockenspiel
septet
mandolin
chord
timbre-2
aeolian
cello-2
allegro
lento
lyre
maestoso
cadence-3
modulation-2
modulation
xylophone-2
tuba-2
piccolo-2
grazioso-2
grazioso
hymn
xylophone
blitz/react-tailwind-migration
254-design-kit-react
253-delete-vanilla-wire-react
issue/252-tests-rtl
issue/242-daemon-link-react
issue/240-types-api-router
issue/251-preview-mode-react
issue/250-dialogs-drawer-react
issue/249-layout-system-react
247-command-bar-react
issue/248-spawn-dialog-react
246-structured-pane-react
issue/245-terminal-pane-react
244-sidebar-react
issue/243-theme-tokens-tailwind
issue/241-catalog-connection-zustand
issue/239-scaffold-react-tailwind
timpani
staccato-2
trombone-2
grave-2
harpsichord-2
recorder-4
vivace
sotto
tuba
chaconne
etude
arpeggio
harpsichord
cadence-2
brillante
clarinet
snare-2
staccato
recorder-2
tritone
balalaika
timbre
violin
fix/web-nix-build
blitz/codex-structured-sessions
codex-structured-sessions/203-tui-spawn
codex-structured-sessions/202-web-spawn
codex-structured-sessions/201-codex-lifecycle
codex-structured-sessions/200-select-acp-adapter
blitz/structured-view
vivo
structured-view/199-command-resolution
structured-view/198-viewport
structured-view/197-lock-order
structured-view/196-concurrent-handshakes
structured-view/195-autoscroll
structured-view/194-plan-row
structured-view/193-expanded-reconnect
structured-view/192-pty-gate
structured-view/143-spawn-structured
structured-view/191-accurate-diffs
structured-view/190-web-tool-state
structured-view/189-tui-approval-failure
structured-view/188-web-submit
structured-view/187-tui-spawn-race
structured-view/141-tui-structured
structured-view/140-web-structured
structured-view/186-unknown-update-doc
structured-view/185-lock-order
structured-view/184-approval-persist
structured-view/142-structured-activity
structured-view/137-structured-docs
fix/codex-attach-scroll
structured-view/139-permission-requests
structured-view/138-structured-api
structured-view/136-transcript-projection
structured-view/183-dismissal-race
structured-view/182-natural-exit-race
structured-view/181-recovery-provenance
structured-view/180-shutdown-create
structured-view/179-shutdown-drain
structured-view/177-restart-worktree
structured-view/178-pid-safe
structured-view/135-event-log
structured-view/134-acp-subprocess
10-umbrella-feature-gate-tests
structured-view/133-session-view
contrabass
fermata
interlude
crescendo
reboot/173-timing-assert
reboot/169-tui-dormant
blitz/reboot-resilience
reboot/171-scrollback
reboot/176-session-id-refresh
reboot/175-resume-races
reboot/168-web-dormant
reboot/174-bootid-strand
reboot/167-resume-policy
reboot/166-resume-route
reboot/172-worktree-field
reboot/164-boot-id
reboot/165-resume-command
reboot/163-prune-sidecars
tuplet
reboot/162-dormant
reboot/161-agent-session-id
sarabande
glissando
blitz/command-bar
legato
command-bar/159-web-leader-config
command-bar/157-touch-entry
command-bar/158-literal-leader
command-bar/156-tui-literal-ctrlk
command-bar/155-tui-drillin
command-bar/151-web-drillin
command-bar/154-tui-sigils
command-bar/152-web-pane-ctrlk
command-bar/150-web-sigils
command-bar/153-tui-bar
aubade
command-bar/147-rust-matcher
dominant
command-bar/149-web-bar
command-bar/145-daemon-focus
command-bar/146-ts-matcher
command-bar/148-web-registry
harmony
command-bar/144-contract
coda
oboe
accordion
snare
feroce
cantabile
fix/tui-daemon-url-resolution
haiky
activity
shortcuts
dorian
symphony
colors
flugelhorn
andante
trombone
organ
scherzo
duduk
sostenuto
lullaby
moderato-motif
largo-piano
moderato-bassoon
lento-sonata
animato-trumpet
largo-lute
feroce-violin
grazioso-viola
sostenuto-bassoon
crescendo-rondo
refresh
marcato-nocturne
brillante-fugue
forte-lyre
rename
themes
blitz/tui-shell
issue/124-project-groups
issue/122-theme-presets
issue/123-focused-panels
issue/121-tui-line2
issue/120-web-line2
issue/119-bare-maestro-tui
issue/118-palette-roles
issue/117-path-helpers
issue/116-sidebar-contract
blitz/sidebar-cards
sidebar-cards/115-fourth-flake
sidebar-cards/114-hook-error
sidebar-cards/113-more-flakes
sidebar-cards/106-hooks-install
sidebar-cards/112-detail-render
sidebar-cards/111-flaky-retention
sidebar-cards/105-activity-endpoint
sidebar-cards/110-lenient-activity
sidebar-cards/108-tui-cards
sidebar-cards/107-web-cards
sidebar-cards/104-activity-clock
sidebar-cards/103-session-env
sidebar-cards/102-activity-wire
sidebar-cards/101-sidebar-contract
blitz/spawn-v2
spawn-v2/97-enter-submits
spawn-v2/94-labels
spawn-v2/96-tui-picker
spawn-v2/93-collapse-worktree
spawn-v2/98-flake-ci
spawn-v2/95-project-picker
spawn-v2/74-gitroot-debounce
spawn-v2/76-preset-reset
spawn-v2/73-draft-pane-swap
spawn-v2/91-wt-toggle-default
spawn-v2/92-form-width
spawn-v2/70-fastforward-key
spawn-v2/72-opendraft-reuse
spawn-v2/75-projects-ttl
blitz/worktree-lifecycle
wl/83-blocked-work
wl/88-e2e-lifecycle
wl/87-drop-cleanup-flag
wl/82-natural-exit
wl/84-web-worktrees
wl/81-force-retains
wl/85-tui-worktrees
wl/86-cli-worktrees
wl/79-kill-guard
wl/80-worktrees-api
wl/77-worktree-collisions
wl/78-retained-store
spawn-v2/67-fastforward
spawn-v2/66-e2e
spawn-v2/65-tui-worktree
spawn-v2/68-draft-teardown
spawn-v2/62-drop-modal
spawn-v2/64-tui-fields
spawn-v2/61-wt-defaults
spawn-v2/53-names
spawn-v2/55-branches
spawn-v2/59-projectlist
spawn-v2/54-projects
spawn-v2/60-autocomplete
spawn-v2/63-tui-draft-pane
spawn-v2/56-worktree-place
spawn-v2/58-tui-textinput
spawn-v2/57-draft-pane
nix
refactor
dev-environment
linear/nap-228-daemon-recover-leaves-stale-tmux-pipe-pane-attach-shows-no
No results found.
Projects
Clear projects
No projects
No Assignees
No due date set.
Depends on
#117 Share the path-abbreviation helpers with Rust clients
naps62/maestro
#121 TUI: render line 2 on every session card
naps62/maestro
#123 TUI: make the focused panel unmistakable
naps62/maestro
Reference: naps62/maestro#124
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The web sidebar groups sessions into collapsible directory folders; the TUI renders one flat list. At more than a handful of sessions the flat list stops being scannable, and the two clients stop describing the same machine.
Give the TUI sidebar a single layer of grouping: one group row per project, its sessions as cards beneath it. Single layer means exactly that — no nesting. Where the web builds a tree and folds linear chains, the TUI groups by the same key and shows the result as one row.
Grouping key. The same rule the web uses in
sessionTreePath: the worktree'sbase_repowhen present, else the session's cwd. A worktree session lands under its repository rather than in a group of its own.Group label. The abbreviated path from #117, matching the web exactly —
~/git.naps.pt/naps62/maestroreads~/g/n/maestro. Style the collapsed stem dim and the last segment normal, using the palette roles. Also show the group's session count, as the web's folder rows do.Collapsing. Group rows are collapsible and remember their state across redraws, as
collapseddoes inweb/src/catalog.ts:19. A collapsed group hides its cards and keeps its count visible.Navigation is where the work is.
visible_sidebar_orderincrates/maestro-tui/src/app.rs:884mapsj/kto aVec<Uuid>of sessions, which no longer describes what is on screen: group rows are focusable too, since collapsing one needs a highlight to act on. The highlight becomes a position in the rendered row sequence rather than a session id, and everything readingAppState::sidebar_highlighthas to follow —session_under_highlight(app.rs:403) returns nothing when a group row is highlighted, and the actions bound to a highlighted card (attach, kill, spawn similar) must do nothing rather than act on a neighbouring session. Collapsing a group that contains the highlight must leave the highlight somewhere sensible, not pointing into hidden rows.Mouse.
RegionMapresolves a click toRegion::SidebarRowand the router maps the row to a session. That mapping now has to account for group rows and hidden cards; a click on a group row toggles it.Cards stay exactly two lines each (#121), which keeps the row-to-item arithmetic tractable — one group row plus two rows per visible card. Do not reintroduce variable-height cards to make this easier.
Tests: grouping puts a worktree session under its base repo, a repo with no sessions produces no row, collapse hides cards and keeps the count,
j/kwalk group rows and cards in visual order, a highlighted group row yields no session for the session-scoped actions, and collapsing the group containing the highlight leaves the highlight on a visible row.Non-goals: no filter or search box, no nesting beyond one layer, and no change to how the web groups. Sorting can follow the web's existing order rather than inventing one.
Depends on: #117, #121, #123