Skip to content

Add equal-grid snapping for split panes - #2488

Merged
brsbl merged 15 commits into
bb/fix-tab-split-actions-thr_q8degf2y66from
bb/split-resize-snap-targets-thr_q8degf2y66
Aug 27, 2026
Merged

Add equal-grid snapping for split panes#2488
brsbl merged 15 commits into
bb/fix-tab-split-actions-thr_q8degf2y66from
bb/split-resize-snap-targets-thr_q8degf2y66

Conversation

@brsbl

@brsbl brsbl commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Why

Users usually want a newly created split to return to equal-sized panes, but free resizing makes that canonical grid hard to recover precisely. This layer adds one shared equal-grid interaction to tab, page/thread, and thread/right-panel dividers without removing arbitrary sizing.

User-visible behavior

  • Two siblings snap to halves, three to thirds, four to quarters, and larger sibling groups use the same equal-grid rule.
  • Nested row and column split nodes own their grids independently; there is no diagonal snapping.
  • Approaching within 12 px—or crossing a target during a fast drag—captures the equal boundary.
  • Once captured, the divider holds through a 30 px release band. A second consecutive out-of-band sample confirms release after coarse pointer movement.
  • A temporary full-span guide marks the active equal boundary.
  • The behavior applies to right-panel tab splits, workspace page/thread splits, and the center divider between a thread and its right panel.
  • Existing 15–85% bounds and arbitrary post-release sizes remain available.

Reliability and performance

  • Grid and divider geometry are read once when a drag begins; pointer movement uses cached geometry.
  • Center, tab, page, and thread dividers share the same free → captured → released state machine and resistance thresholds.
  • The center-divider bridge previews adjacent flex sizes locally and commits once through the panel API on release, matching the internal split path.
  • Release, cancellation, lost pointer capture, a zero-button sample, window blur, replacement drag, and unmount all clear the guide and resize state.

Screenshot evidence

All captures use Chrome for Testing 151.0.7922.71 at the same 1440×900 CSS viewport (DPR 2), the same one-file Split tab UX verification fixture, and one coarse pointer jump that crosses the equal boundary by 80 px. The before revision is exact parent head 1dbfc83bd587b98968d6b0a839da9f81751ce3b9; the after revision is exact PR head a128a9917ffe49588cb2c84d573f01113834e5a6.

Thread / right-panel divider

Before, the fast crossing follows the sampled pointer past center and leaves an arbitrary-width right panel with no guide.

Before: center divider misses the equal grid

After, the same crossing holds at 50/50 and renders a full-height guide through the owning split.

After: center divider captures the equal grid

Vertical tab split

Before, the stacked Diff/Info divider lands 80 px beyond the equal-height boundary with no guide.

Before: vertical tab split misses equal heights

After, the same crossing holds both panes at equal heights and renders the full-width horizontal guide.

After: vertical tab split captures equal heights

Validation

  • Capture manifests record the exact parent/head revisions above, identical fixture and viewport, zero rendered error states, no guide and an 80 px overshoot before this layer, and exact 50/50 geometry with the correct axis-spanning guide after it.
  • Regression coverage in this layer targets equal boundaries for multiple sibling counts and both axes, fast-crossing capture, shared 12/30 px hysteresis, confirmed coarse-sample release, center-divider single-writer behavior, persistence, and cleanup on every drag terminator.
  • Tests, typechecks, lint, and other CI-equivalent checks run on the pull request through GitHub Actions; none were run locally for this screenshot audit.

BB-Thread-ID: thr_q8degf2y66

AGENT GENERATED: by GPT-5.6-Sol

@brsbl
brsbl force-pushed the bb/split-resize-snap-targets-thr_q8degf2y66 branch from 0d39493 to 074e03f Compare August 26, 2026 22:26
@brsbl
brsbl force-pushed the bb/split-resize-snap-targets-thr_q8degf2y66 branch from 074e03f to 956030f Compare August 27, 2026 00:17
@brsbl brsbl changed the title Add split resize snap targets Snap split resizing to a midpoint grid Aug 27, 2026
@brsbl

brsbl commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator Author

Closing this feature layer because split-resize snapping has been cut from the stack. PRs #2486 and #2487 remain unchanged.

