useContactAvatar
A React hook that encapsulates the logic for determining the appropriate avatar content, photo, name initials, or fallback icon, based on contact details and optional icon preferences. Designed to be used alongside the EDS Avatar component, it keeps avatar rendering logic reusable across multiple components without duplicating business logic.
Quick Start
- Installation
npm install @adaptavant/contacts-avatar- Import
import { useContactAvatar } from '@adaptavant/contacts-avatar';
Key Features
A hook that resolves the correct avatar representation from a contact's details:
- Photo priority — When a
photoIDis present, it always takes precedence over name or icon, rendering anAvatarImage. - Name resolution chain — When no photo is available, the hook resolves a display name in priority order:
fullName→firstName/middleName/lastName→companyName→email. The resolved name is passed toAvatarso EDS auto-generates initials. - Icon fallback — When no resolvable name exists (or the contact category is
'company'), the hook renders anAvatarIcon. Provide a customavatarIconprop to override the defaultProfileIcon. - HTML sanitization — Contact names are decoded and stripped of HTML/script tags before rendering to guard against XSS.
- "Unknown" contact handling — Contacts explicitly named
'unknown'or'#unknown'are treated as empty and fall through to the icon fallback. - Separation of concerns — The hook returns plain
nameandchildrenprops ready to spread onto<Avatar>, so the hook is fully decoupled from sizing and styling decisions.
With Photo
When photoID is present on the contact, the hook returns an AvatarImage as children. The image always takes priority over any name or icon.
const avatarProps = useContactAvatar({
contactDetails: {
fullName: 'John Doe',
photoID: 'https://i.pravatar.cc/150?img=12',
category: 'person',
},
});
return <Avatar {...avatarProps} size="40" />;
With Name
When no photo is available, the hook resolves a display name from the contact. The EDS Avatar component automatically renders initials from the resolved name. Full name takes priority; individual name parts (firstName, middleName, lastName) are used as a fallback.
const avatarPropsFullName = useContactAvatar({
contactDetails: { fullName: 'Jane Smith', category: 'person' },
});
const avatarPropsFirstLast = useContactAvatar({
contactDetails: { firstName: 'Alice', lastName: 'Johnson', category: 'person' },
});
return (
<Stack className="gap-4">
<Avatar {...avatarPropsFullName} size="40" />
<Avatar {...avatarPropsFirstLast} size="40" />
</Stack>
);
With Company Name
When a contact has no personal name fields, the hook falls back to companyName for the avatar display.
const avatarProps = useContactAvatar({
contactDetails: {
companyName: 'ACME Corporation',
category: 'person',
},
});
return <Avatar {...avatarProps} size="40" />;
With Email Fallback
When neither name nor company name is available, the hook attempts to derive a display name from the contact's linkedContactMethods. The primary email is checked first, then non-primary email, and finally the login field. The extracted name is passed to Avatar for initials generation.
const avatarPropsEmail = useContactAvatar({
contactDetails: {
linkedContactMethods: [
{ type: 'email', primary: true, value: 'john.doe@example.com' },
],
category: 'person',
},
});
const avatarPropsLogin = useContactAvatar({
contactDetails: {
login: 'wane.smith@example.com',
category: 'person',
},
});
return (
<Stack className="gap-4">
<Avatar {...avatarPropsEmail} size="40" />
<Avatar {...avatarPropsLogin} size="40" />
</Stack>
);
With Default Icon
When no resolvable name exists, the hook renders an AvatarIcon with the default ProfileIcon. This covers cases like empty contacts, contacts named 'unknown', or contacts with the 'company' category.
const avatarPropsEmpty = useContactAvatar({
contactDetails: { category: 'person' },
});
const avatarPropsUnknown = useContactAvatar({
contactDetails: { fullName: 'unknown', category: 'person' },
});
return (
<Stack className="gap-4">
<Avatar {...avatarPropsEmpty} size="40" />
<Avatar {...avatarPropsUnknown} size="40" />
</Stack>
);
With Custom Icon
Pass an avatarIcon function to override the default ProfileIcon used when no name can be resolved. The custom icon receives no props — it is a zero-argument function that returns a JSX element.
const avatarProps = useContactAvatar({
contactDetails: { category: 'person' },
avatarIcon: () => <ProfileIcon />,
});
return <Avatar {...avatarProps} size="40" />;
API Reference
useContactAvatar
Parameters
| Parameter | Default | Description |
|---|---|---|
contactDetails? | undefined | ContactDetailsThe contact whose avatar should be resolved. All fields are optional — the hook degrades gracefully to an icon when nothing is provided. |
contactDetails.fullName? | undefined | stringFull display name. Takes priority over individual name parts when present. |
contactDetails.firstName? | undefined | stringUsed alongside middleName and lastName to construct a full name when fullName is absent. |
contactDetails.middleName? | undefined | stringMiddle name, included in the constructed full name when present. |
contactDetails.lastName? | undefined | stringLast name, included in the constructed full name when present. |
contactDetails.companyName? | undefined | stringCompany name used as a fallback when no personal name fields are available. |
contactDetails.photoID? | undefined | stringURL of the contact's profile photo. When set, the hook always returns an AvatarImage regardless of other fields. |
contactDetails.linkedContactMethods? | [] | LinkedContactMethods[]Array of contact methods. The primary email is used as a name fallback when name and company fields are all empty. |
contactDetails.login? | undefined | stringLogin identifier (typically an email). Used as a last-resort name fallback when linkedContactMethods yields nothing. |
contactDetails.category? | undefined | stringContact category. When set to 'company', the hook bypasses all name resolution and returns an empty name, triggering the icon fallback. |
avatarIcon? | ProfileIcon | () => JSX.ElementCustom icon component rendered inside AvatarIcon when no name or photo can be resolved. Must be a zero-argument function returning a JSX element. |
Return value
| Property | Type | Description |
|---|---|---|
name | string | The resolved display name, or an empty string when no name can be determined. Pass directly to the name prop of Avatar. |
children | ReactNode | Either an AvatarImage (when photoID is set), an AvatarIcon (when no name is resolved), or null (when Avatar should render initials from name). Spread onto Avatar via {...avatarProps}. |
Style API
Our design system components include style props that allow you to easily customize different parts of each component to match your design needs.
Please refer to the Style API documentation for more insights.