Live video on the AT Protocol
1import { FileQuestion } from "@tamagui/lucide-icons";
2import { ReactNode, useState } from "react";
3import { PressableStateCallbackType, StyleProp, ViewStyle } from "react-native";
4import { Pressable } from "react-native-gesture-handler";
5import { AnimatePresence, Text, View } from "tamagui";
6
7export default function SidebarItem({
8 icon,
9 label,
10 collapsed,
11 active,
12 onPress,
13 style = null,
14 tint = "rgba(189, 110, 134)",
15}: {
16 icon: React.ComponentType<any> | React.NamedExoticComponent<any>;
17 label: React.ComponentType<any> | string | ReactNode;
18 collapsed: boolean;
19 active: boolean;
20 onPress: () => void;
21 style?:
22 | StyleProp<ViewStyle>
23 | ((state: PressableStateCallbackType) => StyleProp<ViewStyle>);
24 tint: string;
25}) {
26 const [hover, setHover] = useState<boolean>(false);
27 // if we don't have an icon for some reason default to filequestion
28 const Icon: React.NamedExoticComponent<any> = (icon as any) || FileQuestion;
29 return (
30 <Pressable
31 onPress={onPress}
32 style={style}
33 onHoverIn={() => setHover(true)}
34 onHoverOut={() => setHover(false)}
35 role="button"
36 >
37 <View
38 backgroundColor={
39 hover || active
40 ? tint.replace(
41 ")",
42 ", " + (active && !hover ? "0.1" : "0.25") + ")",
43 )
44 : undefined
45 }
46 borderRadius="$radius.3"
47 flexDirection="row"
48 justifyContent="flex-start"
49 alignItems="center"
50 paddingHorizontal="$3"
51 gap="$2"
52 overflow="hidden"
53 >
54 <View width="$3" paddingVertical="$3">
55 <Icon color="$color" />
56 </View>
57 <AnimatePresence>
58 {!collapsed && (
59 <View
60 // setting to maximum width of the sidebar
61 // so we don't get collapsing text on collapse
62 minWidth={270}
63 maxHeight="auto"
64 animation="quick"
65 enterStyle={{ opacity: 0, width: 100 }}
66 exitStyle={{ opacity: 0, width: 100 }}
67 animateOnly={["opacity", "width"]}
68 >
69 <Text fontSize="$6" textAlign="left">
70 {label}
71 </Text>
72 </View>
73 )}
74 </AnimatePresence>
75 </View>
76 </Pressable>
77 );
78}