forked from cerc-io/snowballtools-base
feat: avatar component (#76)
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import { tv, type VariantProps } from 'tailwind-variants';
|
||||
|
||||
export const avatarTheme = tv(
|
||||
{
|
||||
base: ['relative', 'block', 'rounded-full', 'overflow-hidden'],
|
||||
slots: {
|
||||
image: [
|
||||
'h-full',
|
||||
'w-full',
|
||||
'rounded-[inherit]',
|
||||
'object-cover',
|
||||
'object-center',
|
||||
],
|
||||
fallback: [
|
||||
'grid',
|
||||
'select-none',
|
||||
'place-content-center',
|
||||
'h-full',
|
||||
'w-full',
|
||||
'rounded-[inherit]',
|
||||
'font-medium',
|
||||
],
|
||||
},
|
||||
variants: {
|
||||
type: {
|
||||
gray: {
|
||||
fallback: ['text-elements-highEm', 'bg-base-bg-emphasized'],
|
||||
},
|
||||
orange: {
|
||||
fallback: ['text-elements-warning', 'bg-base-bg-emphasized-warning'],
|
||||
},
|
||||
blue: {
|
||||
fallback: ['text-elements-info', 'bg-base-bg-emphasized-info'],
|
||||
},
|
||||
},
|
||||
size: {
|
||||
18: {
|
||||
base: ['rounded-md', 'h-[18px]', 'w-[18px]', 'text-[0.625rem]'],
|
||||
},
|
||||
20: {
|
||||
base: ['rounded-md', 'h-5', 'w-5', 'text-[0.625rem]'],
|
||||
},
|
||||
24: {
|
||||
base: ['rounded-md', 'h-6', 'w-6', 'text-[0.625rem]'],
|
||||
},
|
||||
28: {
|
||||
base: ['rounded-lg', 'h-[28px]', 'w-[28px]', 'text-[0.625rem]'],
|
||||
},
|
||||
32: {
|
||||
base: ['rounded-lg', 'h-8', 'w-8', 'text-xs'],
|
||||
},
|
||||
36: {
|
||||
base: ['rounded-xl', 'h-[36px]', 'w-[36px]', 'text-xs'],
|
||||
},
|
||||
40: {
|
||||
base: ['rounded-xl', 'h-10', 'w-10', 'text-sm'],
|
||||
},
|
||||
44: {
|
||||
base: ['rounded-xl', 'h-[44px]', 'w-[44px]', 'text-sm'],
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
size: 24,
|
||||
type: 'gray',
|
||||
},
|
||||
},
|
||||
{ responsiveVariants: true },
|
||||
);
|
||||
|
||||
export type AvatarVariants = VariantProps<typeof avatarTheme>;
|
||||
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import { type ComponentPropsWithoutRef, type ComponentProps } from 'react';
|
||||
import { avatarTheme, type AvatarVariants } from './Avatar.theme';
|
||||
import * as PrimitiveAvatar from '@radix-ui/react-avatar';
|
||||
|
||||
export type AvatarProps = ComponentPropsWithoutRef<'div'> & {
|
||||
imageSrc?: string | null;
|
||||
initials?: string;
|
||||
imageProps?: ComponentProps<typeof PrimitiveAvatar.Image>;
|
||||
fallbackProps?: ComponentProps<typeof PrimitiveAvatar.Fallback>;
|
||||
} & AvatarVariants;
|
||||
|
||||
export const Avatar = ({
|
||||
className,
|
||||
size,
|
||||
type,
|
||||
imageSrc,
|
||||
imageProps,
|
||||
fallbackProps,
|
||||
initials,
|
||||
}: AvatarProps) => {
|
||||
const { base, image, fallback } = avatarTheme({ size, type });
|
||||
|
||||
return (
|
||||
<PrimitiveAvatar.Root className={base({ className })}>
|
||||
{imageSrc && (
|
||||
<PrimitiveAvatar.Image
|
||||
{...imageProps}
|
||||
className={image({ className: imageProps?.className })}
|
||||
src={imageSrc}
|
||||
/>
|
||||
)}
|
||||
<PrimitiveAvatar.Fallback asChild {...fallbackProps}>
|
||||
<div className={fallback({ className: fallbackProps?.className })}>
|
||||
{initials}
|
||||
</div>
|
||||
</PrimitiveAvatar.Fallback>
|
||||
</PrimitiveAvatar.Root>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './Avatar';
|
||||
export * from './Avatar.theme';
|
||||
Reference in New Issue
Block a user