5
5
import ChevronRightIcon from '@mui/icons-material/ChevronRight' ;
6
6
import ExpandMoreIcon from '@mui/icons-material/ExpandMore' ;
7
7
import MuiBox from '@mui/material/Box' ;
8
+ import { useEffect , useRef } from 'react' ;
8
9
9
10
import { Resources } from '../../../../shared/shared-types' ;
10
11
import { OpossumColors } from '../../../shared-styles' ;
@@ -26,6 +27,12 @@ const classes = {
26
27
'&:hover .tree-node-selected-indicator' : {
27
28
display : 'block' ,
28
29
} ,
30
+ '&:focus .tree-node-selected-indicator' : {
31
+ display : 'block' ,
32
+ } ,
33
+ '&:focus' : {
34
+ outline : 'none' ,
35
+ } ,
29
36
} ,
30
37
clickableIcon : {
31
38
width : '16px' ,
@@ -74,6 +81,7 @@ interface VirtualizedTreeNodeProps extends TreeNode {
74
81
onToggle : ( nodeIdsToExpand : Array < string > ) => void ;
75
82
readOnly ?: boolean ;
76
83
selected : boolean ;
84
+ focused : boolean ;
77
85
}
78
86
79
87
export function VirtualizedTreeNode ( {
@@ -86,6 +94,7 @@ export function VirtualizedTreeNode({
86
94
onToggle,
87
95
readOnly,
88
96
selected,
97
+ focused,
89
98
} : VirtualizedTreeNodeProps ) {
90
99
const isExpandable = node !== 1 && Object . keys ( node ) . length !== 0 ;
91
100
const marginRight =
@@ -96,6 +105,14 @@ export function VirtualizedTreeNode({
96
105
? SIMPLE_FOLDER_EXTRA_INDENT
97
106
: SIMPLE_NODE_EXTRA_INDENT ) ;
98
107
108
+ const ref = useRef < HTMLDivElement > ( null ) ;
109
+
110
+ useEffect ( ( ) => {
111
+ if ( focused ) {
112
+ ref . current ?. focus ( ) ;
113
+ }
114
+ } , [ focused ] ) ;
115
+
99
116
const handleClick = readOnly
100
117
? undefined
101
118
: ( ) => {
@@ -106,7 +123,24 @@ export function VirtualizedTreeNode({
106
123
} ;
107
124
108
125
return (
109
- < MuiBox sx = { classes . listNode } onClick = { handleClick } >
126
+ < MuiBox
127
+ sx = { classes . listNode }
128
+ onClick = { handleClick }
129
+ tabIndex = { 0 }
130
+ ref = { ref }
131
+ onKeyDown = { ( event ) => {
132
+ if ( [ 'Enter' , 'Space' ] . includes ( event . code ) ) {
133
+ event . preventDefault ( ) ;
134
+ handleClick ?.( ) ;
135
+ } else if ( event . code === 'ArrowRight' && ! isExpandedNode ) {
136
+ event . preventDefault ( ) ;
137
+ onToggle ?.( [ nodeId ] ) ;
138
+ } else if ( event . code === 'ArrowLeft' && isExpandedNode ) {
139
+ event . preventDefault ( ) ;
140
+ onToggle ?.( [ nodeId ] ) ;
141
+ }
142
+ } }
143
+ >
110
144
< MuiBox sx = { classes . treeNodeSpacer } style = { { width : marginRight } } />
111
145
{ renderExpandableNodeIcon ( ) }
112
146
< MuiBox
0 commit comments