Avatar

Avatar displays a person or entity identity using an image when available and fallback initials when not.

When to use

  • Represent users in lists, tables, chat, and profile surfaces.
  • Show presence or role status using AvatarBadge.
  • Render collaborative participant stacks with AvatarGroup.

Behavior notes

  • Use AvatarImage for primary media and AvatarFallback for resilient initials.
  • Choose size='sm' | 'default' | 'lg' based on density and hierarchy.
  • AvatarGroup applies overlap and ring treatment for stacked layouts.
  • AvatarGroupCount indicates hidden members in compact groups.

Example

<Avatar>
  <AvatarImage src={user.image} alt={user.name} />
  <AvatarFallback>JD</AvatarFallback>
  <AvatarBadge />
</Avatar>

Preview

AM

Alex Morgan

Online

JSTNKL
ASMRJL
+4

Usage

import { CircleIcon } from 'lucide-react';

import { Text } from '@branditdev/ui';

import {
  Avatar,
  AvatarBadge,
  AvatarFallback,
  AvatarGroup,
  AvatarGroupCount,
  AvatarImage,
} from './avatar';

export function AvatarDemo() {
  return (
    <div className='w-full max-w-md space-y-5'>
      <div className='flex items-center gap-3'>
        <Avatar>
          <AvatarImage
            src='https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=200&h=200&fit=crop'
            alt='Alex Morgan'
          />
          <AvatarFallback>AM</AvatarFallback>
          <AvatarBadge>
            <CircleIcon className='fill-current' />
          </AvatarBadge>
        </Avatar>
        <div>
          <Text variant='body-sm' className='font-medium'>
            Alex Morgan
          </Text>
          <Text variant='body-sm' className='text-muted-foreground'>
            Online
          </Text>
        </div>
      </div>

      <div className='flex items-center gap-3'>
        <Avatar size='sm'>
          <AvatarFallback>JS</AvatarFallback>
        </Avatar>
        <Avatar>
          <AvatarFallback>TN</AvatarFallback>
        </Avatar>
        <Avatar size='lg'>
          <AvatarFallback>KL</AvatarFallback>
        </Avatar>
      </div>

      <AvatarGroup>
        <Avatar>
          <AvatarFallback>AS</AvatarFallback>
        </Avatar>
        <Avatar>
          <AvatarFallback>MR</AvatarFallback>
        </Avatar>
        <Avatar>
          <AvatarFallback>JL</AvatarFallback>
        </Avatar>
        <AvatarGroupCount>+4</AvatarGroupCount>
      </AvatarGroup>
    </div>
  );
}

API

Avatar(props): Element

Defined in: components/avatar/avatar.tsx:13

Avatar UI component.

Parameters

NameTypeOptionalDefaultDescription
propsAvatarProps & RefAttributes<HTMLSpanElement> & objectno-Component properties.

Returns

Element

Rendered component.

Source

import { Avatar as AvatarPrimitive } from 'radix-ui';
import * as React from 'react';

import { cn } from '@branditdev/ui';

export function Avatar({
  className,
  size = 'default',
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Root> & {
  size?: 'default' | 'sm' | 'lg';
}) {
  return (
    <AvatarPrimitive.Root
      data-slot='avatar'
      data-size={size}
      className={cn(
        'group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6',
        className
      )}
      {...props}
    />
  );
}

export function AvatarImage({
  className,
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
  return (
    <AvatarPrimitive.Image
      data-slot='avatar-image'
      className={cn('aspect-square size-full', className)}
      {...props}
    />
  );
}

export function AvatarFallback({
  className,
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
  return (
    <AvatarPrimitive.Fallback
      data-slot='avatar-fallback'
      className={cn(
        'flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs',
        className
      )}
      {...props}
    />
  );
}

export function AvatarBadge({
  className,
  ...props
}: React.ComponentProps<'span'>) {
  return (
    <span
      data-slot='avatar-badge'
      className={cn(
        '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',
        'group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden',
        'group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2',
        'group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2',
        className
      )}
      {...props}
    />
  );
}

export function AvatarGroup({
  className,
  ...props
}: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='avatar-group'
      className={cn(
        'group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background',
        className
      )}
      {...props}
    />
  );
}

export function AvatarGroupCount({
  className,
  ...props
}: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='avatar-group-count'
      className={cn(
        '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',
        className
      )}
      {...props}
    />
  );
}