diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 5453590b9330..0c44f2709774 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -103,9 +103,10 @@ function BaseSelectionList( const incrementPage = () => setCurrentPage((prev) => prev + 1); /** - * Iterates through the sections and items inside each section, and builds 3 arrays along the way: + * Iterates through the sections and items inside each section, and builds 4 arrays along the way: * - `allOptions`: Contains all the items in the list, flattened, regardless of section - * - `disabledOptionsIndexes`: Contains the indexes of all the disabled items in the list, to be used by the ArrowKeyFocusManager + * - `disabledOptionsIndexes`: Contains the indexes of all the unselectable and disabled items in the list + * - `disabledArrowKeyOptionsIndexes`: Contains the indexes of item that is not navigatable by the arrow key. The list is separated from disabledOptionsIndexes because unselectable item is still navigatable by the arrow key. * - `itemLayouts`: Contains the layout information for each item, header and footer in the list, * so we can calculate the position of any given item when scrolling programmatically */ @@ -113,6 +114,7 @@ function BaseSelectionList( const allOptions: TItem[] = []; const disabledOptionsIndexes: number[] = []; + const disabledArrowKeyOptionsIndexes: number[] = []; let disabledIndex = 0; let offset = 0; @@ -134,9 +136,13 @@ function BaseSelectionList( }); // If disabled, add to the disabled indexes array + const isItemDisabled = !!section.isDisabled || (item.isDisabled && !item.isSelected); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - if (!!section.isDisabled || (item.isDisabled && !item.isSelected) || item.isDisabledCheckbox) { + if (isItemDisabled || item.isDisabledCheckbox) { disabledOptionsIndexes.push(disabledIndex); + if (isItemDisabled) { + disabledArrowKeyOptionsIndexes.push(disabledIndex); + } } disabledIndex += 1; @@ -169,6 +175,7 @@ function BaseSelectionList( allOptions, selectedOptions, disabledOptionsIndexes, + disabledArrowKeyOptionsIndexes, itemLayouts, allSelected: selectedOptions.length > 0 && selectedOptions.length === allOptions.length - disabledOptionsIndexes.length, }; @@ -230,21 +237,21 @@ function BaseSelectionList( [flattenedSections.allOptions], ); - const [disabledIndexes, setDisabledIndexes] = useState(flattenedSections.disabledOptionsIndexes); + const [disabledArrowKeyIndexes, setDisabledArrowKeyIndexes] = useState(flattenedSections.disabledArrowKeyOptionsIndexes); useEffect(() => { - if (arraysEqual(disabledIndexes, flattenedSections.disabledOptionsIndexes)) { + if (arraysEqual(disabledArrowKeyIndexes, flattenedSections.disabledArrowKeyOptionsIndexes)) { return; } - setDisabledIndexes(flattenedSections.disabledOptionsIndexes); + setDisabledArrowKeyIndexes(flattenedSections.disabledArrowKeyOptionsIndexes); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [flattenedSections.disabledOptionsIndexes]); + }, [flattenedSections.disabledArrowKeyOptionsIndexes]); // If `initiallyFocusedOptionKey` is not passed, we fall back to `-1`, to avoid showing the highlight on the first member const [focusedIndex, setFocusedIndex] = useArrowKeyFocusManager({ initialFocusedIndex: flattenedSections.allOptions.findIndex((option) => option.keyForList === initiallyFocusedOptionKey), maxIndex: Math.min(flattenedSections.allOptions.length - 1, CONST.MAX_SELECTION_LIST_PAGE_LENGTH * currentPage - 1), - disabledIndexes, + disabledIndexes: disabledArrowKeyIndexes, isActive: true, onFocusedIndexChange: (index: number) => { scrollToIndex(index, true); diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 4c9b72634c46..cf7cd5cde8d5 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -394,6 +394,7 @@ type FlattenedSectionsReturn = { allOptions: TItem[]; selectedOptions: TItem[]; disabledOptionsIndexes: number[]; + disabledArrowKeyOptionsIndexes: number[]; itemLayouts: ItemLayout[]; allSelected: boolean; };