[APP-1403] Profile empty states (#8969)
* update: Empty state component * update type error fixes * add empty state icon * update translations on labels * update: lint error for empty state * remove unused prompt * update type errors * fix lint errors and update profile followers and profile follows * updated starterpack * fix lint errors * address feedback * update icons to be a react element * update icons * update viewbox for icons * optimize: icons and update profile lists * optimize: icons and update profile lists * lint error fix * update iconSize from the rebase
This commit is contained in:
committed by
GitHub
parent
2d056e5be6
commit
d0649e9a9e
@@ -1,76 +1,111 @@
|
||||
import {type StyleProp, StyleSheet, View, type ViewStyle} from 'react-native'
|
||||
import {type IconProp} from '@fortawesome/fontawesome-svg-core'
|
||||
import {
|
||||
FontAwesomeIcon,
|
||||
type FontAwesomeIconStyle,
|
||||
} from '@fortawesome/react-native-fontawesome'
|
||||
import React from 'react'
|
||||
import {type StyleProp, type TextStyle, type ViewStyle} from 'react-native'
|
||||
import {View} from 'react-native'
|
||||
|
||||
import {usePalette} from '#/lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
||||
import {UserGroupIcon} from '#/lib/icons'
|
||||
import {Growth_Stroke2_Corner0_Rounded as Growth} from '#/components/icons/Growth'
|
||||
import {Text} from './text/Text'
|
||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||
import {Button, type ButtonProps, ButtonText} from '#/components/Button'
|
||||
import {EditBig_Stroke1_Corner0_Rounded as EditIcon} from '#/components/icons/EditBig'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export type EmptyStateButtonProps = Omit<ButtonProps, 'children' | 'label'> & {
|
||||
label: string
|
||||
text: string
|
||||
}
|
||||
|
||||
export function EmptyState({
|
||||
testID,
|
||||
icon,
|
||||
iconSize = '3xl',
|
||||
message,
|
||||
style,
|
||||
textStyle,
|
||||
button,
|
||||
}: {
|
||||
testID?: string
|
||||
icon: IconProp | 'user-group' | 'growth'
|
||||
icon?: React.ComponentType<any> | React.ReactElement
|
||||
iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl'
|
||||
message: string
|
||||
style?: StyleProp<ViewStyle>
|
||||
textStyle?: StyleProp<TextStyle>
|
||||
button?: EmptyStateButtonProps
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const iconSize = isTabletOrDesktop ? 64 : 48
|
||||
const t = useTheme()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
|
||||
const placeholderIcon = (
|
||||
<EditIcon size="2xl" fill={t.atoms.text_contrast_medium.color} />
|
||||
)
|
||||
|
||||
const renderIcon = () => {
|
||||
if (!icon) {
|
||||
return placeholderIcon
|
||||
}
|
||||
|
||||
if (React.isValidElement(icon)) {
|
||||
return icon
|
||||
}
|
||||
|
||||
if (
|
||||
typeof icon === 'function' ||
|
||||
(typeof icon === 'object' && icon && 'render' in icon)
|
||||
) {
|
||||
const IconComponent = icon
|
||||
return (
|
||||
<IconComponent
|
||||
size={iconSize}
|
||||
fill={t.atoms.text_contrast_medium.color}
|
||||
style={{color: t.atoms.text_contrast_low.color}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return placeholderIcon
|
||||
}
|
||||
|
||||
return (
|
||||
<View testID={testID} style={style}>
|
||||
<View
|
||||
style={[
|
||||
styles.iconContainer,
|
||||
isTabletOrDesktop && styles.iconContainerBig,
|
||||
pal.viewLight,
|
||||
a.flex_row,
|
||||
a.align_center,
|
||||
a.justify_center,
|
||||
a.self_center,
|
||||
a.rounded_full,
|
||||
a.mt_5xl,
|
||||
{height: 64, width: 64},
|
||||
React.isValidElement(icon)
|
||||
? a.bg_transparent
|
||||
: [isTabletOrDesktop && {marginTop: 50}],
|
||||
]}>
|
||||
{icon === 'user-group' ? (
|
||||
<UserGroupIcon size={iconSize} />
|
||||
) : icon === 'growth' ? (
|
||||
<Growth width={iconSize} fill={pal.colors.emptyStateIcon} />
|
||||
) : (
|
||||
<FontAwesomeIcon
|
||||
icon={icon}
|
||||
size={iconSize}
|
||||
style={[{color: pal.colors.emptyStateIcon} as FontAwesomeIconStyle]}
|
||||
/>
|
||||
)}
|
||||
{renderIcon()}
|
||||
</View>
|
||||
<Text type="xl" style={[{color: pal.colors.textLight}, styles.text]}>
|
||||
<Text
|
||||
style={[
|
||||
{
|
||||
color: pal.colors.textLight,
|
||||
maxWidth: gtMobile ? '40%' : '60%',
|
||||
},
|
||||
a.pt_xs,
|
||||
a.font_medium,
|
||||
a.text_md,
|
||||
a.leading_snug,
|
||||
a.text_center,
|
||||
a.self_center,
|
||||
textStyle,
|
||||
]}>
|
||||
{message}
|
||||
</Text>
|
||||
{button && (
|
||||
<View style={[a.flex_shrink, a.mt_xl, a.self_center]}>
|
||||
<Button {...button}>
|
||||
<ButtonText>{button.text}</ButtonText>
|
||||
</Button>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
iconContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: 80,
|
||||
width: 80,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
borderRadius: 80,
|
||||
marginTop: 30,
|
||||
},
|
||||
iconContainerBig: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
marginTop: 50,
|
||||
},
|
||||
text: {
|
||||
textAlign: 'center',
|
||||
paddingTop: 20,
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user