---
id: "packages/active-ui/item"
title: "Item"
description: "A row of content with a media slot, a title and description, and actions, alone or in a list."
url: "/packages/active-ui/item"
locale: "en"
revision: "5c49b1e69d7c3154"
---

# Item

An item lays out one row of content: an icon or image, a title with a description, and actions at
the end. Use it for settings, documents, notifications, people, anywhere a list is made of rich rows.
It is only layout: what the row means and what its actions do are yours. This site uses items for
the previous and next links below every page.

**Example: An outlined item, a link and a list**

Client: Runs entirely in your browser. Source: `examples/ui/item.tsx`.

```tsx
// apps/docs/examples/ui/item.tsx
'use client';

import {ChevronRightIcon, FileTextIcon, ShieldCheckIcon} from 'lucide-react';

import {Badge} from '@workspace/active-ui/components/primitives/badge';
import {Button} from '@workspace/active-ui/components/primitives/button';
import {
  Item,
  ItemActions,
  ItemContent,
  ItemDescription,
  ItemGroup,
  ItemMedia,
  ItemSeparator,
  ItemTitle,
} from '@workspace/active-ui/components/primitives/item';

const DOCUMENTS = [
  {title: 'Scheme rules 2026', meta: 'PDF · 1.2 MB'},
  {title: 'Annual report 2025', meta: 'PDF · 3.4 MB'},
];

/**
 * A row of content with a media slot, a title and description, and
 * actions: as a standalone outlined item, as a link, and as a list of
 * items with separators. In a group, which is a list, each item is a
 * `listitem`. Items lay out the content; the actions are yours.
 */
export default function ItemExample() {
  return (
    <div className="flex w-full max-w-md flex-col gap-6">
      <Item variant="outline">
        <ItemMedia variant="icon">
          <ShieldCheckIcon aria-hidden />
        </ItemMedia>
        <ItemContent>
          <ItemTitle>
            Two-step verification <Badge variant="secondary">On</Badge>
          </ItemTitle>
          <ItemDescription>
            A code from your phone is asked at every sign-in.
          </ItemDescription>
        </ItemContent>
        <ItemActions>
          <Button variant="outline" size="sm">
            Manage
          </Button>
        </ItemActions>
      </Item>

      <Item variant="muted" size="sm" render={<a href="#item-statements" />}>
        <ItemContent>
          <ItemTitle>Statements</ItemTitle>
          <ItemDescription>Three new since your last visit</ItemDescription>
        </ItemContent>
        <ItemActions>
          <ChevronRightIcon aria-hidden className="size-4" />
        </ItemActions>
      </Item>

      <ItemGroup>
        {DOCUMENTS.map((document, index) => (
          <div key={document.title} className="contents">
            {index > 0 ? <ItemSeparator /> : null}
            <Item size="sm" role="listitem">
              <ItemMedia variant="icon">
                <FileTextIcon aria-hidden />
              </ItemMedia>
              <ItemContent>
                <ItemTitle>{document.title}</ItemTitle>
                <ItemDescription>{document.meta}</ItemDescription>
              </ItemContent>
              <ItemActions>
                <Button variant="ghost" size="sm">
                  Download
                </Button>
              </ItemActions>
            </Item>
          </div>
        ))}
      </ItemGroup>
    </div>
  );
}
```

## Usage

```tsx
import {
  Item,
  ItemActions,
  ItemContent,
  ItemDescription,
  ItemMedia,
  ItemTitle,
} from '@workspace/active-ui/components/primitives/item';

<Item variant="outline">
  <ItemMedia variant="icon">
    <ShieldCheckIcon aria-hidden />
  </ItemMedia>
  <ItemContent>
    <ItemTitle>Two-step verification</ItemTitle>
    <ItemDescription>
      A code from your phone is asked at every sign-in.
    </ItemDescription>
  </ItemContent>
  <ItemActions>
    <Button variant="outline" size="sm">
      Manage
    </Button>
  </ItemActions>
</Item>;
```

## Anatomy

- `Item`: the row. `variant`: `default` (no frame), `outline` (a border) or `muted` (a light
  fill); `size`: `default`, `sm` or `xs`. `render` makes it another element, such as a link
  (`render={<a href="…" />}`), with a hover state.
- `ItemMedia`: the start of the row. `variant`: `default`, `icon` (sizes an icon) or `image` (a
  square crop).
- `ItemContent` with `ItemTitle` and `ItemDescription` (clamped to two lines).
- `ItemActions`: the end of the row.
- `ItemHeader` and `ItemFooter`: full-width rows above and below the content.
- `ItemGroup` and `ItemSeparator`: a list of items, `role="list"`, and a line between them.

## What your application provides

- The content and the actions. When the whole item is a link, keep the actions out of it: a button
  inside a link cannot be reached on its own.
- Structure for a list: `ItemGroup` is a `role="list"`; give each item `role="listitem"` when
  the list semantics matter, or use your own `<ul>`.

## Accessibility

Items are `<div>`s with no behaviour; a linked item is an ordinary link. The description is part
of the link's name when the item is a link, so keep it short.

## API

### Item

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `size` | `"default" \| "sm" \| "xs" \| null` | no | The padding and gap: `default`, `sm` or `xs`. |
| `variant` | `"default" \| "muted" \| "outline" \| null` | no | `default` has no frame, `outline` a border, `muted` a light fill. |
| `render` | `ComponentRenderFn<HTMLProps, {}> \| ReactElement<unknown, string \| JSXElementConstructor<any>>` | no | Allows you to replace the component's HTML element with a different tag, or compose it with another component.  Accepts a `ReactElement` or a function that returns the element to render. |

### Other parts

**ItemMedia**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `variant` | `"default" \| "icon" \| "image" \| null` | no | `default` as is, `icon` sizes an icon, `image` crops a picture to a square. |

**ItemContent**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

ItemContent has no props of its own.

**ItemActions**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

ItemActions has no props of its own.

**ItemGroup**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

ItemGroup has no props of its own.

**ItemSeparator**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `orientation` | `Orientation` | no | The orientation of the separator. |
| `render` | `ComponentRenderFn<HTMLProps, SeparatorState> \| ReactElement<unknown, string \| JSXElementConstructor<any>>` | no | Allows you to replace the component's HTML element with a different tag, or compose it with another component.  Accepts a `ReactElement` or a function that returns the element to render. |

**ItemTitle**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

ItemTitle has no props of its own.

**ItemDescription**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

ItemDescription has no props of its own.

**ItemHeader**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

ItemHeader has no props of its own.

**ItemFooter**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

ItemFooter has no props of its own.

> [!NOTE]
> **Based on shadcn/ui**
>
> This page adapts the Item documentation of shadcn/ui (MIT licence) to this
> package; see [Third-party notices](/third-party-notices).
