XDSAvatar@xds/core · Avatar

Usage

Avatar represents a person or team with a profile photo, initials, or a default icon. Use it in comment headers, contact lists, chat messages, user cards, and anywhere you need to identify someone visually.

Best practices

GuidancePractices
DoAlways pass a name so the avatar can show initials if the photo fails to load, and so screen readers can announce who it represents.
DoPick a size that matches the context — tiny or xsmall for inline mentions, small or medium for lists and cards, large for profile headers.
DoAdd a status dot when knowing someone's availability matters, like in chat or team views.
Don'tUse Avatar for logos, product images, or anything that isn't a person or team — use an image or icon instead.
Don'tForce a square or custom shape — avatars are always circular to stay consistent across the system.

Anatomy

ElementDescription
PhotoThe profile image, loaded from the src URL. Shown when available.
InitialsOne or two letters extracted from the name. Shown when no photo is available.
Default iconA generic person silhouette. Shown when there is no photo or name.
Status dotA small indicator in the bottom-right corner showing availability (online, away, busy).

Import

ts
import {XDSAvatar} from '@xds/core/Avatar'

Props

PropTypeDescription
src
stringPrimary image source URL.
fallbackSrc
stringFallback image when primary fails.
name
stringUser name for initials and alt text.
alt
stringAlt text (falls back to name).
size
XDSAvatarSize (default: 'small')Avatar size (named or numeric pixel value).
status
ReactNodeCorner content for status indicators.

Sub-components

Avatar is a compound component with 2 sub-components.

XDSAvatar

Displays a user avatar with image, initials fallback, and optional status indicator.
PropTypeDescription
src
stringPrimary image source URL.
fallbackSrc
stringFallback image when primary fails.
name
stringUser name for initials and alt text.
alt
stringAlt text (falls back to name).
size
XDSAvatarSize (default: 'small')Avatar size (named or numeric pixel value).
status
ReactNodeCorner content for status indicators.

XDSAvatarStatusDot

Size-aware status indicator dot that reads avatar size from context and scales proportionally.
PropTypeDescription
variant
'positive' | 'neutral' | 'negative' (default: 'positive')Semantic color variant of the dot.
label
stringAccessible label for screen readers.
icon
ReactNodeIcon centered inside the dot (hidden at tiny sizes).

Examples

