avatar.tsx raw
1 "use client";
2
3 import * as React from "react";
4 import { Avatar as AvatarPrimitive } from "radix-ui";
5
6 import { cn } from "src/lib/utils";
7
8 function Avatar({
9 className,
10 size = "default",
11 ...props
12 }: React.ComponentProps<typeof AvatarPrimitive.Root> & {
13 size?: "default" | "sm" | "lg";
14 }) {
15 return (
16 <AvatarPrimitive.Root
17 data-slot="avatar"
18 data-size={size}
19 className={cn(
20 "group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6",
21 className
22 )}
23 {...props}
24 />
25 );
26 }
27
28 function AvatarImage({
29 className,
30 ...props
31 }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
32 return (
33 <AvatarPrimitive.Image
34 data-slot="avatar-image"
35 className={cn("aspect-square size-full", className)}
36 {...props}
37 />
38 );
39 }
40
41 function AvatarFallback({
42 className,
43 ...props
44 }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
45 return (
46 <AvatarPrimitive.Fallback
47 data-slot="avatar-fallback"
48 className={cn(
49 "flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
50 className
51 )}
52 {...props}
53 />
54 );
55 }
56
57 function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
58 return (
59 <span
60 data-slot="avatar-badge"
61 className={cn(
62 "absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground ring-2 ring-background select-none",
63 "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
64 "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
65 "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
66 className
67 )}
68 {...props}
69 />
70 );
71 }
72
73 function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
74 return (
75 <div
76 data-slot="avatar-group"
77 className={cn(
78 "group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
79 className
80 )}
81 {...props}
82 />
83 );
84 }
85
86 function AvatarGroupCount({
87 className,
88 ...props
89 }: React.ComponentProps<"div">) {
90 return (
91 <div
92 data-slot="avatar-group-count"
93 className={cn(
94 "relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
95 className
96 )}
97 {...props}
98 />
99 );
100 }
101
102 export {
103 Avatar,
104 AvatarImage,
105 AvatarFallback,
106 AvatarBadge,
107 AvatarGroup,
108 AvatarGroupCount,
109 };
110