From 90f219b7f28f50f0b0b4a7d29629fc18febe93e9 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Mon, 15 Apr 2024 14:07:49 +0200 Subject: [PATCH 1/2] Add shouldPreventFocusSync prop to ListItem components --- src/components/SelectionList/BaseListItem.tsx | 3 ++- src/components/SelectionList/BaseSelectionList.tsx | 6 +++++- src/components/SelectionList/InviteMemberListItem.tsx | 4 ++++ src/components/SelectionList/RadioListItem.tsx | 2 ++ src/components/SelectionList/TableListItem.tsx | 2 ++ src/components/SelectionList/UserListItem.tsx | 4 ++++ src/components/SelectionList/types.ts | 7 +++++++ 7 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/components/SelectionList/BaseListItem.tsx b/src/components/SelectionList/BaseListItem.tsx index 5f4438f18f60..600234ede12b 100644 --- a/src/components/SelectionList/BaseListItem.tsx +++ b/src/components/SelectionList/BaseListItem.tsx @@ -28,6 +28,7 @@ function BaseListItem({ FooterComponent, children, isFocused, + shouldPreventFocusSync = false, onFocus = () => {}, }: BaseListItemProps) { const theme = useTheme(); @@ -37,7 +38,7 @@ function BaseListItem({ const pressableRef = useRef(null); // Sync focus on an item - useSyncFocus(pressableRef, Boolean(isFocused)); + useSyncFocus(pressableRef, Boolean(isFocused && !shouldPreventFocusSync)); const rightHandSideComponentRender = () => { if (canSelectMultiple || !rightHandSideComponent) { diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 62f098e76228..10f6bbcb8d0e 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -92,6 +92,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); @@ -349,7 +350,8 @@ function BaseSelectionList( rightHandSideComponent={rightHandSideComponent} keyForList={item.keyForList ?? ''} isMultilineSupported={isRowMultilineSupported} - onFocus={() => setFocusedIndex(index)} + onFocus={() => setFocusedIndex(normalizedIndex)} + shouldPreventFocusSync={isTextInputFocusedRef.current} /> ); }; @@ -522,6 +524,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 5b3442d0e4ef..a761bec77766 100644 --- a/src/components/SelectionList/InviteMemberListItem.tsx +++ b/src/components/SelectionList/InviteMemberListItem.tsx @@ -26,6 +26,8 @@ function InviteMemberListItem({ onDismissError, shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, + onFocus, + shouldPreventFocusSync, }: InviteMemberListItemProps) { const styles = useThemeStyles(); const theme = useTheme(); @@ -66,6 +68,8 @@ function InviteMemberListItem({ ) : undefined } keyForList={item.keyForList} + onFocus={onFocus} + shouldPreventFocusSync={shouldPreventFocusSync} > {(hovered?: boolean) => ( <> diff --git a/src/components/SelectionList/RadioListItem.tsx b/src/components/SelectionList/RadioListItem.tsx index 808fa740bfb3..7d98328af37b 100644 --- a/src/components/SelectionList/RadioListItem.tsx +++ b/src/components/SelectionList/RadioListItem.tsx @@ -17,6 +17,7 @@ function RadioListItem({ rightHandSideComponent, isMultilineSupported = false, onFocus, + shouldPreventFocusSync, }: 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} + shouldPreventFocusSync={shouldPreventFocusSync} > <> diff --git a/src/components/SelectionList/TableListItem.tsx b/src/components/SelectionList/TableListItem.tsx index cc87d84baf03..fd2aae2203bf 100644 --- a/src/components/SelectionList/TableListItem.tsx +++ b/src/components/SelectionList/TableListItem.tsx @@ -24,6 +24,7 @@ function TableListItem({ shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, onFocus, + shouldPreventFocusSync, }: TableListItemProps) { const styles = useThemeStyles(); const theme = useTheme(); @@ -58,6 +59,7 @@ function TableListItem({ pendingAction={item.pendingAction} keyForList={item.keyForList} onFocus={onFocus} + shouldPreventFocusSync={shouldPreventFocusSync} > {(hovered) => ( <> diff --git a/src/components/SelectionList/UserListItem.tsx b/src/components/SelectionList/UserListItem.tsx index 7ab777e7e0f1..fb1c82f80fec 100644 --- a/src/components/SelectionList/UserListItem.tsx +++ b/src/components/SelectionList/UserListItem.tsx @@ -27,6 +27,8 @@ function UserListItem({ onDismissError, shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, + onFocus, + shouldPreventFocusSync, }: UserListItemProps) { const styles = useThemeStyles(); const theme = useTheme(); @@ -67,6 +69,8 @@ function UserListItem({ ) : undefined } keyForList={item.keyForList} + onFocus={onFocus} + shouldPreventFocusSync={shouldPreventFocusSync} > {(hovered?: boolean) => ( <> diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index e15dea542be6..411e4049c85d 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -137,6 +137,12 @@ type ListItemProps = CommonListItemProps & { /** Key used internally by React */ keyForList?: string; + + /** + * Whether the focus sync on element should be prevented. For example it should be set to true 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. + */ + shouldPreventFocusSync?: boolean; }; type BaseListItemProps = CommonListItemProps & { @@ -147,6 +153,7 @@ type BaseListItemProps = CommonListItemProps & { pendingAction?: PendingAction | null; FooterComponent?: ReactElement; children?: ReactElement | ((hovered: boolean) => ReactElement); + shouldPreventFocusSync?: boolean; }; type UserListItemProps = ListItemProps & { From fa118b6ae1b0fff3a4e7769a16ab3a5523d687ee Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Mon, 15 Apr 2024 17:42:23 +0200 Subject: [PATCH 2/2] Rename shouldPreventFocusSync to shouldSyncFocus --- src/components/SelectionList/BaseListItem.tsx | 4 ++-- src/components/SelectionList/BaseSelectionList.tsx | 2 +- src/components/SelectionList/InviteMemberListItem.tsx | 4 ++-- src/components/SelectionList/RadioListItem.tsx | 4 ++-- src/components/SelectionList/TableListItem.tsx | 4 ++-- src/components/SelectionList/UserListItem.tsx | 4 ++-- src/components/SelectionList/types.ts | 6 +++--- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/SelectionList/BaseListItem.tsx b/src/components/SelectionList/BaseListItem.tsx index 600234ede12b..4aac07863c36 100644 --- a/src/components/SelectionList/BaseListItem.tsx +++ b/src/components/SelectionList/BaseListItem.tsx @@ -28,7 +28,7 @@ function BaseListItem({ FooterComponent, children, isFocused, - shouldPreventFocusSync = false, + shouldSyncFocus = true, onFocus = () => {}, }: BaseListItemProps) { const theme = useTheme(); @@ -38,7 +38,7 @@ function BaseListItem({ const pressableRef = useRef(null); // Sync focus on an item - useSyncFocus(pressableRef, Boolean(isFocused && !shouldPreventFocusSync)); + 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 10f6bbcb8d0e..fa04458fc08f 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -351,7 +351,7 @@ function BaseSelectionList( keyForList={item.keyForList ?? ''} isMultilineSupported={isRowMultilineSupported} onFocus={() => setFocusedIndex(normalizedIndex)} - shouldPreventFocusSync={isTextInputFocusedRef.current} + shouldSyncFocus={!isTextInputFocusedRef.current} /> ); }; diff --git a/src/components/SelectionList/InviteMemberListItem.tsx b/src/components/SelectionList/InviteMemberListItem.tsx index a761bec77766..7b6c70373b9e 100644 --- a/src/components/SelectionList/InviteMemberListItem.tsx +++ b/src/components/SelectionList/InviteMemberListItem.tsx @@ -27,7 +27,7 @@ function InviteMemberListItem({ shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, onFocus, - shouldPreventFocusSync, + shouldSyncFocus, }: InviteMemberListItemProps) { const styles = useThemeStyles(); const theme = useTheme(); @@ -69,7 +69,7 @@ function InviteMemberListItem({ } keyForList={item.keyForList} onFocus={onFocus} - shouldPreventFocusSync={shouldPreventFocusSync} + shouldSyncFocus={shouldSyncFocus} > {(hovered?: boolean) => ( <> diff --git a/src/components/SelectionList/RadioListItem.tsx b/src/components/SelectionList/RadioListItem.tsx index 7d98328af37b..088d688fdb2d 100644 --- a/src/components/SelectionList/RadioListItem.tsx +++ b/src/components/SelectionList/RadioListItem.tsx @@ -17,7 +17,7 @@ function RadioListItem({ rightHandSideComponent, isMultilineSupported = false, onFocus, - shouldPreventFocusSync, + shouldSyncFocus, }: RadioListItemProps) { const styles = useThemeStyles(); const fullTitle = isMultilineSupported ? item.text?.trimStart() : item.text; @@ -37,7 +37,7 @@ function RadioListItem({ rightHandSideComponent={rightHandSideComponent} keyForList={item.keyForList} onFocus={onFocus} - shouldPreventFocusSync={shouldPreventFocusSync} + shouldSyncFocus={shouldSyncFocus} > <> diff --git a/src/components/SelectionList/TableListItem.tsx b/src/components/SelectionList/TableListItem.tsx index fd2aae2203bf..9720d963b2d9 100644 --- a/src/components/SelectionList/TableListItem.tsx +++ b/src/components/SelectionList/TableListItem.tsx @@ -24,7 +24,7 @@ function TableListItem({ shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, onFocus, - shouldPreventFocusSync, + shouldSyncFocus, }: TableListItemProps) { const styles = useThemeStyles(); const theme = useTheme(); @@ -59,7 +59,7 @@ function TableListItem({ pendingAction={item.pendingAction} keyForList={item.keyForList} onFocus={onFocus} - shouldPreventFocusSync={shouldPreventFocusSync} + shouldSyncFocus={shouldSyncFocus} > {(hovered) => ( <> diff --git a/src/components/SelectionList/UserListItem.tsx b/src/components/SelectionList/UserListItem.tsx index fb1c82f80fec..a97ac2f26c9a 100644 --- a/src/components/SelectionList/UserListItem.tsx +++ b/src/components/SelectionList/UserListItem.tsx @@ -28,7 +28,7 @@ function UserListItem({ shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, onFocus, - shouldPreventFocusSync, + shouldSyncFocus, }: UserListItemProps) { const styles = useThemeStyles(); const theme = useTheme(); @@ -70,7 +70,7 @@ function UserListItem({ } keyForList={item.keyForList} onFocus={onFocus} - shouldPreventFocusSync={shouldPreventFocusSync} + shouldSyncFocus={shouldSyncFocus} > {(hovered?: boolean) => ( <> diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 411e4049c85d..12f3110f6052 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -139,10 +139,10 @@ type ListItemProps = CommonListItemProps & { keyForList?: string; /** - * Whether the focus sync on element should be prevented. For example it should be set to true when the text input above list items is currently focused. + * 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. */ - shouldPreventFocusSync?: boolean; + shouldSyncFocus?: boolean; }; type BaseListItemProps = CommonListItemProps & { @@ -153,7 +153,7 @@ type BaseListItemProps = CommonListItemProps & { pendingAction?: PendingAction | null; FooterComponent?: ReactElement; children?: ReactElement | ((hovered: boolean) => ReactElement); - shouldPreventFocusSync?: boolean; + shouldSyncFocus?: boolean; }; type UserListItemProps = ListItemProps & {