Fix search typeahead performance with absolute overlay
Instead of toggling display:none/flex on the typeahead and content panels (which causes heavy unmount/remount cycles), the content (SearchScreenInner) now stays always mounted and the typeahead overlay is absolutely positioned on top with conditional rendering. Added reanimated FadeInUp/FadeOutDown animations (native only via native() wrapper) for a smooth transition. Added accessibility props (accessibilityViewIsModal, aria-modal, accessibilityRole) so screen readers properly treat the overlay as a modal list. https://claude.ai/code/session_01BhE3QBg6XZwXTwgTbQP9L9
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
|||||||
View,
|
View,
|
||||||
type ViewStyle,
|
type ViewStyle,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
|
import Animated, {FadeInUp, FadeOutDown} from 'react-native-reanimated'
|
||||||
import {Trans, useLingui} from '@lingui/react/macro'
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useFocusEffect, useNavigation, useRoute} from '@react-navigation/native'
|
import {useFocusEffect, useNavigation, useRoute} from '@react-navigation/native'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
@@ -32,7 +33,7 @@ import {
|
|||||||
type Params,
|
type Params,
|
||||||
parseSearchQuery,
|
parseSearchQuery,
|
||||||
} from '#/screens/Search/utils'
|
} from '#/screens/Search/utils'
|
||||||
import {atoms as a, tokens, useBreakpoints, useTheme, web} from '#/alf'
|
import {atoms as a, native, tokens, useBreakpoints, useTheme, web} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import {SearchInput} from '#/components/forms/SearchInput'
|
import {SearchInput} from '#/components/forms/SearchInput'
|
||||||
import * as Layout from '#/components/Layout'
|
import * as Layout from '#/components/Layout'
|
||||||
@@ -418,11 +419,25 @@ export function SearchScreenShell({
|
|||||||
</Layout.Center>
|
</Layout.Center>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View
|
<View style={[a.flex_1, a.relative]}>
|
||||||
style={{
|
<SearchScreenInner
|
||||||
display: showAutocomplete && !fixedParams ? 'flex' : 'none',
|
key={params.lang}
|
||||||
flex: 1,
|
activeTab={activeTab}
|
||||||
}}>
|
setActiveTab={setActiveTab}
|
||||||
|
query={query}
|
||||||
|
queryWithParams={queryWithParams}
|
||||||
|
headerHeight={headerHeight}
|
||||||
|
focusSearchInput={focusSearchInput}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{showAutocomplete && !fixedParams && (
|
||||||
|
<Animated.View
|
||||||
|
entering={native(FadeInUp.duration(200))}
|
||||||
|
exiting={native(FadeOutDown.duration(150))}
|
||||||
|
style={[a.absolute, a.inset_0, t.atoms.bg]}
|
||||||
|
accessibilityViewIsModal
|
||||||
|
accessibilityRole="list"
|
||||||
|
aria-modal>
|
||||||
{searchText.length > 0 ? (
|
{searchText.length > 0 ? (
|
||||||
<AutocompleteResults
|
<AutocompleteResults
|
||||||
isAutocompleteFetching={isAutocompleteFetching}
|
isAutocompleteFetching={isAutocompleteFetching}
|
||||||
@@ -442,21 +457,8 @@ export function SearchScreenShell({
|
|||||||
onRemoveProfileClick={deleteProfileHistoryItem}
|
onRemoveProfileClick={deleteProfileHistoryItem}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</Animated.View>
|
||||||
<View
|
)}
|
||||||
style={{
|
|
||||||
display: showAutocomplete ? 'none' : 'flex',
|
|
||||||
flex: 1,
|
|
||||||
}}>
|
|
||||||
<SearchScreenInner
|
|
||||||
key={params.lang}
|
|
||||||
activeTab={activeTab}
|
|
||||||
setActiveTab={setActiveTab}
|
|
||||||
query={query}
|
|
||||||
queryWithParams={queryWithParams}
|
|
||||||
headerHeight={headerHeight}
|
|
||||||
focusSearchInput={focusSearchInput}
|
|
||||||
/>
|
|
||||||
</View>
|
</View>
|
||||||
</Layout.Screen>
|
</Layout.Screen>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user