Write on the margins of the internet. Powered by the AT Protocol.
margin.at
extension
web
atproto
comments
1import React from "react";
2import { User } from "lucide-react";
3import { clsx } from "clsx";
4import { getAvatarUrl } from "../../api/client";
5
6type AvatarSize = "xs" | "sm" | "md" | "lg" | "xl";
7
8interface AvatarProps {
9 did?: string;
10 avatar?: string;
11 src?: string;
12 alt?: string;
13 size?: AvatarSize;
14 className?: string;
15}
16
17const sizes: Record<AvatarSize, { container: string; icon: number }> = {
18 xs: { container: "h-6 w-6", icon: 12 },
19 sm: { container: "h-8 w-8", icon: 14 },
20 md: { container: "h-10 w-10", icon: 18 },
21 lg: { container: "h-14 w-14", icon: 24 },
22 xl: { container: "h-20 w-20", icon: 32 },
23};
24
25export default function Avatar({
26 did,
27 avatar,
28 src,
29 alt = "Avatar",
30 size = "md",
31 className,
32}: AvatarProps) {
33 const imageUrl = src || getAvatarUrl(did, avatar);
34 const { container, icon } = sizes[size];
35
36 if (imageUrl) {
37 return (
38 <img
39 src={imageUrl}
40 alt={alt}
41 className={clsx(
42 container,
43 "rounded-full object-cover bg-surface-100 dark:bg-surface-800",
44 className,
45 )}
46 />
47 );
48 }
49
50 return (
51 <div
52 className={clsx(
53 container,
54 "rounded-full bg-surface-100 dark:bg-surface-800 flex items-center justify-center text-surface-400 dark:text-surface-500",
55 className,
56 )}
57 >
58 <User size={icon} />
59 </div>
60 );
61}