What problem are you trying to solve?
As it stands <ScrollView> is an uncontrolled component in that the state that represents the current scroll position is held entirely inside the component.
As a default mode of operation, this makes sense to get off the ground quickly. However, it is a problem in a number of use cases where you are wanting to drive the scroll position from outside, e.g.:
- Bumping it back up to the top on some content refresh.
- Driving the scroll position via some input, e.g. mouse scroll.
- You wish to drive other pieces of UI based on the scroll position.
The lack of 'controlled' capability is somewhat inconsistent with the rest of the library.
Proposed solution
I suspect one reason for this not being here today already is an accidental fallback to Web-platform thinking -- where it would be a fundamentally bad idea to attempt to control a DOM elements scrollTop from the outside, since scroll on the web/in-browsers is inherently a native/hardware-accelerated interaction that you would never want to tie back to the event loop of userland UI code, since that would cause visible performance issues.
However, that concern is not applicable or relevant to terminal UIs where the entire concept of a scrollable panel is in itself orchestrated entirely by our UI component end to end. Indeed, its already the case that the internal variable is the absolute source of truth for the scrollposition, and that is fine in this context.
So simply, I suggest introducing optional onScroll and scrollTop props. If onScroll is unset, the component would work in the same uncontrolled mode as it does today. If it is set, then the new proposed scroll value wold be passed to the onScroll callback. Userland code would then be responsible for setting that, and passing it back down through scrollTop.
Extra bonus if the event that triggered the onScroll callback is also provided. I.e. the key.
const [scrollTop, setScrollTop] = useState(0)
// ...
return <ScrollView scrollTop={scrollTop} onScroll={(e) => setScrollTop(e.value)}) />
e here could contain a e.key to check if upArrow etc if user wanted to know that for whatever reason (one reason is highly advanced/custom focus control).
Alternatives considered
No response
What problem are you trying to solve?
As it stands
<ScrollView>is an uncontrolled component in that the state that represents the current scroll position is held entirely inside the component.As a default mode of operation, this makes sense to get off the ground quickly. However, it is a problem in a number of use cases where you are wanting to drive the scroll position from outside, e.g.:
The lack of 'controlled' capability is somewhat inconsistent with the rest of the library.
Proposed solution
I suspect one reason for this not being here today already is an accidental fallback to Web-platform thinking -- where it would be a fundamentally bad idea to attempt to control a DOM elements
scrollTopfrom the outside, since scroll on the web/in-browsers is inherently a native/hardware-accelerated interaction that you would never want to tie back to the event loop of userland UI code, since that would cause visible performance issues.However, that concern is not applicable or relevant to terminal UIs where the entire concept of a scrollable panel is in itself orchestrated entirely by our UI component end to end. Indeed, its already the case that the internal variable is the absolute source of truth for the scrollposition, and that is fine in this context.
So simply, I suggest introducing optional
onScrollandscrollTopprops. IfonScrollis unset, the component would work in the same uncontrolled mode as it does today. If it is set, then the new proposed scroll value wold be passed to theonScrollcallback. Userland code would then be responsible for setting that, and passing it back down throughscrollTop.Extra bonus if the event that triggered the
onScrollcallback is also provided. I.e. the key.ehere could contain ae.keyto check ifupArrowetc if user wanted to know that for whatever reason (one reason is highly advanced/custom focus control).Alternatives considered
No response