add status indicator to Avatar

This commit is contained in:
Pavel Prichodko 2023-01-18 16:42:22 +01:00
parent 611724f504
commit 6ba2ecfbab
No known key found for this signature in database
GPG Key ID: 0EB8D75C775AB6F1
1 changed files with 77 additions and 9 deletions

View File

@ -1,6 +1,6 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { Stack, styled, Text } from '@tamagui/core' import { Stack, styled, Text, Unspaced } from '@tamagui/core'
import { Image } from '../image' import { Image } from '../image'
@ -66,6 +66,66 @@ const Base = styled(Stack, {
} as const, } as const,
}) })
const Indicator = styled(Stack, {
name: 'Indicator',
position: 'absolute',
width: 8,
height: 8,
bottom: 0,
right: 0,
zIndex: 2,
// borderWidth: 2,
// borderColor: 'rgba(255,255,0,1.0)',
variants: {
size: {
56: {
width: 10,
height: 10,
borderRadius: 10 / 2,
},
// FIXME: use catch all variant
52: {
width: 8,
height: 8,
borderRadius: 8 / 2,
},
48: {
width: 8,
height: 8,
borderRadius: 8 / 2,
},
32: {
width: 8,
height: 8,
borderRadius: 8 / 2,
},
20: {
width: 8,
height: 8,
borderRadius: 8 / 2,
},
},
state: {
online: {
backgroundColor: '$success-50',
},
offline: {
backgroundColor: '$neutral-40',
},
},
shape: {
circle: {},
rounded: {
borderRadius: 16,
},
},
} as const,
})
const Fallback = styled(Text, { const Fallback = styled(Text, {
name: 'AvatarFallback', name: 'AvatarFallback',
}) })
@ -83,7 +143,7 @@ interface Props {
type ImageLoadingStatus = 'idle' | 'loading' | 'loaded' | 'error' type ImageLoadingStatus = 'idle' | 'loading' | 'loaded' | 'error'
const Avatar = (props: Props) => { const Avatar = (props: Props) => {
const { src, size, shape = 'circle', withOutline } = props const { src, size, shape = 'circle', withOutline, indicator } = props
const [status, setStatus] = useState<ImageLoadingStatus>('idle') const [status, setStatus] = useState<ImageLoadingStatus>('idle')
@ -93,13 +153,21 @@ const Avatar = (props: Props) => {
return ( return (
<Base size={size} shape={shape} withOutline={withOutline}> <Base size={size} shape={shape} withOutline={withOutline}>
<Image {indicator && (
src={src} <Unspaced>
width={size} <Indicator size={size} state={indicator} />
height={size} </Unspaced>
onLoad={() => setStatus('loaded')} )}
onError={() => setStatus('error')} <Stack borderRadius={28} overflow="hidden">
/> <Image
src={src}
width={size}
height={size}
onLoad={() => setStatus('loaded')}
onError={() => setStatus('error')}
/>
</Stack>
{status === 'error' && ( {status === 'error' && (
<Fallback <Fallback
width={size} width={size}