Files
CBS-Mobile-App/src/modules/cards/components/ToggleSwitch.tsx
T

128 lines
2.7 KiB
TypeScript

import React, { memo, useEffect } from 'react';
import {
Pressable,
StyleSheet,
Text,
View,
} from 'react-native';
import Animated, {
interpolateColor,
useAnimatedStyle,
useSharedValue,
withTiming,
} from 'react-native-reanimated';
import { useTheme, fontFamily } from '../../../theme';
interface ToggleSwitchProps {
label: string;
description?: string;
value: boolean;
onValueChange: (value: boolean) => void;
disabled?: boolean;
}
const ToggleSwitchComponent = ({
label,
description,
value,
onValueChange,
disabled = false,
}: ToggleSwitchProps) => {
const theme = useTheme();
const progress = useSharedValue(value ? 1 : 0);
useEffect(() => {
progress.value = withTiming(value ? 1 : 0, { duration: 180 });
}, [progress, value]);
const trackStyle = useAnimatedStyle(() => ({
backgroundColor: interpolateColor(
progress.value,
[0, 1],
[theme.colors.surfaceMuted, theme.colors.primary],
),
}));
const thumbStyle = useAnimatedStyle(() => ({
transform: [{ translateX: withTiming(progress.value * 22, { duration: 180 }) }],
}));
return (
<Pressable
disabled={disabled}
onPress={() => onValueChange(!value)}
style={[
styles.row,
disabled && styles.rowDisabled,
{
borderBottomColor: theme.colors.cardBorder,
},
]}
>
<View style={styles.copy}>
<Text style={[styles.label, { color: theme.colors.textPrimary }]}>{label}</Text>
{description ? (
<Text style={[styles.description, { color: theme.colors.textSecondary }]}>
{description}
</Text>
) : null}
</View>
<Animated.View
style={[
styles.track,
trackStyle,
{ borderRadius: theme.radius.pill },
]}
>
<Animated.View
style={[
styles.thumb,
thumbStyle,
{ backgroundColor: theme.colors.white },
]}
/>
</Animated.View>
</Pressable>
);
};
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 16,
borderBottomWidth: StyleSheet.hairlineWidth,
gap: 16,
},
rowDisabled: {
opacity: 0.55,
},
copy: {
flex: 1,
gap: 4,
},
label: {
fontSize: 15,
fontFamily: fontFamily.bold,
},
description: {
fontSize: 12,
lineHeight: 18,
},
track: {
width: 52,
height: 30,
justifyContent: 'center',
paddingHorizontal: 4,
},
thumb: {
width: 18,
height: 18,
borderRadius: 9,
},
});
export const ToggleSwitch = memo(ToggleSwitchComponent);