Skip to content

Commit c3885d4

Browse files
protikbiswas100Protik Biswas
andauthored
adding support for keyboard lef/right arrow for navigation menu items (#706)
* adding support for keyboard lef/right arrow for navigation menu items expand/collapse * removing redundant code * adding focusable prop * adding keyboardEvents * removing enter --------- Co-authored-by: Protik Biswas <protikbiswas100@microsoft.com>
1 parent 2733448 commit c3885d4

File tree

1 file changed

+59
-31
lines changed

1 file changed

+59
-31
lines changed

NewArch/src/App.tsx

Lines changed: 59 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ const DrawerListItem = React.forwardRef<Pressable, DrawerListItemProps>(
130130
return (
131131
<Pressable
132132
ref={ref}
133-
onKeyDown={onKeyDown}
134133
onPress={() => navigation.navigate(route, { shouldFocus: true, focusTimestamp: Date.now() })}
135134
onPressIn={() => setIsPressed(true)}
136135
onPressOut={() => setIsPressed(false)}
@@ -140,7 +139,11 @@ const DrawerListItem = React.forwardRef<Pressable, DrawerListItemProps>(
140139
accessibilityLabel={label}
141140
style={localStyles.drawerListItem}
142141
onAccessibilityTap={() => navigation.navigate(route, { shouldFocus: true, focusTimestamp: Date.now() })}
143-
focusable={true}>
142+
{...({
143+
onKeyDown: onKeyDown,
144+
keyboardEvents: ['keyDown'],
145+
focusable: true,
146+
} as any)}>
144147
<View style={styles.indentContainer}>
145148
<SelectedNavigationItemPill
146149
currentRoute={currentRoute}
@@ -201,6 +204,23 @@ const DrawerCollapsibleCategory = ({
201204
}
202205
};
203206

207+
const handleKeyDown = (e: any) => {
208+
209+
// Handle Left Arrow to collapse if expanded
210+
if (e.nativeEvent.key === 'ArrowLeft' && isExpanded) {
211+
e.preventDefault();
212+
setIsExpanded(false);
213+
return;
214+
}
215+
216+
// Handle Right Arrow to expand if collapsed
217+
if (e.nativeEvent.key === 'ArrowRight' && !isExpanded) {
218+
e.preventDefault();
219+
setIsExpanded(true);
220+
return;
221+
}
222+
};
223+
204224
return (
205225
<View style={styles.category}>
206226
<Pressable
@@ -222,7 +242,11 @@ const DrawerCollapsibleCategory = ({
222242
}
223243
}}
224244
onAccessibilityTap={() => onPress()}
225-
focusable={true}>
245+
{...({
246+
onKeyDown: handleKeyDown,
247+
keyboardEvents: ['keyDown'],
248+
focusable: true,
249+
} as any)}>
226250
<View style={styles.indentContainer}>
227251
<SelectedNavigationItemPill
228252
currentRoute={currentRoute}
@@ -302,40 +326,37 @@ function CustomDrawerContent({ navigation }: { navigation: any }) {
302326
const navigationState = navigation.getState();
303327
const currentRoute = navigationState.routeNames[navigationState.index];
304328

305-
// Refs for hamburger, home and settings buttons
329+
// Refs for main navigation items
306330
const hamburgerRef = useRef<View>(null);
307331
const homeRef = useRef<View>(null);
332+
const allSamplesRef = useRef<any>(null);
308333
const settingsRef = useRef<View>(null);
309334

310-
// When drawer opens, focus the Home menu item
311-
useEffect(() => {
312-
if (isDrawerOpen && homeRef.current) {
313-
InteractionManager.runAfterInteractions(() => {
314-
homeRef.current?.focus();
315-
});
316-
}
317-
}, [isDrawerOpen]);
318-
// Keyboard navigation looping handlers
319-
const onHamburgerKeyDown = (e: RNKeyboardEvent) => {
320-
if (e.nativeEvent.key === 'Tab' && e.nativeEvent.shiftKey) {
321-
e.preventDefault();
322-
settingsRef.current?.focus();
335+
// Simple keyboard handler that just handles arrow keys for basic navigation
336+
const handleKeyDown = (e: any) => {
337+
// Let the default behavior handle most navigation
338+
// This is a minimal implementation to support arrow keys
339+
if (e.nativeEvent.key === 'ArrowDown' || e.nativeEvent.key === 'ArrowUp') {
340+
// Allow default focus management
341+
return;
323342
}
324343
};
325-
const onSettingsKeyDown = (e: RNKeyboardEvent) => {
326-
if (e.nativeEvent.key === 'Tab' && !e.nativeEvent.shiftKey) {
327-
e.preventDefault();
328-
hamburgerRef.current?.focus();
344+
345+
// When drawer opens, focus the Home menu item
346+
useEffect(() => {
347+
if (isDrawerOpen && homeRef.current) {
348+
InteractionManager.runAfterInteractions(() => {
349+
homeRef.current?.focus();
350+
});
329351
}
330-
};
352+
}, [isDrawerOpen]);
331353

332354
return (
333355
<View style={styles.drawer}>
334356
<Pressable
335357
ref={hamburgerRef}
336358
accessibilityRole="button"
337359
accessibilityLabel="Navigation menu"
338-
tooltip={ 'Collapse navigation menu'}
339360
accessibilityHint={'Tap to collapse navigation menu'}
340361
style={styles.menu}
341362
onPress={() => {
@@ -354,9 +375,11 @@ function CustomDrawerContent({ navigation }: { navigation: any }) {
354375
navigation.openDrawer();
355376
}
356377
}}
357-
onKeyDown={onHamburgerKeyDown}
358-
keyboardEvents={['keyDown']}
359-
focusable={true}>
378+
{...({
379+
onKeyDown: handleKeyDown,
380+
keyboardEvents: ['keyDown'],
381+
focusable: true,
382+
} as any)}>
360383
<Text style={styles.icon}>&#xE700;</Text>
361384
</Pressable>
362385

@@ -369,21 +392,26 @@ function CustomDrawerContent({ navigation }: { navigation: any }) {
369392
icon="&#xE80F;"
370393
navigation={navigation}
371394
currentRoute={currentRoute}
372-
onKeyDown={() => {}}
395+
onKeyDown={handleKeyDown}
373396
keyboardEvents={['keyDown']}
374397
focusable={true}
375398
/>
376399
<DrawerListItem
400+
ref={allSamplesRef}
377401
route="All samples"
378402
label="All samples"
379403
icon="&#xE71D;"
380404
navigation={navigation}
381405
currentRoute={currentRoute}
406+
onKeyDown={handleKeyDown}
382407
keyboardEvents={['keyDown']}
383408
focusable={true}
384409
/>
385410
<View style={styles.drawerDivider} />
386-
<DrawerListView navigation={navigation} currentRoute={currentRoute} />
411+
<DrawerListView
412+
navigation={navigation}
413+
currentRoute={currentRoute}
414+
/>
387415
<View style={styles.drawerDivider} />
388416

389417
<DrawerListItem
@@ -393,7 +421,7 @@ function CustomDrawerContent({ navigation }: { navigation: any }) {
393421
icon="&#xE713;"
394422
navigation={navigation}
395423
currentRoute={currentRoute}
396-
onKeyDown={onSettingsKeyDown}
424+
onKeyDown={handleKeyDown}
397425
keyboardEvents={['keyDown']}
398426
focusable={true}
399427
/>
@@ -408,15 +436,15 @@ const Drawer = createDrawerNavigator();
408436
function MyDrawer() {
409437
return (
410438
<Drawer.Navigator
411-
drawerContent={(props) => <CustomDrawerContent {...props} />}
439+
drawerContent={(props: any) => <CustomDrawerContent {...props} />}
412440
screenOptions={{ headerShown: false }}
413441
defaultStatus="closed"
414442
initialRouteName="Home">
415443
{RNGalleryList.map((item) => (
416444
<Drawer.Screen
417445
name={item.key}
418446
key={item.key}
419-
component={item.component}
447+
component={item.component as any}
420448
/>
421449
))}
422450
</Drawer.Navigator>

0 commit comments

Comments
 (0)