Skip to content

feat(ui): view tab strip with keep-alive and open-in-tab links (RIG-4444) - #1755

Merged
trunk-io[bot] merged 7 commits into
compass-ui/rig-4443-window-layoutfrom
compass-ui/rig-4444-tab-strip
Oct 7, 2026
Merged

trunk-io[bot] merged 7 commits into
compass-ui/rig-4443-window-layoutfrom
compass-ui/rig-4444-tab-strip

Conversation

@rigel-mintaka

@rigel-mintaka rigel-mintaka commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

This PR is part of a stack containing 7 PRs:

  1. main
  2. refactor(ui): extract parseRoute and add ViewScope with useView (RIG-4439) #1652
  3. refactor(ui): move routed surfaces and agent-workspace state onto the view scope (RIG-4442) #1675
  4. feat(ui): window layout model, hash sync and session persistence (RIG-4443) #1743
  5. "feat(ui): view tab strip with keep-alive and open-in-tab links (RIG-4444)" (this PR)
  6. feat(ui): W leader chords and palette commands for tabs and panes (RIG-4445) #1770
  7. feat(ui): two-pane split with a resizable splitter (RIG-4446) #1780
  8. fix(ui): chrome cleanup: drop ADE and usage bar, Session Log naming, pane edges, row re-measure (RIG-4771) #1811

Tabs T4 of docs/designs/ui/compass-in-window-tabs/design.md §T4 (RIG-4444), stacked on T3 #1743.

  • components/TabStrip.tsx + design/components/tab-strip.css:
    • A .cx-tab-strip[role=tablist] over store.layout(). It dispatches only LayoutActions: focusTab, close (the close button or Delete), and move (drag).
    • Arrow keys, Home and End rove through createRovingGroup in the topbar zone. Agent tabs lead with a StateDot.
  • route-title.ts: routeTitle (§A3) gives tab labels and document.title.
  • App.tsx, keep-alive (§A4):
    • The tab strip replaces nav.view-tabs.
    • Each view instance gets one [role=tabpanel], which wraps its ViewHost.
    • Inactive panels are hidden and stay mounted. Focus moves into the shown view, to its last-focused element, before the old view hides.
    • .view-panel takes over sizing from .main, so view bodies don't move.
  • open-link.ts (OQ-2): a plain click navigates in place, as before. Mod+click and middle-click dispatch open. This is wired on the sidebar tree, channel, topic and nav rows, the Bridge swimlane gutters, and the right-sidebar "Open agent" buttons.
  • Bridge registers its board.*/list.* commands only while its view is focused. A cleanup removes only the registration it added. This fixes the case where closing one of two Bridge tabs dropped the other tab's commands.
  • store.ts: exposes viewScopes. Adds channelPath and topicPath, so the in-place and new-tab paths are the same.

Readings:

  • There is one ViewHost per view instance, so split panes stay alive too.
  • Roving focus never activates a tab; Enter or a click does.
  • Delete on a focused tab closes it.

Two topbar Bridge-tab tooltip tests were deleted from App.test.tsx. §A7 removes the pinned Bridge tab, and the sidebar Bridge link keeps its own chord-tooltip test.

Review fixes (de33726 → 624e1da, four rounds, now clean)

  • A redirect from a hidden view applies to its own view, not the focused one.
  • Closing a tab leaves focus on the new active tab.
  • Focus only lands on visible, focusable elements; otherwise on the panel (tabindex=-1).
  • An 11th tab shows a notice (§A3). It is an inline chip in the topbar after the strip, in an always-mounted role=status region, with a repeat counter, Dismiss and a 5s timeout. The timeout pauses while the chip has focus or hover and keeps pausing through a window blur. When the chip unmounts with focus inside it, focus returns to the active tab.
  • The topbar search fills its flex box (240px, shrinking to 180px), so it no longer overflows onto the daemon pill when the strip is full.
  • A conversation mounted while hidden scrolls to the latest message on its first show only. Later tab returns keep the user scroll position.
  • Remembered focus targets must still be focusable; each focus move is checked, with fallback to a candidate, then the panel.
  • Every view of the active tab is shown, ready for T6 splits.
  • Backspace closes a tab on mac.
  • Middle-button mousedown is cancelled, so no autoscroll.
  • Bridge drops each of its commands before re-registering it.

Close buttons stay in the tablist; it is the usual closable-tabs pattern, and each has a label.

Visual baselines

These shots are local captures under the pinned dev shell, per DL-399 (#1644). The baseline commit depends on #1644 merging first.

  • tab-strip: a new shot.
  • agent: a refresh. Only the topbar row changes, because one agent tab replaces Bridge + agent. I checked agent-diff.png: no body pixels moved.

All other baselines are unchanged.

Tests

  • New: TabStrip.test.tsx (6), tab-keep-alive.test.tsx (5, including two Bridge tabs where one closes), and a 6-case LeftSidebar open-modes block. All were red first.
  • New e2e e2e/tab-strip.spec.ts: a draft survives switching tabs and back, and both tabs restore after a reload.
  • moon run compass-ui:test: 1270 pass, 0 fail. Typecheck, stylelint and biome are clean.
  • Playwright visual-smoke (13) + dev-boot + tab-strip all pass.

Spec-impact: none.
Ledger-impact: none

Co-authored-by: Matt Wilkinson matt@rigel.build

rigel-mintaka and others added 2 commits October 5, 2026 19:30
…444)

Replaces the topbar view nav with a tab strip over the window layout. Every
view stays mounted while hidden, focus moves into the shown view first, and
Mod+click or middle-click on sidebar and board links opens a new tab.

Co-authored-by: Matt Wilkinson <matt@rigel.build>
…4444)

Local captures under the pinned dev shell per DL-399 (#1644): tab-strip is
a new shot, and agent changes only in the topbar row.

Co-authored-by: Matt Wilkinson <matt@rigel.build>
@linear-code

linear-code Bot commented Oct 5, 2026

Copy link
Copy Markdown

RIG-4444

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Compass engineering docs preview: https://compass-ui-rig-4444-tab-stri.compass-eng-docs.pages.dev

Deployed from compass-ui/rig-4444-tab-strip at 624e1da.

rigel-mintaka and others added 5 commits October 5, 2026 21:02
…b cap (RIG-4444)

Co-authored-by: Matt Wilkinson <matt@rigel.build>
…p (RIG-4444)

Co-authored-by: Matt Wilkinson <matt@rigel.build>
…hile focused (RIG-4444)

Co-authored-by: Matt Wilkinson <matt@rigel.build>

test(ui): type the focused-tab assertion (RIG-4444)

Co-authored-by: Matt Wilkinson <matt@rigel.build>
Co-authored-by: Matt Wilkinson <matt@rigel.build>
… (RIG-4444)

Co-authored-by: Matt Wilkinson <matt@rigel.build>
@trunk-io

trunk-io Bot commented Oct 7, 2026

Copy link
Copy Markdown

This pull request is queued for merge as part of 1798, which will merge 1652, 1675, 1743, 1755, 1770, 1780, 1787, 1798.

@trunk-io
trunk-io Bot merged commit 04278b6 into main Oct 7, 2026
18 checks passed
@trunk-io
trunk-io Bot deleted the compass-ui/rig-4444-tab-strip branch October 7, 2026 04:16
@trunk-io

trunk-io Bot commented Oct 7, 2026

Copy link
Copy Markdown

This pull request was merged into main as part of stacked PR 1798.

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