animate search

This commit is contained in:
Samuel Newman
2024-10-22 12:19:20 +03:00
parent 090ac041c3
commit ddf1eebfe7
+64 -40
View File
@@ -12,6 +12,14 @@ import {
} from 'react-native' } from 'react-native'
import {ScrollView as RNGHScrollView} from 'react-native-gesture-handler' import {ScrollView as RNGHScrollView} from 'react-native-gesture-handler'
import RNPickerSelect from 'react-native-picker-select' import RNPickerSelect from 'react-native-picker-select'
import Animated, {
LayoutAnimationConfig,
LinearTransition,
SlideInLeft,
SlideInRight,
SlideOutLeft,
SlideOutRight,
} from 'react-native-reanimated'
import {AppBskyActorDefs, AppBskyFeedDefs, moderateProfile} from '@atproto/api' import {AppBskyActorDefs, AppBskyFeedDefs, moderateProfile} from '@atproto/api'
import { import {
FontAwesomeIcon, FontAwesomeIcon,
@@ -63,6 +71,7 @@ import {atoms as a, useBreakpoints, useTheme as useThemeNew, web} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import * as FeedCard from '#/components/FeedCard' import * as FeedCard from '#/components/FeedCard'
import {SearchInput} from '#/components/forms/SearchInput' import {SearchInput} from '#/components/forms/SearchInput'
import {useInteractionState} from '#/components/hooks/useInteractionState'
import {ChevronBottom_Stroke2_Corner0_Rounded as ChevronDown} from '#/components/icons/Chevron' import {ChevronBottom_Stroke2_Corner0_Rounded as ChevronDown} from '#/components/icons/Chevron'
import {Menu_Stroke2_Corner0_Rounded as Menu} from '#/components/icons/Menu' import {Menu_Stroke2_Corner0_Rounded as Menu} from '#/components/icons/Menu'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
@@ -844,7 +853,10 @@ export function SearchScreen(
[selectedProfiles], [selectedProfiles],
) )
const {state: isFocused, onIn: onFocus, onOut: onBlur} = useInteractionState()
const onSearchInputFocus = React.useCallback(() => { const onSearchInputFocus = React.useCallback(() => {
onFocus()
if (isWeb) { if (isWeb) {
// Prevent a jump on iPad by ensuring that // Prevent a jump on iPad by ensuring that
// the initial focused render has no result list. // the initial focused render has no result list.
@@ -854,7 +866,7 @@ export function SearchScreen(
} else { } else {
setShowAutocomplete(true) setShowAutocomplete(true)
} }
}, [setShowAutocomplete]) }, [setShowAutocomplete, onFocus])
return ( return (
<Layout.Screen testID="searchScreen"> <Layout.Screen testID="searchScreen">
@@ -872,46 +884,58 @@ export function SearchScreen(
}), }),
]} ]}
sideBorders={gtMobile}> sideBorders={gtMobile}>
<View style={[a.flex_row, a.gap_sm]}> <LayoutAnimationConfig skipEntering skipExiting>
{!gtMobile && ( <View style={[a.flex_row, a.gap_sm]}>
<Button {!gtMobile && !isFocused && (
testID="viewHeaderBackOrMenuBtn" <Animated.View
onPress={onPressMenu} layout={LinearTransition}
hitSlop={HITSLOP_10} entering={SlideInLeft}
label={_(msg`Menu`)} exiting={SlideOutLeft}>
accessibilityHint={_(msg`Access navigation links and settings`)} <Button
size="large" testID="viewHeaderBackOrMenuBtn"
variant="solid" onPress={onPressMenu}
color="secondary" hitSlop={HITSLOP_10}
shape="square"> label={_(msg`Menu`)}
<ButtonIcon icon={Menu} size="lg" /> accessibilityHint={_(
</Button> msg`Access navigation links and settings`,
)} )}
<View style={[a.flex_1]}> size="large"
<SearchInput variant="solid"
ref={textInput} color="secondary"
value={searchText} shape="square">
onFocus={onSearchInputFocus} <ButtonIcon icon={Menu} size="lg" />
onChangeText={onChangeText} </Button>
onClearText={onPressClearQuery} </Animated.View>
onSubmitEditing={onSubmit} )}
/> <Animated.View style={[a.flex_1]} layout={LinearTransition}>
<SearchInput
ref={textInput}
value={searchText}
onFocus={onSearchInputFocus}
onBlur={onBlur}
onChangeText={onChangeText}
onClearText={onPressClearQuery}
onSubmitEditing={onSubmit}
/>
</Animated.View>
{showAutocomplete && (
<Animated.View entering={SlideInRight} exiting={SlideOutRight}>
<Button
label={_(msg`Cancel search`)}
size="large"
variant="ghost"
color="secondary"
style={[a.px_sm]}
onPress={onPressCancelSearch}
hitSlop={HITSLOP_10}>
<ButtonText>
<Trans>Cancel</Trans>
</ButtonText>
</Button>
</Animated.View>
)}
</View> </View>
{showAutocomplete && ( </LayoutAnimationConfig>
<Button
label={_(msg`Cancel search`)}
size="large"
variant="ghost"
color="secondary"
style={[a.px_sm]}
onPress={onPressCancelSearch}
hitSlop={HITSLOP_10}>
<ButtonText>
<Trans>Cancel</Trans>
</ButtonText>
</Button>
)}
</View>
{showFilters && ( {showFilters && (
<View <View