diff --git a/packages/components/src/avatar/avatar.stories.tsx b/packages/components/src/avatar/avatar.stories.tsx new file mode 100644 index 00000000..f641b777 --- /dev/null +++ b/packages/components/src/avatar/avatar.stories.tsx @@ -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 = { + component: Avatar, + argTypes: {}, +} + +type Story = StoryObj + +// 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 => ( + + + + + + + + ), +} + +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 => ( + + + + + + + + ), +} + +export default meta diff --git a/packages/components/src/avatar/avatar.tsx b/packages/components/src/avatar/avatar.tsx new file mode 100644 index 00000000..5420ee20 --- /dev/null +++ b/packages/components/src/avatar/avatar.tsx @@ -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 + +interface Props { + src: string + size: NonNullable + 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('idle') + + useEffect(() => { + setStatus('idle') + }, [JSON.stringify(src)]) + + return ( + + setStatus('loaded')} + onError={() => setStatus('error')} + /> + + PP + + + ) +} + +export { Avatar } +export type { Props as AvatarProps } diff --git a/packages/components/src/avatar/index.tsx b/packages/components/src/avatar/index.tsx new file mode 100644 index 00000000..2d2c2bfc --- /dev/null +++ b/packages/components/src/avatar/index.tsx @@ -0,0 +1 @@ +export { Avatar } from './avatar'