Item
A row with media, a title, a description and actions, for lists of integrations, files, people and settings.
npx prodular-ui add itemList in a card
Plain items split by ItemSeparator. The card is the only box.
import { BlocksIcon, DatabaseIcon, MessageSquareIcon, WebhookIcon } from "lucide-react"import * as React from "react"
import { Badge, BadgeDot } from "@/components/ui/badge"import { Button } from "@/components/ui/button"import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"import { Item, ItemActions, ItemContent, ItemDescription, ItemGroup, ItemMedia, ItemSeparator, ItemTitle,} from "@/components/ui/item"
const integrations = [ { name: "Slack", icon: MessageSquareIcon, description: "Posts failed payments to #billing-alerts", connected: true }, { name: "Snowflake", icon: DatabaseIcon, description: "Syncs invoices and usage every hour", connected: true }, { name: "Webhooks", icon: WebhookIcon, description: "2 endpoints, 14 event types", connected: true }, { name: "HubSpot", icon: BlocksIcon, description: "Match customers to company records", connected: false },]
export default function ItemList() { return ( <Card className="w-full max-w-lg"> <CardHeader> <CardTitle>Integrations</CardTitle> <CardDescription>Connected apps can read billing data for this workspace.</CardDescription> </CardHeader> <CardContent> <ItemGroup className="-mx-3"> {integrations.map((app, i) => ( <React.Fragment key={app.name}> {i > 0 && <ItemSeparator className="mx-3 w-auto" />} <Item role="listitem"> <ItemMedia variant="icon"> <app.icon /> </ItemMedia> <ItemContent> <ItemTitle> {app.name} {app.connected && ( <Badge size="sm" variant="success"> <BadgeDot /> Connected </Badge> )} </ItemTitle> <ItemDescription>{app.description}</ItemDescription> </ItemContent> <ItemActions> <Button variant={app.connected ? "ghost" : "outline"} size="sm"> {app.connected ? "Configure" : "Connect"} </Button> </ItemActions> </Item> </React.Fragment> ))} </ItemGroup> </CardContent> </Card> )}Variants
outline for a standalone row on the page, muted for a quiet link. Render as a link with render.
import { ChevronRightIcon, FileTextIcon, ShieldAlertIcon } from "lucide-react"
import { Button } from "@/components/ui/button"import { Item, ItemActions, ItemContent, ItemDescription, ItemMedia, ItemTitle,} from "@/components/ui/item"
export default function ItemVariants() { return ( <div className="flex w-full max-w-md flex-col gap-3"> <Item variant="outline"> <ItemMedia variant="icon"> <ShieldAlertIcon /> </ItemMedia> <ItemContent> <ItemTitle>Two factor authentication is off</ItemTitle> <ItemDescription>Admins must turn it on before November 15.</ItemDescription> </ItemContent> <ItemActions> <Button size="sm">Turn on</Button> </ItemActions> </Item> <Item variant="muted" size="sm" render={<a href="#report" />}> <ItemMedia variant="icon"> <FileTextIcon /> </ItemMedia> <ItemContent> <ItemTitle>Q3 revenue report</ItemTitle> </ItemContent> <ItemActions> <ChevronRightIcon className="size-4 text-muted-foreground" /> </ItemActions> </Item> </div> )}Anatomy
<ItemGroup> <Item role="listitem"> <ItemMedia variant="icon"><DatabaseIcon /></ItemMedia> <ItemContent> <ItemTitle>Snowflake</ItemTitle> <ItemDescription>Syncs every hour</ItemDescription> </ItemContent> <ItemActions> <Button size="sm" variant="ghost">Configure</Button> </ItemActions> </Item> <ItemSeparator /></ItemGroup>Guidance
Use it when
- Lists where each row has a name, a short description and one or two actions.
- Standalone rows on a page, such as a setting that needs attention (outline).
Avoid
- outline or muted items inside a card. Inside a card use the default variant with separators.
- Data with several comparable columns. Use a Table.
- More than two actions per row. Move the rest into a menu.
Rules for AI agents
Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.
- Inside a Card, use the default variant and separate rows with ItemSeparator. Never use variant="outline" inside a card.
- Wrap rows in ItemGroup and give each Item role="listitem".
- Use ItemMedia variant="icon" for lucide icons and variant="image" for logos or thumbnails.
- To make the whole row a link, pass render={<a href="..." />}. Do not nest buttons inside a linked row.
- Keep ItemTitle to one line and ItemDescription to two.
API
Item
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "outline" | "muted" | "default" | Plain row, raised bordered row or quiet tinted row. |
| size | "default" | "sm" | "xs" | "default" | Padding and gap. |
| render | ReactElement | Renders the row as another element, for example a link. |
ItemMedia
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "icon" | "image" | "default" | Sizing for the leading media. |
Installation
The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.
npx prodular-ui add item# or, with the registry in components.jsonnpx shadcn@latest add @prodular/item