@akhatmirzo/ui

Avatar

A user's photo or initials, with a stable color per name, a status dot and grouping.

Import

import { Avatar, AvatarGroup } from '@akhatmirzo/ui';

When to use

  • To represent a person or an organization — comments, chat, table rows, the profile menu.
  • Always pass name, even with a photo: if the image fails, the initials and color come from the name, and screen readers read it.
  • One name, one color. The color is derived from the name, so people are recognizable by color in a list too.
  • For many participants, use AvatarGroup with max: the rest collapse into "+N".

Sizes and shape

size: xs 24, sm 32, md 40 (default), lg 48 and xl 64px. shape: circle (default) for people, square for stores, organizations and projects.

Image and fallback

With src, the photo is shown; while it loads or if it fails, you see the initials. Without a name either, a person icon (or your fallback) appears. The second avatar's image URL is broken on purpose.

Status

status: online, offline or busy — a colored dot in the corner. It's also added to the aria-label for screen readers: "Sarvar Abduxoliqov (onlayn)".

Group

AvatarGroup overlaps its avatars. size and shape pass from the group to its children; anything beyond max becomes "+N".

+3

Props

Avatar

Avatar accepts every other <span> attribute except children.

PropTypeDefaultDescription
srcstring—Image URL
altstring—Name for screen readers (falls back to name)
namestring—Initials and background color are derived from it
size'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Size: 24 / 32 / 40 / 48 / 64px (inherits the group's inside a group)
shape'circle' | 'square''circle'Shape (inherits the group's inside a group)
status'online' | 'offline' | 'busy'—Status dot in the corner
fallbackReactNode—Shown when there is neither a name nor an image (default: a person icon)
labels{ status?: Partial<Record<AvatarStatus, string>> }{ status: { online: 'onlayn', offline: 'oflayn', busy: 'band' } }Status names for screen readers

AvatarGroup

AvatarGroup accepts every other <div> attribute (aria-label ...).

PropTypeDefaultDescription
maxnumber—Maximum avatars to show; the rest become "+N"
size'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Size of every avatar
shape'circle' | 'square''circle'Shape of every avatar
labels{ more?: (count: number) => string }—Screen reader text for "+N" (default: "Yana N ta")

Helper functions

The logic behind Avatar is exported on its own too:

import { getAvatarColor, getInitials } from '@akhatmirzo/ui';

getInitials('Sarvar Abduxoliqov'); // 'SA'
getInitials("o'tkir hoshimov"); // 'OH'
getAvatarColor('Sarvar Abduxoliqov'); // 'bg-danger-soft text-danger-soft-foreground'

Data attributes

On the Avatar root: data-size, data-shape, data-status and data-state (loading · loaded · fallback).

Accessibility

  • role="img" with an aria-label taken from alt or name, plus the status in brackets. The initials and image inside are aria-hidden, so screen readers say the full name, not "SA".
  • An avatar without a name (no alt, no name) is treated as decoration and hidden completely.
  • The group is role="group"; give it an aria-label ("Project members"). The "+N" is also role="img" and reads "Yana N ta".

On this page