Skip to content

Commit

Permalink
Merge pull request #40562 from software-mansion-labs/fix/notification…
Browse files Browse the repository at this point in the history
…-preferences-animation

[CP Staging] Fix selecting items and animating Pages with SelectionList

(cherry picked from commit 2c15ccc)
  • Loading branch information
cristipaval authored and OSBotify committed Apr 22, 2024
1 parent 8e59b84 commit 00520bb
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/components/SelectionList/BaseListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function BaseListItem<TItem extends ListItem>({
const pressableRef = useRef<View | HTMLDivElement>(null);

// Sync focus on an item
useSyncFocus(pressableRef, Boolean(isFocused && shouldSyncFocus));
useSyncFocus(pressableRef, Boolean(isFocused), shouldSyncFocus);

const rightHandSideComponentRender = () => {
if (canSelectMultiple || !rightHandSideComponent) {
Expand Down
10 changes: 7 additions & 3 deletions src/hooks/useSyncFocus/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import {useLayoutEffect} from 'react';
import type {RefObject} from 'react';
import type {View} from 'react-native';
import useScreenWrapperTranstionStatus from '@hooks/useScreenWrapperTransitionStatus';

/**
* Custom React hook created to handle sync of focus on an element when the user navigates through the app with keyboard.
* When the user navigates through the app using the arrows and then the tab button, the focus on the element and the native focus of the browser differs.
* To maintain consistency when an element is focused in the app, the focus() method is additionally called on the focused element to eliminate the difference between native browser focus and application focus.
*/
const useSyncFocus = (ref: RefObject<HTMLDivElement | View>, isFocused: boolean) => {
const useSyncFocus = (ref: RefObject<HTMLDivElement | View>, isFocused: boolean, shouldSyncFocus = true) => {
const {didScreenTransitionEnd} = useScreenWrapperTranstionStatus();

useLayoutEffect(() => {
if (!isFocused) {
if (!isFocused || !shouldSyncFocus || !didScreenTransitionEnd) {
return;
}

ref.current?.focus();
}, [isFocused, ref]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [didScreenTransitionEnd, isFocused, ref]);
};

export default useSyncFocus;
4 changes: 4 additions & 0 deletions tests/perf-test/SelectionList.perf-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ jest.mock('@components/withKeyboardState', () => <TProps extends KeyboardStateCo
return WrappedComponent;
});

jest.mock('@react-navigation/stack', () => ({
useCardAnimation: () => {},
}));

jest.mock('@react-navigation/native', () => ({
useFocusEffect: () => {},
useIsFocused: () => true,
Expand Down

0 comments on commit 00520bb

Please sign in to comment.