expo-app/src/Components/Accordion/index.js

107 lines
2.5 KiB
JavaScript

import { useState } from "react";
import Animated, {
Easing,
interpolate,
useAnimatedStyle,
useSharedValue,
withTiming,
} from "react-native-reanimated";
import Card from "../Card";
import { Text, TouchableOpacity, View } from "react-native";
import MyIcon from "../Icon";
import { AppStyles } from "../../utils";
export function AccordionItem({
appContext,
title,
description,
cardTopicText,
disablePaddingBottom,
}) {
const shareValue = useSharedValue(0);
const [bodySectionHeight, setBodySectionHeight] = useState(0);
const bodyHeight = useAnimatedStyle(() => ({
height: interpolate(shareValue.value, [0, 1], [0, bodySectionHeight]),
}));
const iconStyle = useAnimatedStyle(() => {
return {
transform: [
{
rotate: `${interpolate(shareValue.value, [0, 1], [0, 180])}deg`,
},
],
};
});
const toggleExpanded = () => {
if (shareValue.value === 0) {
shareValue.value = withTiming(1, {
duration: 500,
easing: Easing.bezier(0.4, 0.0, 0.2, 1),
});
} else {
shareValue.value = withTiming(0, {
duration: 500,
easing: Easing.bezier(0.4, 0.0, 0.2, 1),
});
}
};
return (
<Card
cardTopicText={cardTopicText}
disablePaddingBottom={disablePaddingBottom}
>
<TouchableOpacity activeOpacity={0.7} onPress={toggleExpanded}>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
}}
>
<Text
style={[
{
color: appContext.appTheme.text,
width: "90%",
},
AppStyles.typography16,
]}
>
{title}
</Text>
<Animated.View style={iconStyle}>
<MyIcon name="chevron-down" size={24} />
</Animated.View>
</View>
</TouchableOpacity>
<Animated.View style={[{ overflow: "hidden", marginTop: 6 }, bodyHeight]}>
<View
style={{
position: "absolute",
bottom: 0,
left: 0,
}}
onLayout={(event) =>
setBodySectionHeight(event.nativeEvent.layout.height)
}
>
<Text
style={[
{ color: appContext.appTheme.textSecondary },
AppStyles.typography14,
]}
>
{description}
</Text>
</View>
</Animated.View>
</Card>
);
}