add avatar component
This commit is contained in:
parent
428473f170
commit
91875f1b26
|
@ -0,0 +1,46 @@
|
||||||
|
import { Stack } from '@tamagui/core'
|
||||||
|
|
||||||
|
import { Avatar } from './avatar'
|
||||||
|
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react'
|
||||||
|
|
||||||
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
||||||
|
const meta: Meta<typeof Avatar> = {
|
||||||
|
component: Avatar,
|
||||||
|
argTypes: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof Avatar>
|
||||||
|
|
||||||
|
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
src: 'https://images.unsplash.com/photo-1518020382113-a7e8fc38eac9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=500&h=500&q=80',
|
||||||
|
},
|
||||||
|
render: args => (
|
||||||
|
<Stack space>
|
||||||
|
<Avatar {...args} size={56} />
|
||||||
|
<Avatar {...args} size={52} />
|
||||||
|
<Avatar {...args} size={48} />
|
||||||
|
<Avatar {...args} size={32} />
|
||||||
|
<Avatar {...args} size={20} />
|
||||||
|
</Stack>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Rounded: Story = {
|
||||||
|
args: {
|
||||||
|
src: 'https://images.unsplash.com/photo-1518020382113-a7e8fc38eac9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=500&h=500&q=80',
|
||||||
|
},
|
||||||
|
render: args => (
|
||||||
|
<Stack space>
|
||||||
|
<Avatar {...args} size={56} shape="rounded" />
|
||||||
|
<Avatar {...args} size={52} shape="rounded" />
|
||||||
|
<Avatar {...args} size={48} shape="rounded" />
|
||||||
|
<Avatar {...args} size={32} shape="rounded" />
|
||||||
|
<Avatar {...args} size={20} shape="rounded" />
|
||||||
|
</Stack>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
export default meta
|
|
@ -0,0 +1,108 @@
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
import { Stack, styled, Text } from '@tamagui/core'
|
||||||
|
|
||||||
|
import { Image } from '../image'
|
||||||
|
|
||||||
|
import type { GetProps } from '@tamagui/core'
|
||||||
|
|
||||||
|
// import { Button as RNButton } from 'react-native'
|
||||||
|
|
||||||
|
// setupReactNative({ Button: RNButton })
|
||||||
|
|
||||||
|
// import type { GetProps} from '@tamagui/core';
|
||||||
|
|
||||||
|
const Base = styled(Stack, {
|
||||||
|
name: 'Avatar',
|
||||||
|
|
||||||
|
display: 'inline-flex',
|
||||||
|
position: 'relative',
|
||||||
|
overflow: 'hidden',
|
||||||
|
backgroundColor: 'rgb(255,255,255)',
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
size: {
|
||||||
|
56: {
|
||||||
|
width: 56,
|
||||||
|
height: 56,
|
||||||
|
borderRadius: 56 / 2,
|
||||||
|
},
|
||||||
|
52: {
|
||||||
|
width: 52,
|
||||||
|
height: 52,
|
||||||
|
borderRadius: 52 / 2,
|
||||||
|
},
|
||||||
|
48: {
|
||||||
|
width: 48,
|
||||||
|
height: 48,
|
||||||
|
borderRadius: 48 / 2,
|
||||||
|
},
|
||||||
|
32: {
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
borderRadius: 32 / 2,
|
||||||
|
},
|
||||||
|
20: {
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
borderRadius: 20 / 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
shape: {
|
||||||
|
circle: {},
|
||||||
|
rounded: {
|
||||||
|
borderRadius: 16,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const,
|
||||||
|
})
|
||||||
|
|
||||||
|
const Fallback = styled(Text, {
|
||||||
|
name: 'AvatarFallback',
|
||||||
|
})
|
||||||
|
|
||||||
|
type BaseProps = GetProps<typeof Base>
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
src: string
|
||||||
|
size: NonNullable<BaseProps['size']>
|
||||||
|
indicator?: 'online' | 'offline'
|
||||||
|
shape?: 'circle' | 'rounded'
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageLoadingStatus = 'idle' | 'loading' | 'loaded' | 'error'
|
||||||
|
|
||||||
|
const Avatar = (props: Props) => {
|
||||||
|
const { src, size, shape = 'circle' } = props
|
||||||
|
|
||||||
|
const [status, setStatus] = useState<ImageLoadingStatus>('idle')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setStatus('idle')
|
||||||
|
}, [JSON.stringify(src)])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Base size={size} shape={shape}>
|
||||||
|
<Image
|
||||||
|
src={src}
|
||||||
|
width={size}
|
||||||
|
height={size}
|
||||||
|
onLoad={() => setStatus('loaded')}
|
||||||
|
onError={() => setStatus('error')}
|
||||||
|
/>
|
||||||
|
<Fallback
|
||||||
|
width={size}
|
||||||
|
height={size}
|
||||||
|
display="flex"
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
>
|
||||||
|
PP
|
||||||
|
</Fallback>
|
||||||
|
</Base>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Avatar }
|
||||||
|
export type { Props as AvatarProps }
|
|
@ -0,0 +1 @@
|
||||||
|
export { Avatar } from './avatar'
|
Loading…
Reference in New Issue