diff options
Diffstat (limited to 'apps/web/components/ui/user-avatar.tsx')
| -rw-r--r-- | apps/web/components/ui/user-avatar.tsx | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/apps/web/components/ui/user-avatar.tsx b/apps/web/components/ui/user-avatar.tsx new file mode 100644 index 00000000..4ebb6ec3 --- /dev/null +++ b/apps/web/components/ui/user-avatar.tsx @@ -0,0 +1,52 @@ +"use client"; + +import { useMemo } from "react"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { cn } from "@/lib/utils"; + +import { getAssetUrl } from "@karakeep/shared/utils/assetUtils"; + +interface UserAvatarProps { + image?: string | null; + name?: string | null; + className?: string; + imgClassName?: string; + fallbackClassName?: string; + fallback?: React.ReactNode; +} + +const isExternalUrl = (value: string) => + value.startsWith("http://") || value.startsWith("https://"); + +export function UserAvatar({ + image, + name, + className, + imgClassName, + fallbackClassName, + fallback, +}: UserAvatarProps) { + const avatarUrl = useMemo(() => { + if (!image) { + return null; + } + return isExternalUrl(image) ? image : getAssetUrl(image); + }, [image]); + + const fallbackContent = fallback ?? name?.charAt(0) ?? "U"; + + return ( + <Avatar className={className}> + {avatarUrl && ( + <AvatarImage + src={avatarUrl} + alt={name ?? "User"} + className={cn("object-cover", imgClassName)} + /> + )} + <AvatarFallback className={cn("text-sm font-medium", fallbackClassName)}> + {fallbackContent} + </AvatarFallback> + </Avatar> + ); +} |
