diff --git a/mobile/assets/illustrations/index.tsx b/mobile/assets/illustrations/index.tsx new file mode 100644 index 0000000..75a5b3e --- /dev/null +++ b/mobile/assets/illustrations/index.tsx @@ -0,0 +1,112 @@ +import React from 'react'; +import Svg, { Circle, Line, Path, Rect } from 'react-native-svg'; + +export type IllustrationAssetName = + | 'groups' + | 'transactions' + | 'notifications' + | 'search' + | 'wallet' + | 'error' + | 'success' + | 'default'; + +export function GroupsIllustration() { + return ( + + + + + + + + + + ); +} + +export function TransactionsIllustration() { + return ( + + + + + + + + + + + ); +} + +export function NotificationsIllustration() { + return ( + + + + + + + ); +} + +export function SearchIllustration() { + return ( + + + + + + + + ); +} + +export function WalletIllustration() { + return ( + + + + + + + + + + ); +} + +export function ErrorIllustration() { + return ( + + + + + + + ); +} + +export function SuccessIllustration() { + return ( + + + + + + ); +} + +export function DefaultIllustration() { + return ( + + + + + ); +} diff --git a/mobile/components/ui/EmptyState.tsx b/mobile/components/ui/EmptyState.tsx index 40be38f..856d797 100644 --- a/mobile/components/ui/EmptyState.tsx +++ b/mobile/components/ui/EmptyState.tsx @@ -12,12 +12,14 @@ interface Props { } export function EmptyState({ icon, illustration, title, message, actionLabel, onAction }: Props) { - // Support both icon prop and illustration type - const displayIcon = icon || (illustration ? getIllustration(illustration).emoji : '📦'); + const selected = illustration ? getIllustration(illustration) : getIllustration('default'); + const useFallbackIcon = Boolean(icon); return ( - {displayIcon} + + {useFallbackIcon ? {icon} : selected.render()} + {title} {message} {actionLabel && ( @@ -31,7 +33,8 @@ export function EmptyState({ icon, illustration, title, message, actionLabel, on const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24 }, - icon: { fontSize: 48, marginBottom: 12 }, + illustration: { marginBottom: 14 }, + icon: { fontSize: 48 }, title: { fontSize: 18, fontWeight: '600', color: '#F1F5F9', marginBottom: 8 }, message: { fontSize: 14, color: '#94A3B8', textAlign: 'center', marginBottom: 20 }, button: { diff --git a/mobile/components/ui/Illustration.tsx b/mobile/components/ui/Illustration.tsx index a149a74..6fdcaea 100644 --- a/mobile/components/ui/Illustration.tsx +++ b/mobile/components/ui/Illustration.tsx @@ -2,6 +2,18 @@ * Empty State Illustrations * Visual assets for empty state components */ +import React from 'react'; +import type { ReactNode } from 'react'; +import { + DefaultIllustration, + ErrorIllustration, + GroupsIllustration, + NotificationsIllustration, + SearchIllustration, + SuccessIllustration, + TransactionsIllustration, + WalletIllustration, +} from '../../assets/illustrations'; export type IllustrationType = | 'groups' @@ -14,43 +26,43 @@ export type IllustrationType = | 'default'; interface IllustrationConfig { - emoji: string; description: string; + render: () => ReactNode; } // Map of illustration types to their visual representation export const illustrations: Record = { groups: { - emoji: '👥', description: 'No groups yet', + render: () => , }, transactions: { - emoji: '💳', description: 'No transactions yet', + render: () => , }, notifications: { - emoji: '🔔', description: 'No notifications', + render: () => , }, search: { - emoji: '🔍', description: 'No results found', + render: () => , }, wallet: { - emoji: '💼', description: 'No wallet connected', + render: () => , }, error: { - emoji: '⚠️', description: 'Something went wrong', + render: () => , }, success: { - emoji: '✅', description: 'Success', + render: () => , }, default: { - emoji: '📦', description: 'Nothing here', + render: () => , }, }; @@ -65,5 +77,15 @@ export function getIllustration(type: IllustrationType): IllustrationConfig { * Get illustration emoji by type */ export function getIllustrationEmoji(type: IllustrationType): string { - return getIllustration(type).emoji; -} \ No newline at end of file + const fallbackMap: Record = { + groups: '👥', + transactions: '💳', + notifications: '🔔', + search: '🔍', + wallet: '💼', + error: '⚠️', + success: '✅', + default: '📦', + }; + return fallbackMap[type]; +}