# How to Use Avatar and AvatarGroup Components for User Display in Astryx

> Learn to display user profiles effectively with Astryx Avatar and AvatarGroup components. Customize images, initials, and manage multiple avatars seamlessly for a clean UI.

- Repository: [Meta/astryx](https://github.com/facebook/astryx)
- Tags: how-to-guide
- Published: 2026-07-14

---

**Astryx provides a flexible Avatar component that displays user images, initials, or fallback icons, and an AvatarGroup component that stacks multiple avatars with configurable overlap and overflow handling.**

Astryx, Facebook's open-source design system, delivers robust components for user identity display. The **Avatar and AvatarGroup components** provide a complete solution for showing individual users and stacked groups while maintaining consistent sizing, spacing, and accessibility standards. These components leverage a shared context architecture and StyleX styling to coordinate layout across the UI.

## Core Architecture of the Avatar Component

### Implementation Details in Avatar.tsx

In [`packages/core/src/Avatar/Avatar.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Avatar/Avatar.tsx), the Avatar component accepts `src`, `fallbackSrc`, `name`, `size`, and optional `status` props. The component resolves pixel dimensions through the `resolveSize` function, converting named sizes (like "medium" or "large") to numeric values via `AvatarSizeContext`.

The component implements a sophisticated fallback chain: it attempts to load the primary image, falls back to `fallbackSrc` if provided, then derives initials from the `name` prop, and finally displays a generic person icon if no text is available.

### Accessibility Features and Status Indicators

Accessibility is handled through ARIA attributes: the component applies `role="img"` with `aria-label` when a `name` or `alt` prop is supplied, otherwise it renders as decorative with `role="presentation"`. When using the `status` prop (typically with `AvatarStatusDot` from [`packages/core/src/Avatar/AvatarStatusDot.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Avatar/AvatarStatusDot.tsx)), the component renders a status indicator positioned at the bottom-right corner using dynamic style calculations.

## Building Stacked User Displays with AvatarGroup

### Context-Driven Sizing and Overlap

The `AvatarGroup` component in [`packages/core/src/AvatarGroup/AvatarGroup.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/AvatarGroup/AvatarGroup.tsx) manages stacked avatar layouts through `AvatarGroupContext`. This context shares `size`, `overlap`, and computed numeric values with all child avatars, ensuring consistent dimensions without prop drilling.

The overlap calculation uses `numericSize * OVERLAP_RATIO` (defaulting to 0.25), making avatars overlap proportionally based on their actual pixel dimensions. Children render as-is without introspection, allowing each avatar to maintain its own props such as individual status dots.

### Handling Overflow with AvatarGroupOverflow

For lists exceeding display limits, `AvatarGroupOverflow` in [`packages/core/src/AvatarGroup/AvatarGroupOverflow.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/AvatarGroup/AvatarGroupOverflow.tsx) consumes the group context via `useAvatarGroup()` to inherit sizing and spacing. It renders as a `<button>` when an `onClick` handler is provided, enabling interactive behaviors like opening a participant modal, or as a `<span>` for read-only displays. The component accepts custom children to override the default "+N" label.

## Practical Implementation Examples

### Basic Avatar with Initials Fallback

```tsx
import {Avatar} from '@astryxdesign/core/Avatar';

export const Simple = () => (
  <Avatar name="John Doe" size="medium" />
);

```

### Avatar with Image and Status Dot

```tsx
import {Avatar, AvatarStatusDot} from '@astryxdesign/core/Avatar';

export const WithImageAndStatus = () => (
  <Avatar
    src="https://i.pravatar.cc/150?img=1"
    name="Jane Smith"
    size="large"
    status={<AvatarStatusDot variant="success" label="Online" />}
  />
);

```

### Stacked Avatar Group with Overflow

