Skip to content

Scroll horizontally to reveal deeply nested nodes (#220)#367

Open
TrevorBurnham wants to merge 2 commits into
jameskerr:mainfrom
TrevorBurnham:fix/220-scrollto-horizontal
Open

Scroll horizontally to reveal deeply nested nodes (#220)#367
TrevorBurnham wants to merge 2 commits into
jameskerr:mainfrom
TrevorBurnham:fix/220-scrollto-horizontal

Conversation

@TrevorBurnham

Copy link
Copy Markdown
Collaborator

Summary

Fixes #220: scrollTo doesn't bring deeply nested nodes into view horizontally.

scrollTo only called react-window's scrollToItem(index, align), which adjusts the vertical axis. A node is indented by level * indent (row-container.tsx), so when rows overflow the tree's width a deep node stays off-screen to the right — the tree scrolls down to its row but the label is never revealed. react-window doesn't know about react-arborist's horizontal indentation, so the library has to handle that axis itself.

Change

After the vertical scrollToItem, scrollTo now nudges the list's outer element so the node's indentation start (level * indent) is within the horizontal viewport, aligning it to the left edge when it's off-screen in either direction.

  • No-op when there's no horizontal overflow (scrollWidth <= clientWidth) — trees that fit their width are completely unaffected.
  • Only moves when the node's indentation is actually outside the viewport (auto-style behavior), so it doesn't fight the user's scroll position unnecessarily.

Test plan

  • Added a #220 block in tree-api.test.ts covering: scrolls right when past the right edge, scrolls left when past the left edge, no change when already in view, and no-op when the list doesn't overflow horizontally.
  • yarn test — 53 passing.
  • tsc --noEmit — clean.

🤖 Generated with Claude Code

scrollTo only called react-window's scrollToItem, which adjusts the
vertical axis only. A node indented by level * indent could sit past the
right edge when rows overflow horizontally, so it stayed off-screen.

After the vertical scroll, nudge the list's horizontal scroll so the
node's indentation start is in view. It's a no-op when the list doesn't
overflow horizontally, so trees that fit their width are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 14, 2026 22:31

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

Fixes TreeApi.scrollTo() so that selecting/scrolling to deeply nested nodes also reveals them horizontally when indentation pushes content out of the viewport, addressing issue #220.

Changes:

  • After react-window’s vertical scrollToItem, adjusts the list outer element’s scrollLeft to bring the target node’s indentation start into view.
  • Adds Jest coverage for horizontal scrolling behavior across several scenarios.
  • Adds a changeset entry documenting the user-facing fix.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
modules/react-arborist/src/interfaces/tree-api.ts Adds horizontal scrolling logic to scrollTo() via a helper that updates scrollLeft based on node indentation.
modules/react-arborist/src/interfaces/tree-api.test.ts Adds tests validating horizontal scroll behavior for deep nodes and no-op conditions.
.changes/367-scrollto-horizontal.md Records the fix in the project’s changeset system for release notes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +697 to +704
const left = node.level * this.indent;
const viewLeft = el.scrollLeft;
const viewRight = el.scrollLeft + el.clientWidth;
/* Only move when the node's indentation is outside the viewport, then align
its content start to the left edge so the label is revealed. */
if (left < viewLeft || left > viewRight) {
el.scrollLeft = left;
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch on both. Fixed in e99a132: the right-edge check now uses left >= viewRight (the visible range is half-open, so a start exactly on the right edge is already clipped), and the target is clamped with Math.max(0, Math.min(left, scrollWidth - clientWidth)). Added tests for the exact-boundary and clamp cases.

…rr#367)

The visible range is half-open [scrollLeft, scrollLeft + clientWidth), so
a node whose start equals the right edge is already clipped; use >= and
clamp the target scrollLeft to the scrollable range.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

React Aborist ScrollTo bug with deep nested nodes

2 participants