Avatar
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.
Installation
Install the avatar package:
npm install @zag-js/avatar @zag-js/react # or yarn add @zag-js/avatar @zag-js/react
npm install @zag-js/avatar @zag-js/solid # or yarn add @zag-js/avatar @zag-js/solid
npm install @zag-js/avatar @zag-js/vue # or yarn add @zag-js/avatar @zag-js/vue
npm install @zag-js/avatar @zag-js/svelte # or yarn add @zag-js/avatar @zag-js/svelte
Anatomy
Check the avatar anatomy and part names.
Each part includes a
data-partattribute to help identify them 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
idtouseMachineso 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" function Avatar() { const service = useMachine(avatar.machine, { id: "1" }) const api = avatar.connect(service, normalizeProps) return ( <div {...api.getRootProps()}> <span {...api.getFallbackProps()}>PA</span> <img alt="PA" src={src} {...api.getImageProps()} /> </div> ) }
import * as avatar from "@zag-js/avatar" import { useMachine, normalizeProps } from "@zag-js/solid" function Avatar() { const service = useMachine(avatar.machine, { id: "1" }) const api = createMemo(() => avatar.connect(service, normalizeProps)) return ( <div {...api().getRootProps()}> <span {...api().getFallbackProps()}>PA</span> <img alt="PA" src={src} {...api().getImageProps()} /> </div> ) }
<script setup> import * as avatar from "@zag-js/avatar" import { normalizeProps, useMachine } from "@zag-js/vue" import { computed } from "vue" const service = useMachine(avatar.machine, { id: "1" }) const api = computed(() => avatar.connect(service, normalizeProps)) </script> <template> <div v-bind="api.getRootProps()"> <span v-bind="api.getFallbackProps()">PA</span> <img alt="PA" :src="src" v-bind="api.getImageProps()" /> </div> </template>
<script lang="ts"> import * as avatar from "@zag-js/avatar" import { useMachine, normalizeProps } from "@zag-js/svelte" const id = $props.id() const service = useMachine(avatar.machine, ({ id })) const api = $derived(avatar.connect(service, normalizeProps)) </script> <div {...api.getRootProps()}> <span {...api.getFallbackProps()}>PA</span> <img alt="PA" src={src} {...api.getImageProps()} /> </div>
Listening for loading status changes
When the image loads or fails, onStatusChange is invoked.
const service = useMachine(avatar.machine, { onStatusChange(details) { // details => { status: "error" | "loaded" } }, })
Updating the image source programmatically
Use api.setSrc when the image source changes after mount.
api.setSrc(nextSrc)
Styling guide
Each avatar part includes a data-part attribute you can target in CSS.
[data-scope="avatar"][data-part="root"] { /* Styles for the root part */ } [data-scope="avatar"][data-part="image"] { /* Styles for the image part */ } [data-scope="avatar"][data-part="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" 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) => voidFunctional called when the image loading status changes.idsPartial<{ root: string; image: string; fallback: string; }>The ids of the elements in the avatar. Useful for composition.idstringThe unique identifier of the machine.getRootNode() => ShadowRoot | Node | DocumentA root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.dir"ltr" | "rtl"The document's text/writing direction.
Machine API
The avatar api exposes the following methods:
loadedbooleanWhether the image is loaded.setSrc(src: string) => voidFunction to set new src.setLoadedVoidFunctionFunction to set loaded state.setErrorVoidFunctionFunction to set error state.