Skip to content

Commit a80bb6a

Browse files
committed
working kybd list navigation
1 parent e86732c commit a80bb6a

File tree

7 files changed

+427
-188
lines changed

7 files changed

+427
-188
lines changed

packages/ui/src/elements/TreeView/NestedSectionsTable/NestedItems/index.tsx

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface ItemWithChildrenProps {
1010
firstCellRef?: React.RefObject<HTMLDivElement>
1111
firstCellWidth: number
1212
firstCellXOffset: number
13-
focusedItemIndex?: number
13+
focusedItemKey?: ItemKey | null
1414
hasSelectedAncestor?: boolean
1515
hoveredItemKey: ItemKey | null
1616
isDragging: boolean
@@ -23,10 +23,8 @@ interface ItemWithChildrenProps {
2323
placement?: string
2424
targetItem: null | SectionItem
2525
}) => void
26-
onFocusChange: (focusedIndex: number) => void
27-
onItemDrag: (params: { event: PointerEvent; item: null | SectionItem }) => void
28-
onItemKeyPress: (params: { event: React.KeyboardEvent; item: SectionItem }) => void
29-
onSelectionChange: ({
26+
onFocusChange: (indexPath: number[]) => void
27+
onItemClick: ({
3028
itemKey,
3129
options,
3230
}: {
@@ -37,8 +35,11 @@ interface ItemWithChildrenProps {
3735
shiftKey: boolean
3836
}
3937
}) => void
38+
onItemDrag: (params: { event: PointerEvent; item: null | SectionItem }) => void
39+
onItemKeyDown: (params: { event: React.KeyboardEvent; item: SectionItem }) => void
4040
openItemKeys?: Set<ItemKey>
4141
parentIndex?: number
42+
parentIndexPath: number[]
4243
parentItems?: SectionItem[]
4344
segmentWidth: number
4445
selectedItemKeys?: Set<ItemKey>
@@ -52,7 +53,7 @@ export const NestedItems: React.FC<ItemWithChildrenProps> = ({
5253
firstCellRef,
5354
firstCellWidth,
5455
firstCellXOffset,
55-
focusedItemIndex,
56+
focusedItemKey,
5657
hasSelectedAncestor = false,
5758
hoveredItemKey,
5859
isDragging,
@@ -62,11 +63,12 @@ export const NestedItems: React.FC<ItemWithChildrenProps> = ({
6263
loadingItemKeys,
6364
onDroppableHover,
6465
onFocusChange,
66+
onItemClick,
6567
onItemDrag,
66-
onItemKeyPress,
67-
onSelectionChange,
68+
onItemKeyDown,
6869
openItemKeys,
6970
parentIndex = 0,
71+
parentIndexPath = [],
7072
parentItems = [],
7173
segmentWidth,
7274
selectedItemKeys = new Set<ItemKey>(),
@@ -97,15 +99,14 @@ export const NestedItems: React.FC<ItemWithChildrenProps> = ({
9799
return (
98100
<>
99101
{items.map((sectionItem, sectionItemIndex: number) => {
102+
const itemIndexPath = [...parentIndexPath, sectionItemIndex]
100103
const absoluteItemIndex = getAbsoluteItemIndex(sectionItemIndex)
101104
const isLastSiblingItem = items.length - 1 === sectionItemIndex
102105
const hasNestedItems =
103106
Boolean(sectionItem?.rows?.length) && openItemKeys?.has(sectionItem.itemKey)
104107

105108
const isItemSelected = selectedItemKeys.has(sectionItem.itemKey)
106-
const isInvalidTarget = hasSelectedAncestor || isItemSelected
107109
const isItemAtRootLevel = level === 0 || (isLastSiblingItem && isLastItemOfRoot)
108-
const isFirstItemAtRootLevel = level === 0 && sectionItemIndex === 0
109110

110111
// Calculate drop target items based on position in hierarchy
111112
let targetItems: (null | SectionItem)[] = []
@@ -144,27 +145,29 @@ export const NestedItems: React.FC<ItemWithChildrenProps> = ({
144145
firstCellWidth={firstCellWidth}
145146
firstCellXOffset={firstCellXOffset}
146147
hasSelectedAncestor={hasSelectedAncestor}
148+
indexPath={itemIndexPath}
147149
isDragging={isDragging}
148-
isFirstRootItem={isFirstItemAtRootLevel}
149-
isFocused={focusedItemIndex !== undefined && focusedItemIndex === absoluteItemIndex}
150+
isFocused={focusedItemKey !== undefined && focusedItemKey === sectionItem.itemKey}
150151
isHovered={hoveredItemKey === sectionItem.itemKey}
151-
isInvalidTarget={isInvalidTarget}
152+
isInvalidTarget={hasSelectedAncestor || isItemSelected}
152153
isSelected={isItemSelected}
153154
item={sectionItem}
154155
level={level}
155156
loadingItemKeys={loadingItemKeys}
156-
onClick={onSelectionChange}
157+
onClick={onItemClick}
157158
onDrag={onItemDrag}
158159
onDroppableHover={onDroppableHover}
159160
onFocusChange={onFocusChange}
160-
onKeyPress={onItemKeyPress}
161+
onKeyDown={onItemKeyDown}
161162
openItemKeys={openItemKeys}
162163
segmentWidth={segmentWidth}
163164
selectedItemKeys={selectedItemKeys}
164165
startOffset={startOffset}
165166
targetItems={targetItems}
166167
targetParentItemKey={targetParentItemKey}
167168
toggleExpand={toggleItemExpand}
169+
// isFirstSiblingItem={isFirstSiblingItem}
170+
// isLastSiblingItem={isLastSiblingItem}
168171
/>
169172

170173
{hasNestedItems && sectionItem.rows && (
@@ -173,7 +176,7 @@ export const NestedItems: React.FC<ItemWithChildrenProps> = ({
173176
dropContextName={dropContextName}
174177
firstCellWidth={firstCellWidth}
175178
firstCellXOffset={firstCellXOffset}
176-
focusedItemIndex={focusedItemIndex}
179+
focusedItemKey={focusedItemKey}
177180
hasSelectedAncestor={hasSelectedAncestor || isItemSelected}
178181
hoveredItemKey={hoveredItemKey}
179182
isDragging={isDragging}
@@ -183,11 +186,12 @@ export const NestedItems: React.FC<ItemWithChildrenProps> = ({
183186
loadingItemKeys={loadingItemKeys}
184187
onDroppableHover={onDroppableHover}
185188
onFocusChange={onFocusChange}
189+
onItemClick={onItemClick}
186190
onItemDrag={onItemDrag}
187-
onItemKeyPress={onItemKeyPress}
188-
onSelectionChange={onSelectionChange}
191+
onItemKeyDown={onItemKeyDown}
189192
openItemKeys={openItemKeys}
190193
parentIndex={absoluteItemIndex + 1}
194+
parentIndexPath={itemIndexPath}
191195
parentItems={[...parentItems, sectionItem]}
192196
segmentWidth={segmentWidth}
193197
selectedItemKeys={selectedItemKeys}

packages/ui/src/elements/TreeView/NestedSectionsTable/Row/index.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ interface DivTableRowProps {
2626
firstCellWidth: number
2727
firstCellXOffset: number
2828
hasSelectedAncestor: boolean
29+
indexPath: number[]
2930
isDragging: boolean
30-
isFirstRootItem: boolean
3131
isFocused: boolean
3232
isHovered: boolean
3333
isInvalidTarget: boolean
@@ -45,8 +45,12 @@ interface DivTableRowProps {
4545
}) => void
4646
onDrag: (params: { event: PointerEvent; item: null | SectionItem }) => void
4747
onDroppableHover: (params: { hoveredItemKey?: ItemKey; targetItem: null | SectionItem }) => void
48-
onFocusChange: (focusedIndex: number) => void
49-
onKeyPress: (params: { event: React.KeyboardEvent; item: SectionItem }) => void
48+
onFocusChange: (indexPath: number[]) => void
49+
onKeyDown: (params: {
50+
event: React.KeyboardEvent
51+
indexPath: number[]
52+
item: SectionItem
53+
}) => void
5054
openItemKeys: Set<ItemKey>
5155
segmentWidth: number
5256
selectedItemKeys: Set<ItemKey>
@@ -64,8 +68,8 @@ export const Row: React.FC<DivTableRowProps> = ({
6468
firstCellWidth,
6569
firstCellXOffset,
6670
hasSelectedAncestor,
71+
indexPath,
6772
isDragging,
68-
isFirstRootItem,
6973
isFocused,
7074
isHovered,
7175
isInvalidTarget,
@@ -77,7 +81,7 @@ export const Row: React.FC<DivTableRowProps> = ({
7781
onDrag,
7882
onDroppableHover,
7983
onFocusChange,
80-
onKeyPress,
84+
onKeyDown,
8185
openItemKeys,
8286
segmentWidth,
8387
selectedItemKeys,
@@ -131,12 +135,12 @@ export const Row: React.FC<DivTableRowProps> = ({
131135
onClick={handleClick}
132136
onFocus={(e) => {
133137
if (e.target === e.currentTarget && !isFocused) {
134-
onFocusChange(absoluteIndex)
138+
onFocusChange(indexPath)
135139
}
136140
}}
137141
onKeyDown={(event) => {
138142
if (event.target === event.currentTarget) {
139-
onKeyPress({ event, item })
143+
onKeyDown({ event, indexPath, item })
140144
}
141145
}}
142146
onMouseDown={(e) => {
@@ -235,7 +239,7 @@ export const Row: React.FC<DivTableRowProps> = ({
235239

236240
<div>
237241
{/* Add split-top drop area for first root-level row */}
238-
{isFirstRootItem && (
242+
{absoluteIndex === 0 && (
239243
<RowDropArea
240244
disabled={isInvalidTarget}
241245
dropContextName={dropContextName}

0 commit comments

Comments
 (0)