From 3b1db30456ba09bbc9c2cdb0ec13c73f2c55e76d Mon Sep 17 00:00:00 2001 From: DIYgod Date: Wed, 12 Feb 2025 14:51:24 +0800 Subject: [PATCH] feat: animated view selector --- .../src/modules/feed-drawer/view-selector.tsx | 91 +++++++++++++++---- 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/apps/mobile/src/modules/feed-drawer/view-selector.tsx b/apps/mobile/src/modules/feed-drawer/view-selector.tsx index 0781fa424..142a77ff5 100644 --- a/apps/mobile/src/modules/feed-drawer/view-selector.tsx +++ b/apps/mobile/src/modules/feed-drawer/view-selector.tsx @@ -1,6 +1,9 @@ import { Image } from "expo-image" -import { ScrollView, TouchableOpacity, View } from "react-native" +import { useEffect } from "react" +import type { StyleProp, ViewStyle } from "react-native" +import { ScrollView, Text, TouchableOpacity, View } from "react-native" import { Grayscale } from "react-native-color-matrix-image-filters" +import Animated, { useSharedValue, withSpring } from "react-native-reanimated" import { FallbackIcon } from "@/src/components/ui/icon/fallback-icon" import type { ViewDefinition } from "@/src/constants/views" @@ -32,49 +35,101 @@ export function ViewSelector() { ) } -function ViewItem({ view }: { view: ViewDefinition }) { - const bgColor = useColor("gray2") - const selectedFeed = useSelectedFeed() - if (!selectedFeed) return null - const isActive = selectedFeed.type === "view" && selectedFeed.viewId === view.view +const AnimatedTouchableOpacity = Animated.createAnimatedComponent(TouchableOpacity) + +function ItemWrapper({ + children, + isActive, + onPress, + style, +}: { + children: React.ReactNode + isActive: boolean + onPress: () => void + style?: Exclude, number> +}) { + const width = useSharedValue(isActive ? 130 : 48) + const bgColor = useColor("gray5") + + useEffect(() => { + width.value = withSpring(isActive ? 130 : 48) + }, [isActive, width]) return ( - selectTimeline({ type: "view", viewId: view.view })} + - - + {children} + + ) +} + +function ViewItem({ view }: { view: ViewDefinition }) { + const textColor = useColor("gray") + + const selectedFeed = useSelectedFeed() + const isActive = selectedFeed?.type === "view" && selectedFeed.viewId === view.view + + return ( + selectTimeline({ type: "view", viewId: view.view })} + style={isActive ? { backgroundColor: view.activeColor } : undefined} + > + + {isActive && ( + + {view.name} + + )} + ) } function ListItem({ listId }: { listId: string }) { const list = useList(listId) const selectedFeed = useSelectedFeed() + const bgColor = useColor("orange") if (!selectedFeed) return null const isActive = selectedFeed.type === "list" && selectedFeed.listId === listId if (!list) return null return ( - selectTimeline({ type: "list", listId })} + style={isActive ? { backgroundColor: bgColor } : undefined} > {list.image ? ( isActive ? ( - + ) : ( - + ) ) : ( - + )} - + {isActive && ( + + {list.title} + + )} + ) }