66 Text ,
77 useColorScheme ,
88 KeyboardEvent as RNKeyboardEvent ,
9+ ScrollView ,
910} from 'react-native' ;
1011import { NavigationContainer } from './Navigation' ;
1112import {
@@ -115,26 +116,51 @@ type DrawerListItemProps = {
115116 navigation : any ;
116117 currentRoute : string ;
117118 onKeyDown ?: ( e : RNKeyboardEvent ) => void ;
119+ scrollViewRef ?: React . RefObject < ScrollView > ;
118120 ref ?: React . Ref < Pressable > ;
119121} ;
120122const DrawerListItem = React . forwardRef < Pressable , DrawerListItemProps > (
121123 (
122- { route, label, icon, navigation, currentRoute, onKeyDown } ,
124+ { route, label, icon, navigation, currentRoute, onKeyDown, scrollViewRef } ,
123125 ref ,
124126 ) => {
125127 const [ isHovered , setIsHovered ] = React . useState ( false ) ;
126128 const [ isPressed , setIsPressed ] = React . useState ( false ) ;
129+ const itemRef = useRef < View > ( null ) ;
130+
131+ const handleFocus = ( ) => {
132+ if ( scrollViewRef ?. current && itemRef . current ) {
133+ itemRef . current . measureLayout (
134+ scrollViewRef . current as any ,
135+ ( _x , y , _width , _height ) => {
136+ scrollViewRef . current ?. scrollTo ( {
137+ y : y - 50 ,
138+ animated : true ,
139+ } ) ;
140+ } ,
141+ ( ) => { } ,
142+ ) ;
143+ }
144+ } ;
127145
128146 const localStyles = createDrawerListItemStyles ( isHovered , isPressed ) ;
129147 return (
130148 < Pressable
131- ref = { ref }
149+ ref = { ( node ) => {
150+ if ( typeof ref === 'function' ) {
151+ ref ( node ) ;
152+ } else if ( ref ) {
153+ ( ref as any ) . current = node ;
154+ }
155+ ( itemRef as any ) . current = node ;
156+ } }
132157 onKeyDown = { onKeyDown }
133158 onPress = { ( ) => navigation . navigate ( route , { shouldFocus : true , focusTimestamp : Date . now ( ) } ) }
134159 onPressIn = { ( ) => setIsPressed ( true ) }
135160 onPressOut = { ( ) => setIsPressed ( false ) }
136161 onHoverIn = { ( ) => setIsHovered ( true ) }
137162 onHoverOut = { ( ) => setIsHovered ( false ) }
163+ onFocus = { handleFocus }
138164 accessibilityRole = "button"
139165 accessibilityLabel = { label }
140166 style = { localStyles . drawerListItem }
@@ -170,6 +196,7 @@ type DrawerCollapsibleCategoryProps = {
170196 navigation : any ;
171197 currentRoute : string ;
172198 containsCurrentRoute : boolean ;
199+ scrollViewRef ?: React . RefObject < ScrollView > ;
173200} ;
174201const DrawerCollapsibleCategory = ( {
175202 categoryLabel,
@@ -178,6 +205,7 @@ const DrawerCollapsibleCategory = ({
178205 navigation,
179206 currentRoute,
180207 containsCurrentRoute,
208+ scrollViewRef,
181209} : DrawerCollapsibleCategoryProps ) => {
182210 const categoryRoute = `Category: ${ categoryLabel } ` ;
183211 const isCurrentRoute = currentRoute === categoryRoute ;
@@ -187,6 +215,22 @@ const DrawerCollapsibleCategory = ({
187215 const [ isHovered , setIsHovered ] = React . useState ( false ) ;
188216 const [ isPressed , setIsPressed ] = React . useState ( false ) ;
189217 const localStyles = createDrawerListItemStyles ( isHovered , isPressed ) ;
218+ const itemRef = useRef < View > ( null ) ;
219+
220+ const handleFocus = ( ) => {
221+ if ( scrollViewRef ?. current && itemRef . current ) {
222+ itemRef . current . measureLayout (
223+ scrollViewRef . current as any ,
224+ ( _x , y , _width , _height ) => {
225+ scrollViewRef . current ?. scrollTo ( {
226+ y : y - 50 ,
227+ animated : true ,
228+ } ) ;
229+ } ,
230+ ( ) => { } ,
231+ ) ;
232+ }
233+ } ;
190234
191235 const onPress = ( ) => {
192236 if ( isExpanded && containsCurrentRoute ) {
@@ -203,12 +247,14 @@ const DrawerCollapsibleCategory = ({
203247 return (
204248 < View style = { styles . category } >
205249 < Pressable
250+ ref = { itemRef as any }
206251 style = { localStyles . drawerListItem }
207252 onPress = { ( ) => onPress ( ) }
208253 onPressIn = { ( ) => setIsPressed ( true ) }
209254 onPressOut = { ( ) => setIsPressed ( false ) }
210255 onHoverIn = { ( ) => setIsHovered ( true ) }
211256 onHoverOut = { ( ) => setIsHovered ( false ) }
257+ onFocus = { handleFocus }
212258 accessibilityRole = "button"
213259 accessibilityLabel = { categoryLabel }
214260 accessibilityState = { { expanded : isExpanded } }
@@ -248,6 +294,7 @@ const DrawerCollapsibleCategory = ({
248294 label = { item . label }
249295 navigation = { navigation }
250296 currentRoute = { currentRoute }
297+ scrollViewRef = { scrollViewRef }
251298 />
252299 ) ) }
253300 </ View >
@@ -257,6 +304,7 @@ const DrawerCollapsibleCategory = ({
257304const DrawerListView = ( props : {
258305 navigation : any ;
259306 currentRoute : string ;
307+ scrollViewRef ?: React . RefObject < ScrollView > ;
260308} ) => {
261309 const filterPredicate = ( item : any ) => item . type !== '' ;
262310 const filteredList = RNGalleryList . filter ( filterPredicate ) ;
@@ -288,6 +336,7 @@ const DrawerListView = (props: {
288336 navigation = { props . navigation }
289337 currentRoute = { props . currentRoute }
290338 containsCurrentRoute = { categoryWithCurrentRoute === category . label }
339+ scrollViewRef = { props . scrollViewRef }
291340 />
292341 ) ) }
293342 </ View >
@@ -305,6 +354,7 @@ function CustomDrawerContent({ navigation }: { navigation: any }) {
305354 const hamburgerRef = useRef < View > ( null ) ;
306355 const homeRef = useRef < View > ( null ) ;
307356 const settingsRef = useRef < View > ( null ) ;
357+ const scrollViewRef = useRef < ScrollView > ( null ) ;
308358
309359 // When drawer opens, focus the Home menu item
310360 useEffect ( ( ) => {
@@ -380,7 +430,13 @@ function CustomDrawerContent({ navigation }: { navigation: any }) {
380430 focusable = { true }
381431 />
382432 < View style = { styles . drawerDivider } />
383- < DrawerListView navigation = { navigation } currentRoute = { currentRoute } />
433+ < ScrollView ref = { scrollViewRef } >
434+ < DrawerListView
435+ navigation = { navigation }
436+ currentRoute = { currentRoute }
437+ scrollViewRef = { scrollViewRef }
438+ />
439+ </ ScrollView >
384440 < View style = { styles . drawerDivider } />
385441
386442 < DrawerListItem
0 commit comments