oks-ui

How to use

Avatar

Avatar renders a user's profile image with a graceful fallback to initials (derived from name) or an icon when there's no src, or while the image is still loading. A companion AvatarGroup component stacks several Avatars with automatic overflow counting, for things like a list of collaborators on a document.

import { Avatar } from "oks-ui";

Image with automatic fallback

Pass src for the image and name so there's something sensible to fall back to — Avatar derives initials from name automatically if the image fails to load or hasn't loaded yet. If you don't have a name either, pass icon for a generic fallback instead of leaving it blank.

<Avatar src={user.avatarUrl} name={user.fullName} />
<Avatar name="Ada Lovelace" /> {/* no src -- renders "AL" */}
<Avatar icon={<UserIcon />} /> {/* no src, no name -- renders the icon */}

Status indicator

status renders a small colored dot in the corner for a presence indicator (online, offline, dnd) — built on the same positioning machinery Badge uses for its own dot mode, so it stays correctly anchored across every avatar size.

<Avatar src={user.avatarUrl} name={user.fullName} status="online" />

Fully custom fallback

For anything beyond initials or a single icon — a placeholder illustration, a different fallback per user type — pass fallback with any ReactNode; it takes priority over both icon and the derived initials. showFallback forces the fallback to render even while a valid image is still loading, useful if you'd rather show a stable placeholder than a flash of empty space.

Rendering through a different image component

By default the image renders as a plain <img>. Pass ImgComponent to render it through something else instead — next/image, for instance — with imgProps carrying whatever extra props that component needs (width/height, loader, etc.).

<Avatar
  src={user.avatarUrl}
  name={user.fullName}
  ImgComponent={Image}
  imgProps={{ width: 40, height: 40 }}
/>

Grouping avatars with AvatarGroup

AvatarGroup stacks its children with a configurable overlap and shows a "+N" overflow count once there are more avatars than max — pass total instead of relying on children.length if the real total (e.g. from a paginated API) is larger than what's actually rendered.

import { Avatar, AvatarGroup } from "oks-ui";

<AvatarGroup max={4} total={12}>
  {collaborators.map((c) => (
    <Avatar key={c.id} src={c.avatarUrl} name={c.name} />
  ))}
</AvatarGroup>

Accessibility

  • name doubles as the source for derived initials and should be the person's real display name — it's what a screen reader falls back to describing when there's no explicit label.
  • isFocusable makes an otherwise purely decorative avatar keyboard-reachable, for cases where the avatar itself is interactive (opens a profile card, a menu) rather than just illustrative.
  • status is a purely visual dot by default — if the presence state needs to be announced, pair it with your own aria-label or adjacent text, since color alone doesn't reach assistive technology.

Props reference

All available props for Avatar. See the full component page for an interactive playground.

Props

name

string

Default:

Used to derive fallback initials.

src

string

Default:

Image source URL.

icon

ReactNode

Default:

Custom fallback icon, used when name/initials aren't available.

fallback

ReactNode

Default:

Fully custom fallback content, overrides icon/initials.

showFallback

boolean

Default: false

Forces the fallback (initials/icon) even while an image is loading.

Best practices

  • Always pass name even when src is set — it's the fallback the user actually sees if the image 404s, and costs nothing when the image loads fine.
  • Use showFallback when a slow image load would otherwise cause a visible flash from blank to loaded; it keeps the layout looking intentional the whole time.
  • In AvatarGroup, set max low enough that the stack stays readable — beyond 4-5 overlapping avatars the individual faces become hard to distinguish anyway, and the overflow count communicates the rest just fine.
  • Reach for ImgComponent + imgProps when your app already has an optimized image component (next/image, a CDN-aware wrapper) — piping avatars through it keeps their loading behavior consistent with the rest of the app's images.
View full API reference for Avatar