@brsbl brsbl closed this Aug 27, 2026
@brsbl brsbl reopened this Aug 27, 2026
@brsbl brsbl changed the title Snap split resizing to a midpoint grid Add magnetic split grid snapping Aug 27, 2026
@brsbl

brsbl commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator Author

Reopened after correcting the interaction model: this now uses one shared midpoint grid per split surface with fast-crossing capture and magnetic release hysteresis.

@brsbl brsbl changed the title Add magnetic split grid snapping Add magnetic midpoint snapping for split panes Aug 27, 2026
@brsbl brsbl changed the title Add magnetic midpoint snapping for split panes Add equal-grid snapping for split panes Aug 27, 2026
@brsbl
brsbl force-pushed the bb/split-resize-snap-targets-thr_q8degf2y66 branch from eb95481 to a128a99 Compare August 27, 2026 20:54
@brsbl

brsbl commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator Author

@slopcop Please review the full native PR stack #2486#2487#2488. The screenshot evidence has been audited and refreshed against each layer’s exact merge-base or parent-head and PR-head revisions, using matched fixtures and viewports throughout.

@bb-slop-cop

bb-slop-cop Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

🚨 SLOP COP 🚨 · review

I am SlopCop. I will review this pull request against the configured guidelines.

I will check security, code quality, performance, architecture, duplication, tests, and user behavior.

I will post one final report after the parallel checks finish.

@brsbl
brsbl force-pushed the bb/split-resize-snap-targets-thr_q8degf2y66 branch from a128a99 to 4796c42 Compare August 27, 2026 23:47
@SawyerHood
SawyerHood force-pushed the bb/split-resize-snap-targets-thr_q8degf2y66 branch from 4796c42 to 2aeab61 Compare August 27, 2026 23:50
@brsbl
brsbl merged commit c9922f5 into main Aug 27, 2026
15 checks passed
@brsbl
brsbl deleted the bb/split-resize-snap-targets-thr_q8degf2y66 branch August 27, 2026 23:55
moveEvent.stopPropagation();
const nextPointer =
axis === "x" ? moveEvent.clientX : moveEvent.clientY;
const result = snapSession.resolve({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚨 slopcop/review — The panel adapter applies the wrong size limits.

The shared resolver limits the leading panel to 15%–85%. These panels require 30%–76%, plus a collapsed state.

The adapter blocks the panel library's move events. Thus, the panels cannot reach their collapse thresholds.

A browser check showed a 15% preview. The panel then jumped to 24% after release.

Pass the panel limits and collapse rules into this path. Add tests for both limits and both collapse directions.

};
const commitDrag = () => complete(true);
const cancelDrag = () => complete(false);
const finishForPointer = (finishEvent: PointerEvent) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚨 slopcop/review — A pointer cancellation saves a temporary size.

pointercancel calls the commit path. The custom split dividers restore the original size after a cancellation.

Route this event to cancelDrag. Add a test that restores both flex values and preserves the panel state.

@bb-slop-cop bb-slop-cop Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚨 SLOP COP 🚨 · review

Plain English summary

This change makes a divider pause at equal pane sizes. It adds the same guide and resistance to inner splits and right panels.

Findings

  1. High — The right-panel adapter uses the generic 15%–85% split limits.

    The panels require 30%–76%, plus a collapsed state. The adapter also blocks the panel library's move events.

    Thus, a user cannot collapse either panel with a drag. Extreme previews also jump to a valid size after release.

  2. Medium — A pointercancel event commits the temporary preview.

    A browser or device can cancel a pointer action. This event must restore the original size, as the custom dividers do.

Other review results

I found no security problem. I also found no new performance problem in the pointer-move path.

Three resize paths repeat pair state and release logic. A shared drag-session helper could keep their behavior consistent.

Verification

  • The Turbo type check for @bb/app passed.
  • The five focused test files passed all 99 tests.
  • The full app suite passed 3,477 tests. Nine failures occurred in unchanged test files.
  • A Chrome check reproduced both findings on the real right-panel handle.
  • The final GPT-5.6 review gate confirmed both findings and returned REQUEST CHANGES.
  • The author rebased the branch during this review. The two affected feature files remained identical.

Please fix both regressions before merge. I posted this as a comment-only review, as required.

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