import React, { memo, type PropsWithChildren } from 'react'; import { StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native'; import { useTheme } from '../../theme'; /** * `default` is the resting card and the right answer almost always. * * `flat` has a border and no lift — use it for a card that sits inside another * card, or for a grouped list where a shadow per row would be noise. * * `raised` is for the one object on a screen that has to sit above everything * else, typically the hero balance card. Two raised cards on one screen means * neither of them is. * * `muted` is a well rather than an object — a summary block, a read-only recap. * * `glass` is kept only because 13 call sites still pass it. There is no blur * library in this app, so it never actually rendered as glass; it resolves to * `default`. */ type CardVariant = 'default' | 'flat' | 'raised' | 'muted' | 'glass'; interface CardProps extends PropsWithChildren { style?: StyleProp; variant?: CardVariant; /** Drops the built-in padding, for a card that holds an edge-to-edge list. */ noPadding?: boolean; } const CardComponent = ({ children, style, variant = 'default', noPadding = false, }: CardProps) => { const theme = useTheme(); const { backgroundColor, elevation } = ((): { backgroundColor: string; elevation: ViewStyle; } => { switch (variant) { case 'flat': return { backgroundColor: theme.colors.surface, elevation: theme.elevation.level0 }; case 'raised': return { backgroundColor: theme.colors.surface, elevation: theme.elevation.level2 }; case 'muted': return { backgroundColor: theme.colors.surfaceMuted, elevation: theme.elevation.level0 }; case 'glass': case 'default': default: return { backgroundColor: theme.colors.surface, elevation: theme.elevation.level1 }; } })(); return ( {children} ); }; const styles = StyleSheet.create({ card: { borderWidth: 1, // Clipping is what lets a card hold an edge-to-edge list or image without // the child squaring off the card's own corners. overflow: 'hidden', }, }); export const Card = memo(CardComponent);