/ src / components / ui / avatar.tsx
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 };