Skip to content

Splitpane mouse drag feature#2322

Open
desireddymohithreddy0925 wants to merge 5 commits into
Karanjot786:mainfrom
desireddymohithreddy0925:splitpane-mouse-drag-feature
Open

Splitpane mouse drag feature#2322
desireddymohithreddy0925 wants to merge 5 commits into
Karanjot786:mainfrom
desireddymohithreddy0925:splitpane-mouse-drag-feature

Conversation

@desireddymohithreddy0925

@desireddymohithreddy0925 desireddymohithreddy0925 commented Jul 10, 2026

Copy link
Copy Markdown

Description

This PR fully implements interactive mouse dragging for the SplitPane layout widget in @termuijs/widgets. Previously, users could only resize the panes if the widget had terminal focus by holding Shift+Arrows. This commit introduces a handleMouse listener that dynamically tracks the divider's cell coordinates and manages a _dragging state machine across mousedown, drag, and mouseup events, allowing fluid, continuous mouse adjustments to the layout ratio.

Related Issue

Closes #2261

Which package(s)?

@termuijs/widgets

Type of Change

  • 🐛 Bug fix (type:bug)
  • ✨ Feature (type:feature)
  • 📝 Docs (type:docs)
  • 🧪 Tests (type:testing)
  • ♻️ Refactor (type:refactor)
  • 🎨 Design / UX (type:design)
  • ♿ Accessibility (type:accessibility)
  • ⚡ Performance (type:performance)
  • 🔧 DevOps / CI (type:devops)
  • 🔒 Security (type:security)

Checklist

  • ⭐ You starred the repo. The needs-star check blocks your merge otherwise.
  • Tests pass locally: bun vitest run
  • Build passes: bun run build
  • Typecheck passes: bun run typecheck
  • You read CONTRIBUTING.md.
  • Your PR title follows type: short description.
  • Widget state mutators call markDirty() (if your change affects rendering).
  • No new any types without an inline comment explaining why.
  • No unrelated refactors bundled into this PR.

GSSoC 2026 Participation

  • You are a GSSoC 2026 contributor.
  • Your GSSoC profile: https://gssoc.girlscript.org/profile/YOUR_PROFILE_ID_HERE

Screenshots / Recordings (UI changes)

Notes for the Reviewer

The coordinates are dynamically derived inside handleMouse rather than caching absolute values, ensuring that the drag interaction area remains perfectly accurate even if the terminal window is resized mid-drag!

Summary by CodeRabbit

  • New Features
    • Added mouse-based divider dragging to split panes.
    • Users can now resize horizontal and vertical panes by dragging the divider.
    • Pane proportions remain within their supported limits during resizing.

@github-actions github-actions Bot added the area:widgets @termuijs/widgets label Jul 10, 2026
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@desireddymohithreddy0925, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 37 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c8af1b09-dc90-43c6-81cf-786811751aae

📥 Commits

Reviewing files that changed from the base of the PR and between ee6ff32 and 864362e.

📒 Files selected for processing (1)
  • packages/widgets/src/layout/SplitPane.ts
📝 Walkthrough

Walkthrough

SplitPane now supports mouse-based divider dragging, deriving direction-specific ratios from pointer movement and reusing existing ratio clamping.

Changes

SplitPane divider dragging

Layer / File(s) Summary
Divider mouse interaction
packages/widgets/src/layout/SplitPane.ts
Adds drag state and handles left-button divider presses, pointer movement, and drag termination while updating _ratio through the existing clamping behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: type:feature, level:intermediate

Suggested reviewers: Karanjot786

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is clear and related to the change, though it is not in the repo's preferred type: short description format.
Description check ✅ Passed The description includes the change summary, linked issue, package, change type, checklist, GSSoC section, and reviewer notes.
Linked Issues check ✅ Passed The diff adds the draggable SplitPane mouse interaction requested in #2261, and the existing keyboard behavior is preserved.
Out of Scope Changes check ✅ Passed The change is scoped to SplitPane mouse dragging and does not ցույց any unrelated refactors or extra feature work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/widgets/src/layout/SplitPane.ts (2)

104-104: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Import MouseEvent at the top of the file instead of using an inline import.

The file already imports KeyEvent, Screen, and other shared types from @termuijs/core. Using import('@termuijs/core').MouseEvent inline is non-idiomatic and inconsistent. As per coding guidelines, shared types should be imported from @termuijs/core.

♻️ Proposed refactor

Add MouseEvent to the existing import from @termuijs/core at the top of the file:

