diff --git a/src/components/SelectionList/BaseListItem.tsx b/src/components/SelectionList/BaseListItem.tsx index fe9ccc55711b..9e6fb31d0316 100644 --- a/src/components/SelectionList/BaseListItem.tsx +++ b/src/components/SelectionList/BaseListItem.tsx @@ -28,6 +28,7 @@ function BaseListItem({ FooterComponent, children, isFocused, + shouldSyncFocus = true, onFocus = () => {}, hoverStyle, }: BaseListItemProps) { @@ -38,7 +39,7 @@ function BaseListItem({ const pressableRef = useRef(null); // Sync focus on an item - useSyncFocus(pressableRef, Boolean(isFocused)); + useSyncFocus(pressableRef, Boolean(isFocused && shouldSyncFocus)); const rightHandSideComponentRender = () => { if (canSelectMultiple || !rightHandSideComponent) { diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index a5bdf46450ae..b24fe5351fad 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -93,6 +93,7 @@ function BaseSelectionList( const [itemsToHighlight, setItemsToHighlight] = useState | null>(null); const itemFocusTimeoutRef = useRef(null); const [currentPage, setCurrentPage] = useState(1); + const isTextInputFocusedRef = useRef(false); const incrementPage = () => setCurrentPage((prev) => prev + 1); @@ -354,7 +355,8 @@ function BaseSelectionList( rightHandSideComponent={rightHandSideComponent} keyForList={item.keyForList ?? ''} isMultilineSupported={isRowMultilineSupported} - onFocus={() => setFocusedIndex(index)} + onFocus={() => setFocusedIndex(normalizedIndex)} + shouldSyncFocus={!isTextInputFocusedRef.current} /> ); }; @@ -527,6 +529,8 @@ function BaseSelectionList( textInputRef.current = element as RNTextInput; } }} + onFocus={() => (isTextInputFocusedRef.current = true)} + onBlur={() => (isTextInputFocusedRef.current = false)} label={textInputLabel} accessibilityLabel={textInputLabel} hint={textInputHint} diff --git a/src/components/SelectionList/InviteMemberListItem.tsx b/src/components/SelectionList/InviteMemberListItem.tsx index 03a27c88fa68..69774e24b970 100644 --- a/src/components/SelectionList/InviteMemberListItem.tsx +++ b/src/components/SelectionList/InviteMemberListItem.tsx @@ -26,6 +26,8 @@ function InviteMemberListItem({ onDismissError, shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, + onFocus, + shouldSyncFocus, }: InviteMemberListItemProps) { const styles = useThemeStyles(); const theme = useTheme(); @@ -66,6 +68,8 @@ function InviteMemberListItem({ ) : undefined } keyForList={item.keyForList} + onFocus={onFocus} + shouldSyncFocus={shouldSyncFocus} > {(hovered?: boolean) => ( <> diff --git a/src/components/SelectionList/RadioListItem.tsx b/src/components/SelectionList/RadioListItem.tsx index e26926e75e13..7ad4819b9690 100644 --- a/src/components/SelectionList/RadioListItem.tsx +++ b/src/components/SelectionList/RadioListItem.tsx @@ -17,6 +17,7 @@ function RadioListItem({ rightHandSideComponent, isMultilineSupported = false, onFocus, + shouldSyncFocus, }: RadioListItemProps) { const styles = useThemeStyles(); const fullTitle = isMultilineSupported ? item.text?.trimStart() : item.text; @@ -36,6 +37,7 @@ function RadioListItem({ rightHandSideComponent={rightHandSideComponent} keyForList={item.keyForList} onFocus={onFocus} + shouldSyncFocus={shouldSyncFocus} > <> diff --git a/src/components/SelectionList/TableListItem.tsx b/src/components/SelectionList/TableListItem.tsx index d2fc231b5ac6..d07d658f6b12 100644 --- a/src/components/SelectionList/TableListItem.tsx +++ b/src/components/SelectionList/TableListItem.tsx @@ -24,6 +24,7 @@ function TableListItem({ shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, onFocus, + shouldSyncFocus, }: TableListItemProps) { const styles = useThemeStyles(); const theme = useTheme(); @@ -58,6 +59,7 @@ function TableListItem({ pendingAction={item.pendingAction} keyForList={item.keyForList} onFocus={onFocus} + shouldSyncFocus={shouldSyncFocus} hoverStyle={item.isSelected && styles.activeComponentBG} > {(hovered) => ( diff --git a/src/components/SelectionList/UserListItem.tsx b/src/components/SelectionList/UserListItem.tsx index 940828ebcac3..68349293e134 100644 --- a/src/components/SelectionList/UserListItem.tsx +++ b/src/components/SelectionList/UserListItem.tsx @@ -27,6 +27,8 @@ function UserListItem({ onDismissError, shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, + onFocus, + shouldSyncFocus, }: UserListItemProps) { const styles = useThemeStyles(); const theme = useTheme(); @@ -67,6 +69,8 @@ function UserListItem({ ) : undefined } keyForList={item.keyForList} + onFocus={onFocus} + shouldSyncFocus={shouldSyncFocus} > {(hovered?: boolean) => ( <> diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 9d1d9e15ca0b..a96d6c3abb17 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -139,6 +139,12 @@ type ListItemProps = CommonListItemProps & { /** Key used internally by React */ keyForList?: string; + + /** + * Whether the focus on the element should be synchronized. For example it should be set to false when the text input above list items is currently focused. + * When we type something into the text input, the first element found is focused, in this situation we should not synchronize the focus on the element because we will lose the focus from the text input. + */ + shouldSyncFocus?: boolean; }; type BaseListItemProps = CommonListItemProps & { @@ -149,6 +155,7 @@ type BaseListItemProps = CommonListItemProps & { pendingAction?: PendingAction | null; FooterComponent?: ReactElement; children?: ReactElement> | ((hovered: boolean) => ReactElement>); + shouldSyncFocus?: boolean; hoverStyle?: StyleProp; };