avatar.tsx
1 import * as AvatarPrimitive from "@radix-ui/react-avatar"; 2 import * as React from "react"; 3 4 import { VariantProps, cva } from "class-variance-authority"; 5 import { cn } from "../../lib/utils"; 6 7 const avatarVariants = cva( 8 "ml-1px shadow relative flex shrink-0 overflow-hidden", 9 { 10 compoundVariants: [ 11 { 12 variant: ["outline", "default"], 13 size: "xl", 14 className: "border-3", 15 }, 16 { 17 variant: "filled", 18 color: "primary", 19 className: "bg-primary", 20 }, 21 { 22 variant: "filled", 23 color: "secondary", 24 className: "bg-secondary", 25 }, 26 { 27 variant: "filled", 28 color: "error", 29 className: "bg-error", 30 }, 31 { 32 variant: "filled", 33 color: "success", 34 className: "bg-success", 35 }, 36 { 37 variant: "filled", 38 color: "warning", 39 className: "bg-warning", 40 }, 41 { 42 variant: "filled", 43 color: "info", 44 className: "bg-info", 45 }, 46 ], 47 variants: { 48 color: { 49 primary: "bg-primary/75 border-primary text-primary", 50 secondary: "bg-secondary/75 border-secondary text-secondary", 51 error: "bg-error/75 border-error text-error", 52 success: "bg-success/75 border-success text-success", 53 warning: "bg-warning/75 border-warning text-warning", 54 info: "bg-info/75 border-info text-info", 55 muted: "bg-gray-400/75 border-gray-500", 56 }, 57 variant: { 58 default: "border-2 shadow text-background", 59 filled: "shadow text-background", 60 outline: "border-2 shadow bg-transparent", 61 ghost: "shadow bg-transparent", 62 }, 63 size: { 64 xs: "h-6 w-6 text-xs", 65 sm: "h-8 w-8 text-sm", 66 md: "h-9 w-9 text-base", 67 lg: "h-10 w-10 text-lg", 68 xl: "h-12 w-12 text-xl", 69 }, 70 round: { 71 both: "rounded-full", 72 left: "rounded-l-full", 73 right: "rounded-r-full", 74 none: "rounded-none", 75 top: "rounded-t", 76 bottom: "rounded-b", 77 topLeft: "rounded-tl", 78 topRight: "rounded-tr", 79 bottomLeft: "rounded-bl", 80 bottomRight: "rounded-br", 81 }, 82 }, 83 defaultVariants: { 84 variant: "default", 85 color: "primary", 86 round: "both", 87 size: "md", 88 }, 89 }, 90 ); 91 92 export interface AvatarProps 93 extends Omit< 94 React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>, 95 "color" 96 >, 97 VariantProps<typeof avatarVariants> { 98 asChild?: boolean; 99 noShadow?: boolean; 100 height?: string; 101 } 102 103 const Avatar = React.forwardRef< 104 React.ElementRef<typeof AvatarPrimitive.Root>, 105 AvatarProps 106 >( 107 ( 108 { className, noShadow, color, height, size, round, variant, ...props }, 109 ref, 110 ) => ( 111 <AvatarPrimitive.Root 112 ref={ref} 113 className={cn( 114 avatarVariants({ 115 variant, 116 color, 117 size, 118 round, 119 }), 120 `rounded-${round}-${size}`, 121 noShadow && "shadow-none", 122 className, 123 height, 124 )} 125 {...props} 126 /> 127 ), 128 ); 129 130 Avatar.displayName = AvatarPrimitive.Root.displayName; 131 Avatar.defaultProps = { 132 variant: "default", 133 color: "primary", 134 round: "both", 135 size: "md", 136 }; 137 138 const AvatarImage = React.forwardRef< 139 React.ElementRef<typeof AvatarPrimitive.Image>, 140 React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image> 141 >(({ className, ...props }, ref) => ( 142 <AvatarPrimitive.Image 143 ref={ref} 144 className={cn("aspect-square h-full w-full", className)} 145 {...props} 146 /> 147 )); 148 AvatarImage.displayName = AvatarPrimitive.Image.displayName; 149 150 const AvatarFallback = React.forwardRef< 151 React.ElementRef<typeof AvatarPrimitive.Fallback>, 152 React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> 153 >(({ className, ...props }, ref) => ( 154 <AvatarPrimitive.Fallback 155 ref={ref} 156 className={cn("flex h-full w-full items-center justify-center", className)} 157 {...props} 158 /> 159 )); 160 AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; 161 162 export { Avatar, AvatarFallback, AvatarImage };