11import { cn } from "@follow/utils"
2+ import { useEffect } from "react"
23import { Image , ScrollView , StyleSheet , TouchableOpacity , View } from "react-native"
4+ import Animated , { useAnimatedStyle , useSharedValue , withTiming } from "react-native-reanimated"
35import { useSafeAreaInsets } from "react-native-safe-area-context"
46
57import { FallbackIcon } from "@/src/components/ui/icon/fallback-icon"
@@ -17,12 +19,12 @@ export const CollectionPanel = () => {
1719 const insets = useSafeAreaInsets ( )
1820 return (
1921 < View
20- className = "bg-quaternary -system-fill dark:bg-tertiary-system-background"
22+ className = "bg-secondary -system-fill dark:bg-tertiary-system-background"
2123 style = { { width : 65 } }
2224 >
2325 < ScrollView
2426 contentContainerClassName = "flex gap-4 px-3.5"
25- contentContainerStyle = { { paddingTop : insets . top + 10 , paddingBottom : insets . bottom } }
27+ contentContainerStyle = { { marginTop : insets . top + 10 , paddingBottom : insets . bottom } }
2628 >
2729 < View className = "flex-1 items-center" >
2830 < Logo width = { 37 } height = { 37 } color = "#222" />
@@ -46,16 +48,38 @@ const styles = StyleSheet.create({
4648 } ,
4749} )
4850
51+ const ActiveIndicator = ( { isActive } : { isActive : boolean } ) => {
52+ const scaleY = useSharedValue ( 1 )
53+
54+ useEffect ( ( ) => {
55+ if ( isActive ) {
56+ scaleY . value = withTiming ( 1 , { duration : 200 } )
57+ } else {
58+ scaleY . value = withTiming ( 0 , { duration : 200 } )
59+ }
60+ } , [ isActive , scaleY ] )
61+
62+ const animatedStyle = useAnimatedStyle ( ( ) => {
63+ return {
64+ transform : [ { scaleY : scaleY . value } ] ,
65+ }
66+ } )
67+
68+ return (
69+ < Animated . View
70+ className = "absolute -left-3.5 h-9 w-1 rounded-r-xl bg-black"
71+ style = { animatedStyle }
72+ />
73+ )
74+ }
75+
4976const ViewButton = ( { viewDef } : { viewDef : ViewDefinition } ) => {
5077 const selectedCollection = useSelectedCollection ( )
5178 const isActive = selectedCollection . type === "view" && selectedCollection . viewId === viewDef . view
5279
5380 return (
5481 < TouchableOpacity
55- className = { cn (
56- "flex aspect-square items-center justify-center rounded-full p-3" ,
57- isActive ? "bg-secondary-system-fill" : "bg-system-background" ,
58- ) }
82+ className = "relative flex aspect-square items-center justify-center rounded-full p-3"
5983 onPress = { ( ) =>
6084 selectCollection ( {
6185 type : "view" ,
@@ -64,6 +88,7 @@ const ViewButton = ({ viewDef }: { viewDef: ViewDefinition }) => {
6488 }
6589 style = { { backgroundColor : viewDef . activeColor } }
6690 >
91+ < ActiveIndicator isActive = { isActive } />
6792 < viewDef . icon key = { viewDef . name } color = { "#fff" } />
6893 </ TouchableOpacity >
6994 )
@@ -77,22 +102,22 @@ const ListButton = ({ listId }: { listId: string }) => {
77102
78103 return (
79104 < TouchableOpacity
80- className = { cn (
81- "flex aspect-square items-center justify-center overflow-hidden rounded-full p-3" ,
82- isActive ? "bg-system-fill" : "bg-system-background" ,
83- ) }
105+ className = { cn ( "relative flex aspect-square items-center justify-center rounded-full p-3" ) }
84106 onPress = { ( ) =>
85107 selectCollection ( {
86108 type : "list" ,
87109 listId,
88110 } )
89111 }
90112 >
91- { list . image ? (
92- < Image source = { { uri : list . image , width : 41 , height : 41 } } resizeMode = "cover" />
93- ) : (
94- < FallbackIcon title = { list . title } size = { 41 } />
95- ) }
113+ < ActiveIndicator isActive = { isActive } />
114+ < View className = "overflow-hidden rounded-full" >
115+ { list . image ? (
116+ < Image source = { { uri : list . image , width : 41 , height : 41 } } resizeMode = "cover" />
117+ ) : (
118+ < FallbackIcon title = { list . title } size = { 41 } />
119+ ) }
120+ </ View >
96121 </ TouchableOpacity >
97122 )
98123}
0 commit comments