Skip to content

Commit c38677b

Browse files
committed
feat: collection panel active indicator
1 parent e0d6746 commit c38677b

File tree

1 file changed

+40
-15
lines changed

1 file changed

+40
-15
lines changed

apps/mobile/src/modules/feed-drawer/collection-panel.tsx

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { cn } from "@follow/utils"
2+
import { useEffect } from "react"
23
import { Image, ScrollView, StyleSheet, TouchableOpacity, View } from "react-native"
4+
import Animated, { useAnimatedStyle, useSharedValue, withTiming } from "react-native-reanimated"
35
import { useSafeAreaInsets } from "react-native-safe-area-context"
46

57
import { 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+
4976
const 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

Comments
 (0)