Item

Flexible row for lists, menus, and settings.

Arrange media, a title, supporting text, and actions in one row. Stack items with ItemGroup to build a list.

Basic Item

A simple item with title and description.

Your profile has been verified.
tsx
import { Button } from "@/components/ui/button"import {  Item,  ItemActions,  ItemContent,  ItemDescription,  ItemMedia,  ItemTitle,} from "@/components/ui/item"function BadgeCheckIcon(props: React.SVGProps<SVGSVGElement>) {  return (    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}>      <path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" />      <path d="m9 12 2 2 4-4" />    </svg>  )}function ChevronRightIcon(props: React.SVGProps<SVGSVGElement>) {  return (    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}>      <path d="m9 18 6-6-6-6" />    </svg>  )}export function Example() {  return (    <div className="flex w-full max-w-md flex-col gap-4">      <Item variant="outline">        <ItemContent>          <ItemTitle>Basic Item</ItemTitle>          <ItemDescription>            A simple item with title and description.          </ItemDescription>        </ItemContent>        <ItemActions>          <Button variant="outline" size="sm">            Action          </Button>        </ItemActions>      </Item>      <Item variant="outline" size="sm" render={<a href="#" />}>        <ItemMedia>          <BadgeCheckIcon className="size-5" />        </ItemMedia>        <ItemContent>          <ItemTitle>Your profile has been verified.</ItemTitle>        </ItemContent>        <ItemActions>          <ChevronRightIcon className="size-4" />        </ItemActions>      </Item>    </div>  )}

Installation

npx @arctis-sh/@arctis-sh/ui@latest add item

Usage

import {  Item,  ItemActions,  ItemContent,  ItemDescription,  ItemMedia,  ItemTitle,} from "@/components/ui/item"
<Item>  <ItemMedia variant="icon">    <Icon />  </ItemMedia>  <ItemContent>    <ItemTitle>Title</ItemTitle>    <ItemDescription>Description</ItemDescription>  </ItemContent>  <ItemActions>    <Button>Action</Button>  </ItemActions></Item>

Composition

ItemGroup
└── Item
    ├── ItemHeader
    ├── ItemMedia
    ├── ItemContent
    │   ├── ItemTitle
    │   └── ItemDescription
    ├── ItemActions
    └── ItemFooter

Variant

Use variant to choose a default, outlined, or muted surface.

Default

Transparent background with no border.

Outline

Outlined style with a visible border.

Muted

Muted background for secondary content.

tsx
import {  Item,  ItemContent,  ItemDescription,  ItemTitle,} from "@/components/ui/item"export function Example() {  return (    <div className="flex w-full max-w-md flex-col gap-4">      <Item>        <ItemContent>          <ItemTitle>Default</ItemTitle>          <ItemDescription>            Transparent background with no border.          </ItemDescription>        </ItemContent>      </Item>      <Item variant="outline">        <ItemContent>          <ItemTitle>Outline</ItemTitle>          <ItemDescription>Outlined style with a visible border.</ItemDescription>        </ItemContent>      </Item>      <Item variant="muted">        <ItemContent>          <ItemTitle>Muted</ItemTitle>          <ItemDescription>            Muted background for secondary content.          </ItemDescription>        </ItemContent>      </Item>    </div>  )}

Size

size accepts default, sm, or xs.

Default

The standard size for most use cases.

Small

A compact size for dense layouts.

Extra small

The most compact size available.

tsx
import {  Item,  ItemContent,  ItemDescription,  ItemMedia,  ItemTitle,} from "@/components/ui/item"function InboxIcon(props: React.SVGProps<SVGSVGElement>) {  return (    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}>      <polyline points="22 12 16 12 14 15 10 15 8 12 2 12" />      <path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" />    </svg>  )}export function Example() {  return (    <div className="flex w-full max-w-md flex-col gap-4">      <Item variant="outline">        <ItemMedia variant="icon">          <InboxIcon />        </ItemMedia>        <ItemContent>          <ItemTitle>Default</ItemTitle>          <ItemDescription>The standard size for most use cases.</ItemDescription>        </ItemContent>      </Item>      <Item variant="outline" size="sm">        <ItemMedia variant="icon">          <InboxIcon />        </ItemMedia>        <ItemContent>          <ItemTitle>Small</ItemTitle>          <ItemDescription>A compact size for dense layouts.</ItemDescription>        </ItemContent>      </Item>      <Item variant="outline" size="xs">        <ItemMedia variant="icon">          <InboxIcon />        </ItemMedia>        <ItemContent>          <ItemTitle>Extra small</ItemTitle>          <ItemDescription>The most compact size available.</ItemDescription>        </ItemContent>      </Item>    </div>  )}

Icon

Set variant="icon" on ItemMedia for an icon tile.

Security Alert

New login detected from unknown device.

tsx
import { Button } from "@/components/ui/button"import {  Item,  ItemActions,  ItemContent,  ItemDescription,  ItemMedia,  ItemTitle,} from "@/components/ui/item"function ShieldAlertIcon(props: React.SVGProps<SVGSVGElement>) {  return (    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}>      <path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" />      <path d="M12 8v4" />      <path d="M12 16h.01" />    </svg>  )}export function Example() {  return (    <Item variant="outline" className="max-w-lg">      <ItemMedia variant="icon">        <ShieldAlertIcon />      </ItemMedia>      <ItemContent>        <ItemTitle>Security Alert</ItemTitle>        <ItemDescription>          New login detected from unknown device.        </ItemDescription>      </ItemContent>      <ItemActions>        <Button size="sm" variant="outline">          Review        </Button>      </ItemActions>    </Item>  )}

Avatar

Place an Avatar inside ItemMedia.

Mina ChoMC
Mina Cho

Last seen 5 months ago

Jonas BergJBElsa LindELNoah ParkNP
No members

Invite people to this project.

tsx
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"import { Button } from "@/components/ui/button"import {  Item,  ItemActions,  ItemContent,  ItemDescription,  ItemMedia,  ItemTitle,} from "@/components/ui/item"export function Example() {  return (    <div className="flex w-full max-w-lg flex-col gap-4">      <Item variant="outline">        <ItemMedia>          <Avatar size="sm">            <AvatarImage src="/assets/brand/demos/avatars/avatar-1.png" alt="Mina Cho" />            <AvatarFallback>MC</AvatarFallback>          </Avatar>        </ItemMedia>        <ItemContent>          <ItemTitle>Mina Cho</ItemTitle>          <ItemDescription>Last seen 5 months ago</ItemDescription>        </ItemContent>      </Item>      <Item variant="outline">        <ItemMedia>          <div className="flex -space-x-2">            <Avatar size="sm" className="ring-2 ring-background">              <AvatarImage src="/assets/brand/demos/avatars/avatar-2.png" alt="Jonas Berg" />              <AvatarFallback>JB</AvatarFallback>            </Avatar>            <Avatar size="sm" className="ring-2 ring-background">              <AvatarImage src="/assets/brand/demos/avatars/avatar-3.png" alt="Elsa Lind" />              <AvatarFallback>EL</AvatarFallback>            </Avatar>            <Avatar size="sm" className="ring-2 ring-background">              <AvatarImage src="/assets/brand/demos/avatars/avatar-4.png" alt="Noah Park" />              <AvatarFallback>NP</AvatarFallback>            </Avatar>          </div>        </ItemMedia>        <ItemContent>          <ItemTitle>No members</ItemTitle>          <ItemDescription>Invite people to this project.</ItemDescription>        </ItemContent>        <ItemActions>          <Button size="sm" variant="outline">            Invite          </Button>        </ItemActions>      </Item>    </div>  )}

Image

Set variant="image" on ItemMedia for cover art or thumbnails.

Midnight City Lights
Midnight City Lights
3:45

Electric Nights

Coffee Shop Conversations
Coffee Shop Conversations
4:05

Urban Stories

Digital Rain
Digital Rain
3:30

Binary Beats

tsx
import {  Item,  ItemContent,  ItemDescription,  ItemGroup,  ItemMedia,  ItemTitle,} from "@/components/ui/item"const tracks = [  {    title: "Midnight City Lights",    description: "Electric Nights",    image: "/assets/brand/demos/attachments/attachment-1.png",    duration: "3:45",  },  {    title: "Coffee Shop Conversations",    description: "Urban Stories",    image: "/assets/brand/demos/attachments/attachment-2.png",    duration: "4:05",  },  {    title: "Digital Rain",    description: "Binary Beats",    image: "/assets/brand/demos/attachments/attachment-3.png",    duration: "3:30",  },] as constexport function Example() {  return (    <ItemGroup className="max-w-md gap-4">      {tracks.map((track) => (        <Item key={track.title} variant="outline">          <ItemMedia variant="image">            <img src={track.image} alt={track.title} />          </ItemMedia>          <ItemContent>            <div className="flex items-center justify-between gap-2">              <ItemTitle>{track.title}</ItemTitle>              <span className="shrink-0 text-sm text-muted-foreground">                {track.duration}              </span>            </div>            <ItemDescription>{track.description}</ItemDescription>          </ItemContent>        </Item>      ))}    </ItemGroup>  )}

Group

Group related rows with ItemGroup and, when needed, ItemSeparator.

Mina ChoMC
Mina Cho

mina@arctis.dev

Jonas BergJB
Jonas Berg

jonas@arctis.dev

Elsa LindEL
Elsa Lind

elsa@arctis.dev

tsx
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"import {  Item,  ItemContent,  ItemDescription,  ItemGroup,  ItemMedia,  ItemSeparator,  ItemTitle,} from "@/components/ui/item"const people = [  {    name: "Mina Cho",    email: "mina@arctis.dev",    src: "/assets/brand/demos/avatars/avatar-1.png",    fallback: "MC",  },  {    name: "Jonas Berg",    email: "jonas@arctis.dev",    src: "/assets/brand/demos/avatars/avatar-2.png",    fallback: "JB",  },  {    name: "Elsa Lind",    email: "elsa@arctis.dev",    src: "/assets/brand/demos/avatars/avatar-3.png",    fallback: "EL",  },] as constexport function Example() {  return (    <ItemGroup className="max-w-md rounded-md border border-border">      {people.map((person, index) => (        <div key={person.email}>          {index > 0 ? <ItemSeparator /> : null}          <Item>            <ItemMedia>              <Avatar size="sm">                <AvatarImage src={person.src} alt={person.name} />                <AvatarFallback>{person.fallback}</AvatarFallback>              </Avatar>            </ItemMedia>            <ItemContent>              <ItemTitle>{person.name}</ItemTitle>              <ItemDescription>{person.email}</ItemDescription>            </ItemContent>          </Item>        </div>      ))}    </ItemGroup>  )}

Add ItemHeader above the content for card-style layouts.

v0-1.5-sm
v0-1.5-sm

Everyday tasks and UI generation.

v0-1.5-lg
v0-1.5-lg

Advanced thinking or reasoning.

v0-2.0-mini
v0-2.0-mini

Open source model for everyone.

tsx
import {  Item,  ItemContent,  ItemDescription,  ItemHeader,  ItemTitle,} from "@/components/ui/item"const models = [  {    name: "v0-1.5-sm",    description: "Everyday tasks and UI generation.",    image: "/assets/brand/demos/attachments/attachment-1.png",  },  {    name: "v0-1.5-lg",    description: "Advanced thinking or reasoning.",    image: "/assets/brand/demos/attachments/attachment-2.png",  },  {    name: "v0-2.0-mini",    description: "Open source model for everyone.",    image: "/assets/brand/demos/attachments/attachment-3.png",  },] as constexport function Example() {  return (    <div className="grid w-full max-w-2xl gap-4 sm:grid-cols-3">      {models.map((model) => (        <Item          key={model.name}          variant="outline"          className="flex-col flex-nowrap items-stretch gap-3"        >          <ItemHeader className="block">            <img              src={model.image}              alt={model.name}              className="aspect-[4/3] w-full rounded-sm object-cover"            />          </ItemHeader>          <ItemContent className="w-full flex-none">            <ItemTitle>{model.name}</ItemTitle>            <ItemDescription>{model.description}</ItemDescription>          </ItemContent>        </Item>      ))}    </div>  )}

Pass render to make the item a real <a> or <button>.

tsx
import {  Item,  ItemActions,  ItemContent,  ItemDescription,  ItemTitle,} from "@/components/ui/item"function ChevronRightIcon(props: React.SVGProps<SVGSVGElement>) {  return (    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}>      <path d="m9 18 6-6-6-6" />    </svg>  )}function ExternalLinkIcon(props: React.SVGProps<SVGSVGElement>) {  return (    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}>      <path d="M15 3h6v6" />      <path d="M10 14 21 3" />      <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />    </svg>  )}export function Example() {  return (    <div className="flex w-full max-w-md flex-col gap-3">      <Item render={<a href="#" />}>        <ItemContent>          <ItemTitle>Visit our documentation</ItemTitle>          <ItemDescription>            Learn how to get started with our components.          </ItemDescription>        </ItemContent>        <ItemActions>          <ChevronRightIcon className="size-4" />        </ItemActions>      </Item>      <Item        variant="outline"        render={<a href="https://example.com" target="_blank" rel="noreferrer noopener" />}      >        <ItemContent>          <ItemTitle>External resource</ItemTitle>          <ItemDescription>            Opens in a new tab with security attributes.          </ItemDescription>        </ItemContent>        <ItemActions>          <ExternalLinkIcon className="size-4" />        </ItemActions>      </Item>    </div>  )}
<Item render={<a href="/dashboard" />}>  <ItemContent>    <ItemTitle>Dashboard</ItemTitle>    <ItemDescription>Overview of your account and activity.</ItemDescription>  </ItemContent></Item>

API Reference

Item

Root row. itemVariants is also exported for composing styles. Standard HTML attributes pass through to the root or the element provided through render.

PropTypeDefault
variant"default" | "outline" | "muted""default"
size"default" | "sm" | "xs""default"
renderReactElement
classNamestring
<Item variant="outline" size="sm">  <ItemContent>    <ItemTitle>Title</ItemTitle>  </ItemContent></Item>

ItemGroup

Groups related items. Renders with role="list".

<ItemGroup>  <Item />  <Item /></ItemGroup>

ItemSeparator

Separator between items in a group.

<ItemGroup>  <Item />  <ItemSeparator />  <Item /></ItemGroup>

ItemMedia

Media slot for icons, images, or avatars.

PropTypeDefault
variant"default" | "icon" | "image""default"
classNamestring
<ItemMedia variant="icon">  <Icon /></ItemMedia>
<ItemMedia variant="image">  <img src="..." alt="..." /></ItemMedia>

ItemContent

Wraps the title and description.

<ItemContent>  <ItemTitle>Title</ItemTitle>  <ItemDescription>Description</ItemDescription></ItemContent>

ItemTitle

Primary label for the item.

<ItemTitle>Item Title</ItemTitle>

ItemDescription

Supporting text. Clamps to two lines.

<ItemDescription>Item description</ItemDescription>

ItemActions

Container for buttons or other actions.

<ItemActions>  <Button>Action</Button></ItemActions>

ItemHeader

Full-width header above the content.

<Item>  <ItemHeader>Header</ItemHeader>  <ItemContent>...</ItemContent></Item>

ItemFooter

Full-width footer below the content.

<Item>  <ItemContent>...</ItemContent>  <ItemFooter>Footer</ItemFooter></Item>