# Avatar and Item

> Avatar and Item: anatomy, keyboard behavior, state, and theming in Askr.

Source: [https://askrjs.com/docs/components/avatar-and-item](https://askrjs.com/docs/components/avatar-and-item)

Status: stable. Packages: @askrjs/ui/avatar, @askrjs/themes/avatar, @askrjs/themes/item.

**Published packages are authoritative.** Examples may lag behind a published contract. When guidance differs, verify the exports and TypeScript declarations in your installed package, then file an issue.

## Example

```tsx
import { Avatar, AvatarFallback, AvatarImage, Item, ItemContent, ItemDescription, ItemMedia, ItemTitle } from '@askrjs/themes/components';

<Item>
  <ItemMedia><Avatar><AvatarImage src={owner.avatarUrl} alt="" /><AvatarFallback>{owner.initials}</AvatarFallback></Avatar></ItemMedia>
  <ItemContent><ItemTitle>{owner.name}</ItemTitle><ItemDescription>{owner.role}</ItemDescription></ItemContent>
</Item>
```

## Published props

Generated from the TypeScript declarations shipped by the installed package.

### `AvatarAsChildProps`

Import from `@askrjs/ui/avatar`.

- `asChild: true;`
- `children: JSXElement;`
- `id?: string | undefined;`
- `ref?: Ref<Element>;`

### `AvatarFallbackAsChildProps`

Import from `@askrjs/ui/avatar`.

- `asChild: true;`
- `children: JSXElement;`
- `ref?: Ref<Element>;`

### `AvatarFallbackOwnProps`

Import from `@askrjs/ui/avatar`.

- `children?: unknown;`

### `AvatarFallbackProps`

Import from `@askrjs/ui/avatar`.

- `asChild?: false | undefined;`
- `children?: unknown;`
- `ref?: Ref<HTMLSpanElement>;`

### `AvatarImageOwnProps`

Import from `@askrjs/ui/avatar`.

- `alt: string;`
- `onLoadingStatusChange?: ((status: AvatarLoadingStatus) => void) | undefined;`
- `src?: string | undefined;`

### `AvatarImageProps`

Import from `@askrjs/ui/avatar`.

- `alt: string;`
- `onLoadingStatusChange?: ((status: AvatarLoadingStatus) => void) | undefined;`
- `ref?: Ref<HTMLImageElement>;`
- `src?: string | undefined;`

### `AvatarOwnProps`

Import from `@askrjs/ui/avatar`.

- `children?: unknown;`
- `id?: string | undefined;`

### `AvatarProps`

Import from `@askrjs/ui/avatar`.

- `asChild?: false | undefined;`
- `children?: unknown;`
- `id?: string | undefined;`
- `ref?: Ref<HTMLSpanElement>;`

## Purpose

Avatar and Item solve two different problems that tend to show up together: Avatar renders a person or entity's image with a graceful fallback, and Item lays out a single row of content — icon or avatar, title, description, and trailing actions — the kind of row you see in a user list, a notification, or a search result. Avatar is a real headless primitive from `@askrjs/ui/avatar` with a themed skin on top; Item exists only in `@askrjs/themes`, since a static content row doesn't need behavior of its own beyond what its interactive children provide.

## Install and import

Import `Avatar`, `AvatarImage`, and `AvatarFallback` from `@askrjs/ui/avatar` if you're building your own visual treatment, or from `@askrjs/themes/avatar` for the pre-styled version — both re-export the same underlying components, so you're choosing between headless and themed, not between two different APIs. `Item`, `ItemGroup`, `ItemHeader`, `ItemMedia`, `ItemContent`, `ItemTitle`, `ItemDescription`, `ItemActions`, and `ItemFooter` all come from `@askrjs/themes/item`, since there's no `@askrjs/ui` counterpart to import instead.

## Live examples

A typical avatar is `<Avatar><AvatarImage src={url} alt={name} /><AvatarFallback>{initials}</AvatarFallback></Avatar>` — the fallback renders automatically while the image is loading or if it errors. Drop that into an `ItemMedia` slot inside an `Item`, pair it with `ItemContent` holding `ItemTitle` and `ItemDescription`, and add `ItemActions` for a trailing button or menu — that's the standard "user row" pattern used across account lists, comment threads, and search results. Wrap several `Item`s in `ItemGroup` when they belong together as a list.

## Anatomy

Avatar is three pieces: the `Avatar` root (a `span`), `AvatarImage` (an `img` with required `alt`), and `AvatarFallback` (a `span` shown before the image loads or after it errors). Item is a row split into `ItemMedia` (for the avatar or icon), `ItemContent` (holding `ItemTitle` and `ItemDescription`), and optional `ItemHeader`/`ItemFooter`/`ItemActions` slots — `ItemGroup` wraps a set of `Item`s into a list container.

## State model

Avatar tracks one real piece of state: `AvatarLoadingStatus`, typed as `'idle' | 'loading' | 'loaded' | 'error'`, exposed through `AvatarImage`'s `onLoadingStatusChange` callback so you can react to load failures yourself. Item's state is purely presentational — `active?: boolean` and `variant?: 'default' | 'outline' | 'muted'` control appearance, but Item doesn't manage selection or interaction state; if a row needs to respond to clicks or track selected-ness, that logic lives in your own component or in whatever interactive element you put inside it.

## Keyboard and accessibility

`AvatarImage` requires an `alt` prop at the type level — there's no way to render an image avatar without supplying alt text, which the a11y contract documents as `requiresAlt: true`. `AvatarFallback` is marked `visibleBeforeImageLoad: true` in that same contract, so screen reader users don't hit a blank state while the image is in flight. Item itself has no keyboard model since it's not a control — if a row is meant to be actionable, put a real `<button>` or link inside `ItemActions` or make the whole row an anchor rather than relying on a synthetic click handler.

## Styling and tokens

Both components mark their internal parts with `data-slot` hooks — `data-avatar`, `data-avatar-image`, `data-avatar-fallback` for Avatar per its `AVATAR_A11Y_CONTRACT` — which is the surface you should target with CSS rather than reaching into internal structure. Item's `size` prop (`'default' | 'sm' | 'xs'`) and `variant` prop map to `data-size`/`data-variant` attributes that drive gap, padding, and background changes off the theme's general `--ak-space-*` scale — not the separate `--ak-density-*` family, which is scoped to form-control sizing rather than list rows — so a compact `Item` list still lines up visually with the rest of the theme's spacing rhythm, just not through that specific token family.

## API

`AvatarImageProps` accepts `src?: string`, a required `alt: string`, and `onLoadingStatusChange?: (status: AvatarLoadingStatus) => void`, layered on top of native `img` attributes (minus the ones it manages itself). `AvatarProps` and `AvatarFallbackProps` are otherwise just `children` plus standard box props. `Item` takes `active?: boolean`, `size?: 'default' | 'sm' | 'xs'`, and `variant?: 'default' | 'outline' | 'muted'` on top of the generic `CatalogComponentProps` (`as`, `asChild`, `class`, `children`) shared by every themed catalog component; the surrounding `Item*` parts (`ItemGroup`, `ItemHeader`, `ItemMedia`, `ItemContent`, `ItemTitle`, `ItemDescription`, `ItemActions`, `ItemFooter`) only take that same generic prop set.

## Edge cases

If `AvatarImage` never resolves — a broken URL, a slow network, an offline user — the fallback stays visible indefinitely, so make sure your `AvatarFallback` content (initials, a generic icon) is something reasonable to show long-term, not just a placeholder. Long titles or descriptions inside `ItemContent` will wrap by default; if you need truncation, that's a CSS concern you own, same as Card. An `Item` with no `ItemMedia` still lays out correctly — the media slot is optional, not required scaffolding.

## Related pages

Card is the right fit once a row grows past "single line of content plus actions" into something with its own header, body, and footer regions. Table and Data Table are worth checking when you're rendering many rows of structured, sortable data rather than a loose list. NavigationMenu and Sidebar's `SidebarMenuItem` cover navigation-flavored rows, which overlap with Item conceptually but carry their own interaction model.

## Documentation navigation

[Previous](https://askrjs.com/docs/components/card/index.md) | [Next](https://askrjs.com/docs/components/typography-and-display-primitives/index.md)
