etfoglasi-frontend/components/CollapsibleCategory.tsx

111 lines
3.4 KiB
TypeScript

import React, { useState } from "react";
import {
View,
Text,
TouchableOpacity,
Animated,
LayoutAnimation,
Platform,
UIManager,
useColorScheme,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
import ExpandableItem, { FeedItem } from "./ExpandableItem";
if (Platform.OS === "android") {
UIManager.setLayoutAnimationEnabledExperimental?.(true);
}
export interface Category {
id: string;
label: string;
icon: keyof typeof Ionicons.glyphMap;
color: string; // accent hex for the icon badge
darkColor: string;
items: FeedItem[];
}
interface CollapsibleCategoryProps {
category: Category;
defaultOpen?: boolean;
}
export default function CollapsibleCategory({
category,
defaultOpen = false,
}: CollapsibleCategoryProps) {
const [open, setOpen] = useState(defaultOpen);
const scheme = useColorScheme();
const dark = scheme === "dark";
const accentColor = dark ? category.darkColor : category.color;
const toggle = () => {
LayoutAnimation.configureNext({
duration: 260,
create: { type: "easeInEaseOut", property: "opacity" },
update: { type: "spring", springDamping: 0.85 },
});
setOpen((v) => !v);
};
return (
<View className="mb-4">
<TouchableOpacity
onPress={toggle}
activeOpacity={0.8}
className={`
mx-4 flex-row items-center px-4 py-3.5 rounded-2xl
${dark
? "bg-obsidian-50 border border-border-dark"
: "bg-parchment-100 border border-border-light"
}
`}
>
{/* Icon badge */}
<View
className="w-8 h-8 rounded-xl items-center justify-center mr-3"
style={{ backgroundColor: accentColor + "25" }}
>
<Ionicons name={category.icon} size={16} color={accentColor} />
</View>
<Text
className={`flex-1 text-sm font-sans font-bold tracking-wide ${
dark ? "text-ink-dark" : "text-ink-light"
}`}
>
{category.label}
</Text>
{/* Count badge */}
<View
className="px-2 py-0.5 rounded-full mr-3"
style={{ backgroundColor: accentColor + "20" }}
>
<Text
className="text-xs font-sans font-semibold"
style={{ color: accentColor }}
>
{category.items.length}
</Text>
</View>
<Ionicons
name={open ? "chevron-up" : "chevron-down"}
size={16}
color={dark ? "#706D67" : "#8A8278"}
/>
</TouchableOpacity>
{/* Items */}
{open && (
<View className="mt-2">
{category.items.map((item) => (
<ExpandableItem key={item.id} item={item} />
))}
</View>
)}
</View>
);
}