```tsx
import {Avatar, AvatarGroup, AvatarGroupOverflow} from '@astryxdesign/core/Avatar';

const users = [
  {id: 1, src: 'https://i.pravatar.cc/150?img=2', name: 'Alice'},
  {id: 2, src: 'https://i.pravatar.cc/150?img=3', name: 'Bob'},
  {id: 3, src: 'https://i.pravatar.cc/150?img=4', name: 'Carol'},
  {id: 4, src: 'https://i.pravatar.cc/150?img=5', name: 'David'},
];

export const Group = () => (
  <AvatarGroup size="small">
    {users.slice(0, 3).map(u => (
      <Avatar key={u.id} src={u.src} name={u.name} />
    ))}
    <AvatarGroupOverflow count={users.length - 3} />
  </AvatarGroup>
);

```

### Interactive Overflow Button

```tsx
import {AvatarGroup, AvatarGroupOverflow, Avatar} from '@astryxdesign/core/Avatar';

export const ClickableGroup = () => {
  const handleShowAll = () => alert('Show all participants');

  return (
    <AvatarGroup size="medium">
      <Avatar src="https://i.pravatar.cc/150?img=6" name="User 1" />
      <Avatar src="https://i.pravatar.cc/150?img=7" name="User 2" />
      <AvatarGroupOverflow count={5} onClick={handleShowAll} />
    </AvatarGroup>
  );
};

```

### Custom Overflow Content

```tsx
import {AvatarGroup, AvatarGroupOverflow, Avatar} from '@astryxdesign/core/Avatar';

export const CustomOverflow = () => (
  <AvatarGroup size="small">
    <Avatar name="A" />
    <Avatar name="B" />
    <AvatarGroupOverflow count={12}>
      <span style={{fontWeight: 600}}>+12</span>
    </AvatarGroupOverflow>
  </AvatarGroup>
);

```

## Summary

- **Avatar** resolves sizing through `resolveSize` and `AvatarSizeContext`, supporting named sizes that convert to pixel values for consistent rendering.
- **Fallback chain** progresses from primary image to fallback image, then initials, and finally a generic icon, ensuring users always see visual identification.
- **AvatarGroup** uses `AvatarGroupContext` to share size and overlap values, calculating overlap as `numericSize * 0.25` for proportional stacking.
- **AvatarGroupOverflow** supports both interactive (button) and static (span) modes, with customizable content to replace the default count indicator.
- All components respect accessibility standards via ARIA roles and labels, and use StyleX for type-safe CSS-in-JS styling according to Astryx design tokens.

## Frequently Asked Questions

### How does the Avatar component handle image loading failures?

According to the source code in [`packages/core/src/Avatar/Avatar.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Avatar/Avatar.tsx), the Avatar implements a cascading fallback system: if the primary `src` fails to load, it attempts the `fallbackSrc` prop. If that also fails or is undefined, it extracts initials from the `name` prop. If no name is provided, it renders a generic person icon as the final fallback.

### Can I use Avatar outside of AvatarGroup without losing functionality?

Yes. While `AvatarGroup` provides `AvatarGroupContext` for coordinated sizing and overlap, the `Avatar` component functions independently using its own `size` prop and `AvatarSizeContext`. When used outside a group, it relies on the prop-based size resolution via `resolveSize` without requiring any group context providers.

### How do I customize the overlap amount between avatars in a group?

The overlap ratio is hardcoded in [`packages/core/src/AvatarGroup/AvatarGroup.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/AvatarGroup/AvatarGroup.tsx) as `OVERLAP_RATIO = 0.25`, meaning avatars overlap by 25% of their numeric size. To customize this, you would need to modify the source or wrap the component, as the current implementation calculates overlap as `numericSize * OVERLAP_RATIO` and passes this value through context to child avatars.

### What accessibility features are built into the Avatar and AvatarGroup components?

The Avatar component applies `role="img"` with an `aria-label` derived from the `name` or `alt` props when available, making it accessible to screen readers. If no descriptive text is provided, it defaults to `role="presentation"` to indicate decorative content. The AvatarGroupOverflow component renders as a semantic `<button>` when interactive, ensuring keyboard navigability, or as a `<span>` for static displays.