Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
at main 112 lines 2.8 kB view raw
1import React from 'react' 2import {type StyleProp, type TextStyle, type ViewStyle} from 'react-native' 3import {View} from 'react-native' 4 5import {usePalette} from '#/lib/hooks/usePalette' 6import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' 7import {atoms as a, useBreakpoints, useTheme} from '#/alf' 8import {Button, type ButtonProps, ButtonText} from '#/components/Button' 9import {EditBig_Stroke1_Corner0_Rounded as EditIcon} from '#/components/icons/EditBig' 10import {Text} from '#/components/Typography' 11 12export type EmptyStateButtonProps = Omit<ButtonProps, 'children' | 'label'> & { 13 label: string 14 text: string 15} 16 17export function EmptyState({ 18 testID, 19 icon, 20 iconSize = '3xl', 21 message, 22 style, 23 textStyle, 24 button, 25}: { 26 testID?: string 27 icon?: React.ComponentType<any> | React.ReactElement 28 iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' 29 message: string 30 style?: StyleProp<ViewStyle> 31 textStyle?: StyleProp<TextStyle> 32 button?: EmptyStateButtonProps 33}) { 34 const pal = usePalette('default') 35 const {isTabletOrDesktop} = useWebMediaQueries() 36 const t = useTheme() 37 const {gtMobile} = useBreakpoints() 38 39 const placeholderIcon = ( 40 <EditIcon size="2xl" fill={t.atoms.text_contrast_medium.color} /> 41 ) 42 43 const renderIcon = () => { 44 if (!icon) { 45 return placeholderIcon 46 } 47 48 if (React.isValidElement(icon)) { 49 return icon 50 } 51 52 if ( 53 typeof icon === 'function' || 54 (typeof icon === 'object' && icon && 'render' in icon) 55 ) { 56 const IconComponent = icon 57 return ( 58 <IconComponent 59 size={iconSize} 60 fill={t.atoms.text_contrast_medium.color} 61 style={{color: t.atoms.text_contrast_low.color}} 62 /> 63 ) 64 } 65 66 return placeholderIcon 67 } 68 69 return ( 70 <View testID={testID} style={[a.w_full, style]}> 71 <View 72 style={[ 73 a.flex_row, 74 a.align_center, 75 a.justify_center, 76 a.self_center, 77 a.rounded_full, 78 a.mt_5xl, 79 {height: 64, width: 64}, 80 React.isValidElement(icon) 81 ? a.bg_transparent 82 : [isTabletOrDesktop && {marginTop: 50}], 83 ]}> 84 {renderIcon()} 85 </View> 86 <Text 87 style={[ 88 { 89 color: pal.colors.textLight, 90 maxWidth: gtMobile ? '40%' : '60%', 91 }, 92 a.pt_xs, 93 a.font_medium, 94 a.text_md, 95 a.leading_snug, 96 a.text_center, 97 a.self_center, 98 !button && a.mb_5xl, 99 textStyle, 100 ]}> 101 {message} 102 </Text> 103 {button && ( 104 <View style={[a.flex_shrink, a.mt_xl, a.self_center, a.mb_5xl]}> 105 <Button {...button}> 106 <ButtonText>{button.text}</ButtonText> 107 </Button> 108 </View> 109 )} 110 </View> 111 ) 112}