Common configurations, variations, and states.
Avatar — Fallback ChainDemonstrates the avatar fallback chain: primary image, fallback image, initials, then default icon.
tsx
'use client';
import {XDSAvatar} from '@xds/core/Avatar';
import {XDSHStack, XDSVStack} from '@xds/core/Layout';
import {XDSText} from '@xds/core/Text';
export default function AvatarFallbackChain() {
return (
<XDSVStack gap={4}>
<XDSHStack gap={3} vAlign="center">
<XDSAvatar
src="https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-60.jpg"
name="Carol Davis"
size="medium"
/>
<XDSText type="supporting">Valid src</XDSText>
</XDSHStack>
<XDSHStack gap={3} vAlign="center">
<XDSAvatar
src="https://lookaside.facebook.com/assets/xds_oss/does-not-exist-primary.jpg"
fallbackSrc="https://lookaside.facebook.com/assets/xds_oss/illustration-horizontal-2.png"
name="Invalid User"
size="medium"
/>
<XDSText type="supporting">Invalid src, valid fallbackSrc</XDSText>
</XDSHStack>
<XDSHStack gap={3} vAlign="center">
<XDSAvatar
src="https://lookaside.facebook.com/assets/xds_oss/does-not-exist-primary.jpg"
fallbackSrc="https://lookaside.facebook.com/assets/xds_oss/does-not-exist-fallback.jpg"
name="Test User"
size="medium"
/>
<XDSText type="supporting">Both invalid, has name</XDSText>
</XDSHStack>
<XDSHStack gap={3} vAlign="center">
<XDSAvatar
src="https://lookaside.facebook.com/assets/xds_oss/does-not-exist-primary.jpg"
size="medium"
/>
<XDSText type="supporting">All invalid, no name</XDSText>
</XDSHStack>
</XDSVStack>
);
}
Avatar — GroupOverlap multiple avatars in a row to represent a group of people. Use for team lists, PR reviewers, or participant counts where you want to show faces without taking up much space.
tsx
'use client';
import {XDSAvatar} from '@xds/core/Avatar';
import {XDSStack} from '@xds/core/Layout';
import {XDSText} from '@xds/core/Text';
import * as stylex from '@stylexjs/stylex';
const USERS = [
{
name: 'Alex Daniels',
src: 'https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-05.jpg',
},
{
name: 'Ann Smith',
src: 'https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-30.jpg',
},
{
name: 'Carol Davis',
src: 'https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-60.jpg',
},
{
name: 'Gina Wilson',
src: 'https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-98.jpg',
},
{
name: 'Eve Park',
src: 'https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-125.jpg',
},
];
const groupStyles = stylex.create({
overlap: (offset: number) => ({
marginLeft: offset,
borderRadius: '50%',
border: '2px solid var(--color-background-surface, #fff)',
}),
});
export default function AvatarGroup() {
return (
<XDSStack direction="vertical" gap={8}>
<XDSStack direction="vertical" gap={3}>
<XDSText type="supporting" color="secondary">
Team members
</XDSText>
<XDSStack direction="horizontal" vAlign="center">
{USERS.map((user, i) => (
<XDSStack
direction="vertical"
key={user.name}
{...stylex.props(groupStyles.overlap(i === 0 ? 0 : -10))}>
<XDSAvatar src={user.src} name={user.name} size="medium" />
</XDSStack>
))}
<XDSStack
direction="vertical"
{...stylex.props(groupStyles.overlap(-10))}>
<XDSAvatar name="+3" size="medium" />
</XDSStack>
</XDSStack>
</XDSStack>
<XDSStack direction="vertical" gap={3}>
<XDSText type="supporting" color="secondary">
Larger group
</XDSText>
<XDSStack direction="horizontal" vAlign="center">
{USERS.slice(0, 3).map((user, i) => (
<XDSStack
direction="vertical"
key={user.name}
{...stylex.props(groupStyles.overlap(i === 0 ? 0 : -14))}>
<XDSAvatar src={user.src} name={user.name} size="medium" />
</XDSStack>
))}
<XDSStack
direction="vertical"
{...stylex.props(groupStyles.overlap(-14))}>
<XDSAvatar name="+8" size="medium" />
</XDSStack>
</XDSStack>
</XDSStack>
</XDSStack>
);
}
Avatar — InitialsShow initials instead of a photo. The avatar extracts the first and last initials from the name automatically. Use when you only have a user name, like in anonymous accounts or new user onboarding.
tsx
'use client';
import {XDSAvatar} from '@xds/core/Avatar';
import {XDSStack} from '@xds/core/Layout';
import {XDSText} from '@xds/core/Text';
const NAMES = [
{name: 'John Doe', note: 'First + last'},
{name: 'Alice', note: 'Single name'},
{name: 'Bob Smith Johnson', note: 'Multi-word'},
{name: 'Dr. Sarah Connor', note: 'Prefixed'},
];
export default function AvatarInitialsFallback() {
return (
<XDSStack direction="horizontal" gap={6} vAlign="center">
{NAMES.map(({name, note}) => (
<XDSStack key={name} direction="vertical" gap={2} hAlign="center">
<XDSAvatar name={name} size="medium" />
<XDSText type="supporting" color="secondary">
{note}
</XDSText>
</XDSStack>
))}
</XDSStack>
);
}
Avatar — PhotoShow a profile photo at different sizes. Use when you have a user photo URL. If the image fails to load, initials are shown instead.
tsx
'use client';
import {XDSAvatar} from '@xds/core/Avatar';
import {XDSStack} from '@xds/core/Layout';
export default function AvatarWithImage() {
return (
<XDSStack direction="horizontal" gap={4} vAlign="center">
<XDSAvatar
src="https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-05.jpg"
name="Alex Daniles"
size="tiny"
/>
<XDSAvatar
src="https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-30.jpg"
name="Ann Smith"
size="small"
/>
<XDSAvatar
src="https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-60.jpg"
name="Carol Davis"
size="medium"
/>
<XDSAvatar
src="https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-98.jpg"
name="Gina Wilson"
size="large"
/>
</XDSStack>
);
}
Avatar — Status DotAdd a status dot to an avatar to show whether someone is online, away, or busy. Use in chat, messaging, or any UI where knowing availability matters.
tsx
'use client';
import {XDSAvatar, XDSAvatarStatusDot} from '@xds/core/Avatar';
import {XDSStack} from '@xds/core/Layout';
export default function AvatarWithStatus() {
return (
<XDSStack direction="horizontal" gap={4} vAlign="center">
<XDSAvatar
src="https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-05.jpg"
name="Alex Daniels"
size="large"
status={<XDSAvatarStatusDot variant="positive" label="Online" />}
/>
<XDSAvatar
src="https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-30.jpg"
name="Ann Smith"
size="large"
status={<XDSAvatarStatusDot variant="neutral" label="Offline" />}
/>
<XDSAvatar
src="https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-60.jpg"
name="Carol Davis"
size="large"
status={<XDSAvatarStatusDot variant="negative" label="Busy" />}
/>
</XDSStack>
);
}
Avatar — User CardPlace an avatar next to a name and role to create a user card row. Use for comment headers, contact lists, profile sections, or anywhere you need to identify a person at a glance.
tsx
'use client';
import {XDSAvatar, XDSAvatarStatusDot} from '@xds/core/Avatar';
import {XDSStack} from '@xds/core/Layout';
import {XDSText} from '@xds/core/Text';
const USERS = [
{
name: 'Alex Daniels',
role: 'Engineering Lead',
variant: 'positive' as const,
src: 'https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-05.jpg',
},
{
name: 'Ann Smith',
role: 'Product Designer',
variant: 'neutral' as const,
src: 'https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-30.jpg',
},
{
name: 'Carol Davis',
role: 'Engineering Manager',
variant: 'negative' as const,
src: 'https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-60.jpg',
},
];
export default function AvatarUserCard() {
return (
<XDSStack direction="vertical" gap={4}>
{USERS.map(user => (
<XDSStack
key={user.name}
direction="horizontal"
gap={3}
vAlign="center">
<XDSAvatar
src={user.src}
name={user.name}
size="medium"
status={
<XDSAvatarStatusDot variant={user.variant} label={user.variant} />
}
/>
<XDSStack direction="vertical" gap={0}>
<XDSText type="body" weight="bold">
{user.name}
</XDSText>
<XDSText type="supporting" color="secondary">
{user.role}
</XDSText>
</XDSStack>
</XDSStack>
))}
</XDSStack>
);
}

Showcase source

tsx
'use client';
import {XDSAvatar, XDSAvatarStatusDot} from '@xds/core/Avatar';
import {XDSStack} from '@xds/core/Layout';
export default function AvatarShowcase() {
return (
<XDSStack direction="horizontal" gap={4} vAlign="center">
<XDSAvatar
name="Ann Smith"
size="large"
src="https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-30.jpg"
status={<XDSAvatarStatusDot variant="positive" label="Online" />}
/>
<XDSAvatar
name="Alex Daniels"
size="large"
src="https://lookaside.facebook.com/assets/vs_datakit_profile_photos_t66173184/VS-Design-Tools-Datakit-05.jpg"
/>
<XDSAvatar name="Sam Chen" size="large" />
<XDSAvatar
name="Taylor Nguyen"
size="large"
status={<XDSAvatarStatusDot variant="negative" label="Online" />}
/>
</XDSStack>
);
}