ScrollViewReader
The ScrollViewReader component equivalent to SwiftUI’s ScrollViewReader, allowing scripts to programmatically control scrolling position within scrollable content such as List or ScrollView.
ScrollViewProxy
ScrollViewProxy represents the programmatic interface for controlling scrolling. It is provided by ScrollViewReader during rendering.
1interface ScrollViewProxy {
2 scrollTo: (id: string | number, anchor?: KeywordPoint | Point) => void
3}
Methods
scrollTo(id, anchor?)
Scrolls the closest scrollable container until the element with the specified key becomes visible.
Parameters
| Parameter |
Type |
Required |
Description |
| id |
string |
number |
Yes |
| anchor |
KeywordPoint |
Point |
No |
KeywordPoint
Predefined scroll alignment keywords:
Point
Precise alignment coordinates:
1type Point = {
2 x: number
3 y: number
4}
ScrollViewReader Component
1type ScrollViewReaderProps = {
2 children: (scrollViewProxy: ScrollViewProxy) => VirtualNode;
3};
4declare const ScrollViewReader: FunctionComponent<ScrollViewReaderProps>;
Props
| Name |
Type |
Required |
Description |
| children |
(proxy: ScrollViewProxy) => VirtualNode |
Yes |
A function that receives a ScrollViewProxy and returns scrollable content. |
Behavior and Usage Notes
- ScrollViewReader must wrap a
List, ScrollView, or another scrollable container.
- The
proxy is created once during rendering. Use useRef if you need to store it.
scrollTo works only with elements that have a unique key.
- Using
withAnimation enables smooth scrolling.
- The API follows React’s identity model, but scroll behavior matches SwiftUI.
Example Usage
1import {
2 Button,
3 Navigation,
4 NavigationStack,
5 Script,
6 Text,
7 List,
8 ScrollViewReader,
9 ScrollView,
10 VStack,
11 useRef,
12 ScrollViewProxy,
13 withAnimation
14} from "scripting"
15
16
17function Item({ index }: { index: number }) {
18 return <Text>
19 Item - {index}
20 </Text>
21}
22
23function View() {
24 const dismiss = Navigation.useDismiss()
25 const proxyRef = useRef<ScrollViewProxy>()
26
27 return <NavigationStack>
28 <VStack navigationTitle="ScrollViewReader">
29
30 <ScrollViewReader>
31 {(proxy) => {
32 // Store the proxy instance
33 proxyRef.current = proxy
34
35 return <List>
36 {new Array(100).fill(0).map((_, index) =>
37 <Item
38 key={index}
39 index={index}
40 />
41 )}
42 <Text key="bottom">
43 Bottom
44 </Text>
45 </List>
46 }}
47 </ScrollViewReader>
48
49 <Button
50 title="Jump"
51 action={() => {
52 if (proxyRef.current == null) {
53 console.log("no proxy found")
54 return
55 }
56
57 const index = Math.random() * 100 | 0
58
59 withAnimation(() => {
60 proxyRef.current?.scrollTo(index)
61
62 // Scroll to the element identified by key="bottom"
63 // proxyRef.current?.scrollTo("bottom", "bottom")
64 })
65 }}
66 />
67
68 </VStack>
69 </NavigationStack>
70}
71
72async function run() {
73 await Navigation.present({
74 element: <View />
75 })
76 Script.exit()
77}
78
79run()
How key Works in Scripting
Scripting does not support .id() as in SwiftUI.
Instead:
1<Text key="bottom">Bottom</Text>
key identifies the element within the virtual node tree
scrollTo("bottom") will scroll to this element
key must be stable and unique, similar to React and SwiftUI’s .id()
Animation Support
Scroll operations can be wrapped in withAnimation to enable smooth transitions:
1withAnimation(() => {
2 proxy.scrollTo("targetKey", "center")
3})
The animation behavior follows SwiftUI’s animation engine.
Important Notes
- Every scroll target must have a unique
key.
scrollTo will not work without a matching key.
- The scrollable content must be inside the same ScrollViewReader.
- The alignment anchor is optional but useful for precise positioning.
- The API mirrors SwiftUI’s ScrollViewReader logic but adopts React-style identity handling.