-    handleMouse(event: import('`@termuijs/core`').MouseEvent): void {
+    handleMouse(event: MouseEvent): void {

And update the top-level import (adjust to match the existing import statement):

-import { type KeyEvent, type Screen, ... } from '`@termuijs/core`';
+import { type KeyEvent, type MouseEvent, type Screen, ... } from '`@termuijs/core`';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/widgets/src/layout/SplitPane.ts` at line 104, Import MouseEvent
alongside the existing KeyEvent, Screen, and other symbols from `@termuijs/core`,
then update SplitPane.handleMouse to use the imported MouseEvent type instead of
the inline import.

Source: Coding guidelines


107-133: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Deduplicate the horizontal and vertical branches.

The two branches are structurally identical, differing only in axis (x/width vs y/height). Consolidating them reduces maintenance burden and the risk of the branches diverging.

♻️ Proposed refactor
     if (width <= 0 || height <= 0) return;
 
-    if (this._direction === 'horizontal') {
-        const dividerX = x + Math.floor(this._ratio * width);
-        
-        if (event.type === 'mousedown' && event.button === 'left') {
-            if (event.x === dividerX) {
-                this._dragging = true;
-            }
-        } else if ((event.type === 'mousemove' || event.type === 'drag') && this._dragging) {
-            const newRatio = (event.x - x) / width;
-            this.setRatio(newRatio);
-        } else if (event.type === 'mouseup' || event.type === 'dragend') {
-            this._dragging = false;
-        }
-    } else {
-        const dividerY = y + Math.floor(this._ratio * height);
-        
-        if (event.type === 'mousedown' && event.button === 'left') {
-            if (event.y === dividerY) {
-                this._dragging = true;
-            }
-        } else if ((event.type === 'mousemove' || event.type === 'drag') && this._dragging) {
-            const newRatio = (event.y - y) / height;
-            this.setRatio(newRatio);
-        } else if (event.type === 'mouseup' || event.type === 'dragend') {
-            this._dragging = false;
-        }
-    }
+    const isHorizontal = this._direction === 'horizontal';
+    const pos = isHorizontal ? event.x : event.y;
+    const origin = isHorizontal ? x : y;
+    const size = isHorizontal ? width : height;
+    const dividerPos = origin + Math.floor(this._ratio * size);
+
+    if (event.type === 'mousedown' && event.button === 'left') {
+        if (pos === dividerPos) {
+            this._dragging = true;
+        }
+    } else if ((event.type === 'mousemove' || event.type === 'drag') && this._dragging) {
+        this.setRatio((pos - origin) / size);
+    } else if (event.type === 'mouseup' || event.type === 'dragend') {
+        this._dragging = false;
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/widgets/src/layout/SplitPane.ts` around lines 107 - 133, Deduplicate
the axis-specific logic in the SplitPane event handler by selecting the relevant
coordinate and dimension based on this._direction, then sharing one mousedown,
move/drag, and mouseup/dragend flow. Preserve divider detection, ratio
calculation, setRatio, and dragging state behavior while referencing the unified
axis values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/widgets/src/layout/SplitPane.ts`:
- Around line 105-116: Prevent invalid ratio updates in SplitPane.handleMouse by
guarding horizontal drag calculations when width is non-positive, matching the
existing safeguards in _renderSelf and _positionChildren. Skip the newRatio
calculation and setRatio call when the content width is zero or less; apply the
equivalent height guard for vertical dragging if it performs the same division.

---

Nitpick comments:
In `@packages/widgets/src/layout/SplitPane.ts`:
- Line 104: Import MouseEvent alongside the existing KeyEvent, Screen, and other
symbols from `@termuijs/core`, then update SplitPane.handleMouse to use the
imported MouseEvent type instead of the inline import.
- Around line 107-133: Deduplicate the axis-specific logic in the SplitPane
event handler by selecting the relevant coordinate and dimension based on
this._direction, then sharing one mousedown, move/drag, and mouseup/dragend
flow. Preserve divider detection, ratio calculation, setRatio, and dragging
state behavior while referencing the unified axis values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 944a350e-80d5-410c-847f-bfec2f2b3837

📥 Commits

Reviewing files that changed from the base of the PR and between 65d1f7e and ee6ff32.

📒 Files selected for processing (1)
  • packages/widgets/src/layout/SplitPane.ts

Comment thread packages/widgets/src/layout/SplitPane.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:widgets @termuijs/widgets

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] SplitPane Widget with Draggable Dividers

1 participant