'use client'; import * as React from 'react'; import * as AvatarPrimitive from 'radix-ui/avatar'; import { cva, type VariantProps } from '@/lib/cva'; import { cn } from '@/lib/utils'; import { colorPalettes } from '@/lib/cva-presets'; const avatarVariants = cva( 'group/avatar relative flex shrink-0 items-center justify-center overflow-hidden font-medium select-none', { variants: { /* * The fill lives on the root rather than the fallback, so a loaded image * simply covers it and there is one place that decides how an avatar is * coloured. CBAR draws no `ghost` or `surface` avatar, so this is the * three treatments it does draw. */ variant: { solid: 'bg-(--ctl-solid) text-(--ctl-solid-fg)', subtle: 'bg-(--ctl-subtle) text-(--ctl-fg)', outline: 'border border-(--ctl-border) text-(--ctl-fg)', }, colorPalette: colorPalettes, size: { '2xs': 'size-6 text-[10px]', xs: 'size-8 text-xs', sm: 'size-9 text-sm', md: 'size-10 text-base', lg: 'size-12 text-xl', xl: 'size-16 text-2xl', }, /** CBAR names these `shape` and `square`; the round one is the default. */ shape: { circle: 'rounded-full', square: 'rounded-md', }, }, defaultVariants: { variant: 'subtle', colorPalette: 'black', size: 'md', shape: 'circle', }, } ); export interface AvatarProps extends React.ComponentProps, VariantProps {} export type AvatarImageProps = React.ComponentProps; export type AvatarFallbackProps = React.ComponentProps; /** * User or entity image with a text fallback. * * The fallback renders only after the image fails or is still loading, so the * initials never flash over a successfully loaded photo. * * ```tsx * * * {initials} * * ``` */ function Avatar({ className, variant, colorPalette, size = 'md', shape, ...props }: AvatarProps) { return ( ); } function AvatarImage({ className, ...props }: AvatarImageProps) { return ( ); } /** * Initials shown until the image loads. Transparent on purpose — the root owns * the fill and the type size, so the two can never drift apart. */ function AvatarFallback({ className, ...props }: AvatarFallbackProps) { return ( ); } /** Presence dot or small icon pinned to the avatar's bottom-right corner. */ function AvatarBadge({ className, ...props }: React.ComponentProps<'span'>) { return (