Avatar and Item
Use avatar and item with the current published Askr packages.
@askrjs/ui/avatar0.0.13@askrjs/themes/avatar0.0.13@askrjs/themes/item0.0.13
How to use avatar and item
Avatar and Item should use the standard themed surface unless the application is deliberately implementing its own design system on top of @askrjs/ui.
- Import the themed component from @askrjs/themes/components; use @askrjs/ui directly only when building a custom visual system.
- Keep avatar and item labels, state, and application actions visible at the call site instead of styling internal DOM nodes.
- Verify keyboard behavior, focus movement or return, disabled state, and both standard themes.
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@askrjs/themes/components';
<Card>
<CardHeader><CardTitle>Project health</CardTitle><CardDescription>Updated just now</CardDescription></CardHeader>
<CardContent><ProjectHealth /></CardContent>
</Card>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 token-driven density and background changes, consistent with the rest of the theme's `--ak-density-*` scale, so a compact `Item` list lines up visually with compact buttons and inputs elsewhere.
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.