Components
Item
A flexible list-row primitive that composes media, title, description, and action slots into a single aligned row — the building block for settings lists, file rows, and feeds.
Basic usage
Compose ItemMedia, ItemContent, and ItemActions inside an Item.
Updated 3 days ago · 2.4 MB
Variants
Three surface treatments — default for in-list rows, outline for standalone cards, and muted for inactive state.
Transparent — sits flush in a list.
Bordered — reads as a standalone card.
Soft fill — useful for inactive rows.
Media slots
ItemMedia renders a leading affordance: icon boxes a Lucide glyph, while image clips an avatar or thumbnail.
A boxed 32px icon affordance.
A 40px avatar or thumbnail.
Grouped lists
Wrap rows in an ItemGroup (a role="list" container) and divide them with ItemSeparator. Use asChild to make a whole row a link.
Header and footer bands
Item is a flex-wrap row, and ItemHeader and ItemFooter are basis-full — they take a full line of their own above and below the media/content/actions line, with their children pushed to opposite ends. Use them for metadata that belongs to the row but does not belong beside the title.
Due 31 March · $4,200
Props
Item — the row container.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'outline' | 'muted' | 'default' | Surface treatment of the row — transparent, bordered, or soft-filled with bg-muted/50. |
size | 'default' | 'sm' | 'default' | default is p-4 gap-4; sm tightens the gap to 2.5 and takes its vertical padding from the --list-item-py token, so it follows the density axis. |
asChild | boolean | false | Merge props onto the child element instead of rendering a div — use to make the whole row a link or button. |
className | string | — | Additional Tailwind classes to merge. |
...rest | React.ComponentProps<'div'> | — | All native div props are forwarded. |
ItemMedia — the leading affordance.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'icon' | 'image' | 'default' | default is unstyled; icon renders a 32px boxed slot; image renders a 40px clipped, rounded slot for an <img>. |
className | string | — | Additional Tailwind classes to merge. |
...rest | React.ComponentProps<'div'> | — | All native div props are forwarded. |
ItemSeparator — a preset Separator, so it takes the same props.
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | 'horizontal' | 'vertical' | 'horizontal' | Forwarded to Separator. ItemSeparator presets it to horizontal because it divides stacked rows; pass it explicitly only if you really need a vertical rule. |
decorative | boolean | true | Forwarded to Separator — leave it true so the rule is skipped by screen readers and the list role stays clean. |
className | string | — | Merged after the built-in my-0, so a margin override wins. |
The remaining slots (ItemGroup, ItemContent, ItemTitle, ItemActions, ItemHeader, ItemFooter) forward native <div> props only; ItemDescription renders a <p>. The itemVariants and itemMediaVariants cva helpers are exported for building a row that has to match without being an Item.
Accessibility
ItemGroupappliesrole="list", butItemdoes not addrole="listitem"— a list whose children are not list items is announced as empty, so supply the role yourself. On a plain row put it on theItem; on anasChildrow the prop would land on the<a>and replace its link role, so wrap that row in<div role="listitem">instead.- Use
asChildwith an<a>or<button>so the interactive row is a real, focusable element with native keyboard support. - Interactive rows receive a
focus-visiblering using the brand gold ring token, visible on keyboard navigation and hidden on click. - Decorative media (icons, avatars) should be hidden from screen readers — give
<img>an emptyalt=""and letItemTitlecarry the accessible name. ItemTitleis a<div>, not a heading — a long list of rows should not add dozens of entries to the document outline. If a row genuinely is a section heading, render one inside it.ItemDescriptionis clamped to two lines, so never put information there that has no other home. Links inside it are underlined, not colour-only.