Avatar
User image with an initials fallback, a badge overlay, and a stack for a group of them.

A user's picture, falling back to initials when there is no source or the image fails to load.
Pass fallback with the initials you want; without it, a missing image leaves an empty circle.
For several people at once, Avatar.Group stacks them and counts the ones that did not fit.
Installation
Avatar ships with the library — no separate install.
import { Avatar, Badge } from 'panelui-native';Or copy the source into your project, to own and edit it:
npx panelui-cli@latest add avatarUsage
<Avatar size="lg" source={{ uri: user.avatarUrl }} fallback="KA" />
<Avatar source={{ uri: user.avatarUrl }} fallback="KA">
<Avatar.Badge>
<Badge variant="destructive" count={5} />
</Avatar.Badge>
</Avatar>Composition
<Avatar>
<Avatar.Badge>…</Avatar.Badge>
</Avatar>
<Avatar.Group>
<Avatar />
</Avatar.Group>Avatar.Badge— Overlay pinned to the top-right — an unread count or a presence dot.Avatar.Group— A row of avatars, each overlapping the one after it, with the people who did not fit counted at the end.
Examples
Image with an initials fallback
The fallback shows while the image is missing and if it fails to load, so a dead URL never leaves an empty circle.

<Avatar source={{ uri: user.avatarUrl }} fallback="KA" />
{/* No source at all — straight to initials. */}
<Avatar fallback="OL" />A presence dot
Avatar.Badge hangs off an unclipped wrapper, so it is not cut in half by the avatar’s rounding.
<Avatar size="lg" source={{ uri: user.avatarUrl }} fallback="KA">
<Avatar.Badge>
<View className="h-3 w-3 rounded-full bg-green-500" />
</Avatar.Badge>
</Avatar>A stack
Avatar.Group overlaps them and rings each one. Its size applies to every face, so the stack is set in one place rather than on each avatar.

<Avatar.Group size="sm">
{members.map((member) => (
<Avatar
key={member.id}
source={{ uri: member.avatarUrl }}
fallback={member.initials}
/>
))}
</Avatar.Group>The ones that did not fit
max caps the faces, not the row: three with five people shows three avatars and a +2. Pass total when the children are only the first few of a longer list — the count is measured against it instead of against the number of children.
{/* Five people, three faces, and a +2. */}
<Avatar.Group max={3}>
{members.map((member) => (
<Avatar key={member.id} source={{ uri: member.avatarUrl }} fallback={member.initials} />
))}
</Avatar.Group>
{/* Three faces out of forty — a +37. */}
<Avatar.Group max={3} total={40}>
{members.slice(0, 3).map((member) => (
<Avatar key={member.id} source={{ uri: member.avatarUrl }} fallback={member.initials} />
))}
</Avatar.Group>A notification badge
Avatar.Badge overlays a Badge in the corner — a count, or a shape="dot" presence dot.

<Avatar size="lg" source={{ uri: user.avatar }} fallback="AB">
<Avatar.Badge>
<Badge variant="destructive" count={5} />
</Avatar.Badge>
</Avatar>Variants
size
smmd(default)lgxl
<Avatar size="sm" fallback="KA" />
<Avatar size="md" fallback="KA" />
<Avatar size="lg" fallback="KA" />
<Avatar size="xl" fallback="KA" />API Reference
Avatar
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | |
source | ImageSourcePropType | — | Image source; falls back to initials when missing or on load error. |
fallback | string | — | Fallback text, e.g. initials ("KA"). |
imageProps | Omit<ImageProps, 'source'> | — |
Avatar.Badge
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — |
Avatar.Group
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | |
size | AvatarSizeName | md | Size for every avatar in the stack. A child's own size still wins. |
max | number | — | How many faces to show. The rest are counted into a trailing +N. It caps the faces, not the row: max={3} with five people shows three avatars and a +2. |
total | number | — | How many people there are, when the children are only the first few of them. The count is measured against this instead of against the number of children, so a stack of three out of forty reads +37. |
overlap | number | — | Points each avatar slides under the one before it. Defaults to a third of the size. |
Every part also accepts the underlying React Native props (ViewProps or TextProps) and a className for Tailwind utilities.
Notes
When an image fails, Avatar shows the fallback for that exact source. Changing the URI, request headers, or asset retries with the new source; a consumer imageProps.onError is called after the fallback state is secured.
A plain avatar renders as one clipped node. Adding children wraps it in an unclipped container so a corner badge is not cut in half by the circular mask.
Avatar.Group keeps people in the order they were written and exposes each visible person, followed by the +N overflow summary, as a list item. Explicit stacking order puts the first face on top without reversing assistive-technology traversal. This logical order is preserved in both LTR and RTL layouts.
Each face in a group gets a ring in the page background, so the stack reads as separate people on any surface. Pass overlap to change how far they slide under each other — 0 closes the stack up into a plain row.
Public exports
Values: Avatar
Types: AvatarProps, AvatarBadgeProps, AvatarGroupProps