bx

Item

A composable row for lists with media, content and actions.

JD
John Doe

john@example.com

AS
Alice Smith

alice@example.com

tsx
<div className="w-full max-w-md space-y-2">
  <Item>
    <ItemMedia><Avatar><AvatarFallback>JD</AvatarFallback></Avatar></ItemMedia>
    <ItemContent>
      <ItemTitle>John Doe</ItemTitle>
      <ItemDescription>john@example.com</ItemDescription>
    </ItemContent>
    <ItemActions><Button size="sm" variant="outline">Follow</Button></ItemActions>
  </Item>
  <Item>
    <ItemMedia><Avatar><AvatarFallback>AS</AvatarFallback></Avatar></ItemMedia>
    <ItemContent>
      <ItemTitle>Alice Smith</ItemTitle>
      <ItemDescription>alice@example.com</ItemDescription>
    </ItemContent>
    <ItemActions><Button size="sm" variant="outline">Follow</Button></ItemActions>
  </Item>
</div>

Item is a composable row for heterogeneous lists (settings, contacts, notifications, dashboard cards). Media (icon/avatar/thumbnail) + Content (Title + Description) + Actions (buttons, switch, badge).

It differs from Card: Item is horizontal, dense, and meant to be stacked in a list. Card is a block, more visual.

Installation

Terminal
$ bext ui add item

Usage

tsx
import { Item, ItemMedia, ItemContent, ItemTitle, ItemDescription, ItemActions, Avatar, AvatarFallback, Button } from "@bext-stack/ui/primitives"

<Item>
  <ItemMedia><Avatar><AvatarFallback>JD</AvatarFallback></Avatar></ItemMedia>
  <ItemContent>
    <ItemTitle>John Doe</ItemTitle>
    <ItemDescription>john@example.com</ItemDescription>
  </ItemContent>
  <ItemActions><Button size="sm" variant="outline">Follow</Button></ItemActions>
</Item>

Anatomy

<Item>
  ├── <ItemMedia><Avatar /></ItemMedia>       // optional
  ├── <ItemContent>
  │   ├── <ItemTitle>John Doe</ItemTitle>
  │   └── <ItemDescription>john@example.com</ItemDescription>
  └── <ItemActions><Button /></ItemActions>   // optional

<ItemGroup>                                   // role="list" wrapper for a stack of Items
  ├── <Item>...</Item>
  ├── <ItemSeparator />
  └── <Item>...</Item>

API Reference

Item

Prop Type Default Description
variant "default" | "outline" | "muted" "default" default: transparent. outline: visible border. muted: bg-muted/50.
size "default" | "sm" "default" default: gap-4 p-4. sm: gap-2.5 px-4 py-3.
href string — When set, the row is rendered as an <a> instead of a <div>.
children ReactNode — ItemMedia, ItemContent and ItemActions, in that order.

ItemMedia

Prop Type Default Description
variant "default" | "icon" | "image" "default" icon: 32px bordered muted square. image: 40px thumbnail that crops its <img>.
children ReactNode — Left slot (avatar, icon, thumbnail).

ItemContent

Prop Type Default Description
children ReactNode — Center: stacked Title + Description.

ItemTitle

Prop Type Default Description
children ReactNode — Primary line, text-sm font-medium. Rendered as a <div>.

ItemDescription

Prop Type Default Description
children ReactNode — Muted, text-sm, clamped to two lines. Rendered as a <p>.

ItemActions

Prop Type Default Description
children ReactNode — Right slot: buttons, switch, badge.

ItemGroup

Prop Type Default Description
children ReactNode — Stack of Items in a flex column with role="list".

ItemSeparator

Prop Type Default Description
className string — 1px line with role="separator" between two Items.

ItemHeader / ItemFooter

Prop Type Default Description
children ReactNode — Full-width row (basis-full, justify-between) above or below the main row.

Data Attributes

Attributes you can target in custom CSS to override the style for each state.

Attribute On Values Description
data-slot every sub-component "item" | "item-media" | "item-content" | "item-title" | "item-description" | "item-actions" | "item-group" | "item-separator" | "item-header" | "item-footer" Stable selector for custom styling.
data-variant Item, ItemMedia see the variant prop Reflects the variant prop.
data-size Item "default" | "sm" Reflects the size prop.

Accessibility

ItemGroup sets role="list" on the container. Item sets no role and has no prop to add one, so the rows are not announced as list items: if the list semantics matter, write your own <ul> with one Item per <li> instead of using ItemGroup.