Last active
February 16, 2025 17:12
-
-
Save hirbod/dc1615dfc4c3d15f1b59fbd2b4fd751c to your computer and use it in GitHub Desktop.
Reanimated CSS 4 Search Bar Header Replica (hacked together quick and dirty, no support!)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useSafeAreaInsets } from 'react-native-safe-area-context' | |
import { useCallback, useLayoutEffect, useMemo, useReducer, useRef, useState } from 'react' | |
import { ActivityIndicator, Keyboard, Platform, Text, View, TextInput, useWindowDimensions } from 'react-native' | |
import Animated from 'react-native-reanimated' | |
const SearchBar = () => { | |
const inset = useSafeAreaInsets() | |
const [isFocused, toggle] = useReducer((s) => !s, false) | |
const ref = useRef<View>(null) | |
const rect = useRef({ width: 0, height: 0, x: 0, y: 0 }) | |
useLayoutEffect(() => { | |
// Even though ref.current is never null with Fabric, adding a typeguard to please the linter | |
if (ref.current) { | |
// @ts-expect-error - unstable_getBoundingClientRect, types outdated | |
rect.current = ref.current.unstable_getBoundingClientRect() | |
} | |
}, []) | |
return ( | |
<Animated.View | |
className="bg-red-500" | |
style={{ | |
paddingTop: inset.top, | |
// darker colors when focused | |
backgroundColor: isFocused ? 'rgba(255, 0, 0, 0.6)' : 'rgba(255, 255, 0, 0.8)', | |
height: isFocused ? 60 + inset.top : 100 + inset.top, | |
transitionProperty: ['height', 'backgroundColor'], | |
transitionDuration: 250, | |
}}> | |
<Animated.View className="flex-row h-full"> | |
<Animated.View className="flex-1 items-center justify-center px-4"> | |
<TextInput | |
placeholder="Search" | |
className="w-full bg-neutral-200 px-4 rounded-xl h-12" | |
placeholderTextColor="black" | |
keyboardType="web-search" | |
clearButtonMode="while-editing" | |
onFocus={() => toggle()} | |
onBlur={() => toggle()} | |
/> | |
</Animated.View> | |
<Animated.View | |
style={{ | |
paddingRight: !isFocused ? 0 : rect.current.width, | |
transitionProperty: ['paddingRight'], | |
transitionDuration: 250, | |
}} | |
/> | |
<Animated.View | |
className="items-center justify-center absolute right-0" | |
style={{ | |
opacity: isFocused ? 1 : 0, | |
height: '100%', | |
transitionProperty: ['opacity'], | |
transitionDuration: 250, | |
}}> | |
<View className="pr-4" ref={ref}> | |
<Text | |
numberOfLines={1} | |
className="font-semibold text-center color-white" | |
onPress={() => Keyboard.dismiss()}> | |
Cancel | |
</Text> | |
</View> | |
</Animated.View> | |
</Animated.View> | |
</Animated.View> | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Simulator.Screen.Recording.-.iPhone.16.Pro.-.2025-01-25.at.00.29.43.mp4
aa22222225.mp4