Support overflow scrolling. #764
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This resolves #765
The primary goal was to introduce a robust scrolling mechanism directly into the native Ink
<Box>component, inspired by the overflow scroll model on the web.Overview
<Box>withoverflow: 'scroll'should not expand beyond its flexbox-defined height. Instead, its content should be scrollable.scrollHeight) and set the scroll position.Non goals for the initial implementation
2. Implementation Strategy
The implementation involved the following steps:
Step 1: Extending the Styling System
src/styles.tsStylestype definition to add'scroll'as a valid value for theoverflow,overflowX, andoverflowYproperties.Stylestype for configuring the scrollbar's appearance and behavior (scrollTop,scrollLeft,initialScrollPosition,scrollbarThumbCharacter, etc.).applyOverflowStyles, to set theYGOverflowScrollproperty on the underlying Yoga layout node whenoverflow: 'scroll'is specified. This is the key to enabling Yoga's native overflow measurement capabilities.Step 2: Updating the Box Component
src/components/Box.tsxPropstype to include the new scroll-related properties (scrollLeft), making them available to developers.Step 3: Modifying the Internal DOM Structure
src/dom.tsDOMElementtype to include internal fields for storing calculated scroll state (internal_scrollTop,internal_scrollHeight,internal_clientHeight). This allows the renderer to access this information without needing to recalculate it.getScrollWidthto calculate the total width of the content and other measurement metrics required for users to implement their own keyboard or mouse based scroll on top of the Ink library without Ink having to commit to an API for that.Step 4: Implementing the Core Scrolling Logic
src/render-node-to-output.tsrenderNodeToOutputfunction was heavily modified to:<Box>hasoverflowX: 'scroll'oroverflowY: 'scroll'.clientHeight/clientWidth(the visible area) andscrollHeight/scrollWidth(the total size of its children).scrollTopandscrollLeftbased on the props, ensuring it stays within valid bounds.Step 5: Verification
examples/scroll/scroll.tsxexamples/scroll/index.ts<Box>with a flex model driven height and width, overflowing content, and interactive controls to switch between scrolling and not scrolling on each axis.