71 lines
1.8 KiB
TypeScript
71 lines
1.8 KiB
TypeScript
import { View, Pressable, type ViewStyle } from "react-native";
|
|
import { useTheme } from "../theme";
|
|
|
|
interface CardProps {
|
|
children: React.ReactNode;
|
|
style?: ViewStyle;
|
|
onPress?: () => void;
|
|
variant?: "default" | "elevated" | "outlined" | "flat" | "glass";
|
|
}
|
|
|
|
export function Card({ children, style, onPress, variant = "default" }: CardProps) {
|
|
const theme = useTheme();
|
|
|
|
const variantStyles: Record<string, ViewStyle> = {
|
|
default: {
|
|
backgroundColor: theme.colors.card,
|
|
borderRadius: theme.radius.lg,
|
|
padding: theme.spacing.md,
|
|
borderWidth: 0,
|
|
},
|
|
flat: {
|
|
backgroundColor: theme.colors.surfaceAlt,
|
|
borderRadius: theme.radius.md,
|
|
padding: theme.spacing.md,
|
|
borderWidth: 0,
|
|
},
|
|
elevated: {
|
|
backgroundColor: theme.colors.card,
|
|
borderRadius: theme.radius.lg,
|
|
padding: theme.spacing.md,
|
|
...theme.shadows.sm,
|
|
},
|
|
outlined: {
|
|
backgroundColor: theme.colors.card,
|
|
borderRadius: theme.radius.lg,
|
|
padding: theme.spacing.md,
|
|
borderWidth: 1,
|
|
borderColor: theme.colors.border,
|
|
},
|
|
glass: {
|
|
backgroundColor: theme.isDarkMode ? "rgba(30,30,30,0.85)" : "rgba(255,255,255,0.92)",
|
|
borderRadius: theme.radius.lg,
|
|
padding: theme.spacing.md,
|
|
borderWidth: 1,
|
|
borderColor: theme.isDarkMode ? "rgba(255,255,255,0.06)" : "rgba(255,255,255,0.5)",
|
|
...theme.shadows.md,
|
|
},
|
|
};
|
|
|
|
if (onPress) {
|
|
return (
|
|
<Pressable
|
|
onPress={onPress}
|
|
style={({ pressed }) => [
|
|
variantStyles[variant],
|
|
pressed && { opacity: 0.82, transform: [{ scale: 0.99 }] },
|
|
style,
|
|
]}
|
|
>
|
|
{children}
|
|
</Pressable>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<View style={[variantStyles[variant], style]}>
|
|
{children}
|
|
</View>
|
|
);
|
|
}
|