Skip to main content

An avatar represents a user profile picture. It displays an image or fallback content in a container.

Avatar supports fallback text or elements when the image fails to load or when no image is provided.

Loading...

Installation

Install the avatar package:

npm install @zag-js/avatar @zag-js/react # or yarn add @zag-js/avatar @zag-js/react

Anatomy

Check the avatar anatomy and part names.

Each part includes a component-scoped data attribute to help identify it in the DOM.

Usage

Import the avatar package:

import * as avatar from "@zag-js/avatar"

The avatar package exports two key functions:

  • machine - State machine logic.
  • connect - Maps machine state to JSX props and event handlers.

Pass a unique id to useMachine so generated element ids stay predictable.

Then use the framework integration helpers:

import * as avatar from "@zag-js/avatar" import { useMachine, normalizeProps } from "@zag-js/react" import { useId } from "react" function Avatar() { const service = useMachine(avatar.machine, { id: useId() }) const api = avatar.connect(service, normalizeProps) return ( <div {...api.getRootProps()}> <span {...api.getFallbackProps()}>PA</span> <img alt="PA" src={src} {...api.getImageProps()} /> </div> ) }

Loading status

The image loading status is loading, loaded, or error. Read the current value from api.status, or react to changes with onStatusChange.

const service = useMachine(avatar.machine, { onStatusChange(details) { // details => { status: "loading" | "error" | "loaded" } }, })

Updating the image source

You own the image src; the machine observes the rendered image and owns its loading lifecycle. Update src however you normally would and the machine reacts, resetting to loading and then to loaded or error.

This holds for srcSet and <picture> too, since the machine watches the element rather than a value you hand it.

const [src, setSrc] = useState(initialSrc) <img alt="" src={src} {...api.getImageProps()} />

Two cases the machine already covers, so you don't have to:

  • An image served from cache can finish loading before the load handler is attached. The machine checks whether the image is already complete.
  • Setting src to a URL that previously failed retries it, rather than staying in the error state.

If the image is loaded by something that doesn't fire load and error on the element itself, drive the lifecycle with api.setLoaded() and api.setError().

Styling guide

Each part includes a component-scoped data attribute you can target in CSS.

[data-avatar-root] { /* Styles for the root part */ } [data-avatar-image] { /* Styles for the image part */ } [data-avatar-fallback] { /* Styles for the fallback part */ }

Creating a component

Create your avatar component by abstracting the machine into your own component.

Usage

import { Avatar } from "./your-avatar" function Demo() { return ( <Avatar src="https://avatars.githubusercontent.com/u/139426" name="John Doe" /> ) }

Implementation

Use the splitProps utility to separate the machine's props from the component's props.

import * as avatar from "@zag-js/avatar" import { useMachine, normalizeProps } from "@zag-js/react" import { useId } from "react" export interface AvatarProps extends Omit<avatar.Context, "id"> { /** * The src of the avatar image */ src?: string /** * The srcSet of the avatar image */ srcSet?: string /** * The name of the avatar */ name: string } function Avatar(props: AvatarProps) { const [machineProps, localProps] = avatar.splitProps(props) const service = useMachine(avatar.machine, { id: useId(), ...machineProps, }) const api = avatar.connect(service, normalizeProps) return ( <div {...api.getRootProps()}> <span {...api.getFallbackProps()}>{getInitials(localProps.name)}</span> <img alt="PA" src={localProps.src} srcSet={localProps.srcSet} {...api.getImageProps()} /> </div> ) } function getInitials(name: string) { return name .split(" ") .map((word) => word[0]) .join("") }

Methods and Properties

Machine Context

The avatar machine exposes the following context properties:

  • onStatusChange((details: StatusChangeDetails) => void) | undefinedFunctional called when the image loading status changes.
  • idsElementIds | undefinedThe ids of the elements in the avatar. Useful for composition.
  • idstringThe unique identifier of the machine.
  • getRootNode(() => ShadowRoot | Document | Node) | undefinedA root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.
  • dir"ltr" | "rtl" | undefinedThe document's text/writing direction.

Machine API

The avatar api exposes the following methods:

  • statusLoadStatusThe current image loading status.
  • loadedbooleanWhether the image is loaded.
  • setLoadedVoidFunctionFunction to set loaded state.
  • setErrorVoidFunctionFunction to set error state.

Data Attributes

Image
data-avatar-image
<uid>
data-state
"visible" | "hidden"
Fallback
data-avatar-fallback
<uid>
data-state
"hidden" | "visible"
Edit this page on GitHub