Skip to content

Resolve deferred review items from split tab groups#227

Merged
parsakhaz merged 1 commit into
mainfrom
fix/split-tabs-deferred-followups
Jun 12, 2026
Merged

Resolve deferred review items from split tab groups#227
parsakhaz merged 1 commit into
mainfrom
fix/split-tabs-deferred-followups

Conversation

@parsakhaz

Copy link
Copy Markdown
Member

Description

Closes out every remaining deferred item from the #224 review rounds (the should-fixes went out in #225, the strip drop gap is #226):

  1. Background-tab close kept your current tab (VS Code behavior): the close handler picked a successor active tab even when the closed tab was not the active one. Now gated on group.activePanelId === panel.id.
  2. Layout persist flushes on beforeunload: the 500ms debounce only flushed on session switch/unmount, so a split followed by an immediate quit lost the layout. The debounce timer also now calls flushLayoutPersist instead of duplicating its body.
  3. role="tablist" on secondary strips: their role="tab" children previously had no tablist container (the primary strip gets one from PanelTabBar).
  4. Stored sizes sync after n-ary inserts: Allotment's defaultSizes is mount-only, so dropping a tab as a new sibling in an existing split left on-screen sizes diverged from the stored model until the next sash drag. onChange now keeps a per-split snapshot in a ref (no re-renders), and a child-count change syncs the model from it once. Sash behavior is unchanged (persist still happens on drag end only).
  5. Unit tests for the layout tree math: 44 vitest tests covering normalize (id stability, flattening, size renormalization), splitGroup (wrap + n-ary), movePanel (center reorder incl. the index-adjustment cases, edge drops, sole-tab safety), reconcile (prune/dedupe/orphan adoption/focus+zoom repair), updateSizes, directional focus geometry, and dropZoneFor. Adds vitest to the frontend workspace (same ^2.1.8 as main) and a frontend test step to the quality workflow.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Test improvement

Checklist

  • My code follows the code style of this project
  • I have performed a self-review of my own code
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have run pnpm typecheck and pnpm lint locally

Critical Areas Modified

  • State management (layout persist path)

Additional Notes

The remaining flagged items are deliberate tradeoffs, not fixed: Windows/Linux Ctrl+\ is the split hotkey so it no longer reaches the PTY as SIGQUIT there (macOS preserved in #225), and the first split / last un-split remounts the surviving group per the pixel-identical single-group rule.

Addresses the remaining deferred suggestions from the PR 224 review
rounds:

- closing a background tab no longer switches the group's active tab;
  a successor is picked only when the closed tab was active (VS Code
  behavior)
- pending layout writes flush on beforeunload, so a split made just
  before quit is not lost to the 500ms debounce; the debounce timer
  now reuses flushLayoutPersist instead of duplicating it
- secondary group strips get role=tablist to match their role=tab
  children (the primary strip already had one via PanelTabBar)
- after an n-ary sibling insert into an existing split, the stored
  model syncs once from Allotment's live sizes (defaultSizes is
  mount-only, so on-screen and stored sizes diverged until the next
  sash drag)
- add a vitest suite for the pure tree math in panelLayout.ts
  (44 tests: normalize, splitGroup, movePanel, reconcile, geometry,
  drop zones) and run frontend unit tests in the quality workflow

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ec1cb5e0d0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Flush a pending layout write before the window closes: the debounce would
// otherwise lose a split made just before quit.
useEffect(() => {
window.addEventListener('beforeunload', flushLayoutPersist);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Flush layout from the quit path

When the user quits the app via the app-level quit flow, this beforeunload hook is bypassed by the existing shutdown path: main/src/index.ts prevents app.before-quit at line 1200 and later calls app.exit(0) at line 1419 instead of closing the BrowserWindow, so the renderer can be terminated without a beforeunload event. In that split-then-quit scenario the layout can still remain only in pendingLayoutRef; trigger the flush from the main quit flow or explicitly close the window after the pending write has completed.

Useful? React with 👍 / 👎.

@parsakhaz parsakhaz merged commit fa61f9f into main Jun 12, 2026
4 checks passed
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.

1 participant