Skip to content

feat: DH-22800: Support Intersection 2D Window Resizing#2701

Open
SimonVutov wants to merge 9 commits into
deephaven:mainfrom
SimonVutov:DH-22800-Support-Intersection-2D-Window-Resizing
Open

feat: DH-22800: Support Intersection 2D Window Resizing#2701
SimonVutov wants to merge 9 commits into
deephaven:mainfrom
SimonVutov:DH-22800-Support-Intersection-2D-Window-Resizing

Conversation

@SimonVutov

@SimonVutov SimonVutov commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Changes

  • Adds 2D intersection resizing in Golden Layout by introducing an invisible intersection handle at splitter crossings.
  • Uses the existing horizontal and vertical splitter drag logic together: one drag moves both splitters, then applies both size updates atomically on drag stop.
  • Reuses existing splitter highlight styling so both crossing lines stay highlighted on hover and during drag (VS Code-like affordance), with proper z-index layering.
  • Fixes handle positioning by computing crossing points from bounding-rect centers (offset-parent safe), so nested intersections are reliably grabbable.
  • Supports deeply nested crossings by recursively discovering perpendicular splitters that reach the shared edge, not just immediate children.
  • Fixes nested drag artifacts by stretching the stem line with CSS transform scale (paint-only) instead of mutating layout width/height, preventing content/tab reflow.

Validation

  • intersection-drag tests: 9/9 passing: tests in packages/golden-layout/src/__tests__/intersection-drag.test.ts

Demo (23s mov video):

2026-06-24.10-35-43.mov

Other Information

The splitter lines are width 10px, and this intersection handle is a square of side length 14px. this._hitAreaSize = Math.max(this._grabSize, 14);
Each crossing gets an invisible square handle element and it is centered exactly on the crossing point: It uses _getIntersectionPosition to get the intersection position and places the handle centered there with slightly higher z index than splitter lines so that it has priority over them.

@SimonVutov SimonVutov self-assigned this Jun 15, 2026
@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 63.36088% with 133 lines in your changes missing coverage. Please review.
✅ Project coverage is 51.39%. Comparing base (37b079e) to head (7431a81).
⚠️ Report is 15 commits behind head on main.

Files with missing lines Patch % Lines
packages/golden-layout/src/items/RowOrColumn.ts 61.22% 133 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2701      +/-   ##
==========================================
+ Coverage   50.49%   51.39%   +0.90%     
==========================================
  Files         788      795       +7     
  Lines       44923    45574     +651     
  Branches    11447    11618     +171     
==========================================
+ Hits        22682    23422     +740     
+ Misses      22222    22133      -89     
  Partials       19       19              
Flag Coverage Δ
unit 51.39% <63.36%> (+0.90%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI 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.

Pull request overview

Adds 2D “intersection” resize handles to Golden Layout so users can drag diagonally at row/column splitter crossings to resize both axes together (DH-22800).

Changes:

  • Add IntersectionSplitter control (2D drag handle) and export it from controls.
  • Extend RowOrColumn to create/refresh intersection handles and apply drag updates for both the parent splitter and a perpendicular child splitter.
  • Add styling + Jest coverage for intersection handle creation and drag behavior.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/golden-layout/src/items/RowOrColumn.ts Creates/positions intersection handles and wires diagonal drag to existing 1D splitter logic.
packages/golden-layout/src/controls/IntersectionSplitter.ts New 2D splitter control backed by DragListener.
packages/golden-layout/src/controls/index.ts Re-exports IntersectionSplitter.
packages/golden-layout/src/tests/intersection-drag.test.ts Adds tests covering diagonal drag + handle persistence across refreshes/drags.
packages/golden-layout/scss/goldenlayout-dark-theme.scss Dark theme styling for intersection handle visibility/hover/drag states.
packages/golden-layout/scss/goldenlayout-base.scss Base styling + cursor override while intersection-dragging.

Comment thread packages/golden-layout/src/items/RowOrColumn.ts
Comment thread packages/golden-layout/src/items/RowOrColumn.ts Outdated
Comment thread packages/golden-layout/src/controls/IntersectionSplitter.ts
@SimonVutov SimonVutov force-pushed the DH-22800-Support-Intersection-2D-Window-Resizing branch from b54162a to 5cb5501 Compare June 24, 2026 14:30
@SimonVutov SimonVutov requested review from dsmmcken and mofojed June 24, 2026 14:36
@SimonVutov SimonVutov marked this pull request as ready for review June 24, 2026 14:41

@dsmmcken dsmmcken 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.

2d drag, over another splitter triggers it and it gets stuck hovered;
Image

I wonder if we could detect 4-way corners, with a bit of fuzziness (like if the 4th corner is +/- 5px or 10px or whatever), and make them a 4-way drag (that leaves it snapped perfectly aligned on drop)?

Image

Didn't review JS, will leave to someone else to review that.

Comment on lines +42 to +45
.lm_intersection_dragging,
.lm_intersection_dragging * {
cursor: move !important;
}

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.

Doesn't actually do anything, pointer-events none means cursor wont trigger, and the pointer-events none is needed to prevent interaction with other elements while dragging.

Comment on lines +93 to +103
z-index: 59;
}
}

// Intersection splitter: an invisible grab area at grid crossing points that
// enables simultaneous (2D) resizing of rows and columns. The visible drag
// affordance is the two perpendicular splitter lines themselves, which are
// highlighted (via .lm_dragging) on hover and while dragging.
.lm_intersection_splitter {
position: absolute;
z-index: 60;

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.

these z-indexes look sus.

Comment on lines +136 to +141
// Intersection splitter (2D grid resize). The grab area is invisible; the drag
// affordance is the two perpendicular splitter lines, which reuse the standard
// .lm_splitter.lm_dragging highlight above.
.lm_intersection_splitter {
background: transparent;
}

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.

Does nothing, transparent by default.

@SimonVutov SimonVutov requested a review from dsmmcken June 25, 2026 17:16

@mofojed mofojed left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Need to make sure the JSDocs on these functions include all parameters and are up to date. Should also add a couple e2e tests

There's still some odd behaviours in some scenarios.

  1. When dragging from a 1D splitter and then dragging over a intersection point, it changes lights up the whole cross for a moment and then all the highlights disappear as you drag away; however when you drop the change still occurs
    https://github.com/user-attachments/assets/f65b9284-077c-4b10-97d0-c845c4d3cd0a

  2. When dragging a column in the grid, then dragging over an intersection point, the cursor changes and the splitters highlight unnecessarily. (I would have thought this wouldn't be possible because I thought the grid turns off pointer events for the document when a column drag is occurring).
    https://github.com/user-attachments/assets/f0397b7f-412d-44c8-b757-b037131e7e7b

I like the feature though, great work overall.

item: AbstractContentItem | undefined,
nearEdge: boolean,
path: string,
out: {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't like using an out parameter like this. Why not just return an array of the splitters?

* crossing handle can be created for it. Lines can be nested arbitrarily deep,
* so descend until the edge is no longer shared.
*
* @param nearEdge true when the bar sits at the start of `item` along the bar

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

JSDocs need to be updated

@SimonVutov SimonVutov requested a review from mofojed July 3, 2026 16:10
return (
$(document.body).hasClass('lm_dragging') ||
$(document.body).hasClass('lm_intersection_dragging') ||
document.documentElement.classList.contains('grid-block-events')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

golden-layout should not depend on grid, or any grid specific class.
I don't think this is actually needed for anything? Just remove this grid-block-events check.

@SimonVutov SimonVutov requested a review from mofojed July 3, 2026 19:23
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.

4 participants