A row with media, text and actions — for settings and lists.

Security alert

New login from an unrecognised device in Lisbon.

Two-factor authentication Recommended
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Item, ItemActions, ItemContent, ItemDescription, ItemMedia, ItemTitle } from '@/components/ui/item'

export default function ItemDemo() {
  return (
    <div className="flex w-full max-w-md flex-col gap-4">
      <Item variant="outline">
        <ItemMedia variant="icon">
          <ShieldIcon />
        </ItemMedia>
        <ItemContent>
          <ItemTitle>Security alert</ItemTitle>
          <ItemDescription>New login from an unrecognised device in Lisbon.</ItemDescription>
        </ItemContent>
        <ItemActions>
          <Button variant="outline" size="sm">
            Review
          </Button>
        </ItemActions>
      </Item>

      <Item variant="muted" size="sm">
        <ItemContent>
          <ItemTitle>
            Two-factor authentication <Badge variant="secondary">Recommended</Badge>
          </ItemTitle>
        </ItemContent>
        <ItemActions>
          <Button size="sm">Enable</Button>
        </ItemActions>
      </Item>
    </div>
  )
}

function ShieldIcon() {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
      <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" />
    </svg>
  )
}

Installation

pnpm dlx shadcn@latest add https://kagadmodyaa.vercel.app/r/item.json

Needs a React + Tailwind project set up with shadcn. Copies the component source straight into your project, so you can edit it.

Item imports cn() from lib/utils.ts — add it too if you don't have it yet:

import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

Usage

import { Item, ItemMedia, ItemContent, ItemTitle, ItemDescription, ItemActions } from '@/components/ui/item'

<Item variant="outline">
  <ItemMedia variant="icon"><BellIcon /></ItemMedia>
  <ItemContent>
    <ItemTitle>Notifications</ItemTitle>
    <ItemDescription>Choose what you hear about.</ItemDescription>
  </ItemContent>
  <ItemActions>
    <Button size="sm" variant="outline">Edit</Button>
  </ItemActions>
</Item>

Examples

Settings list

Email digests

A weekly summary of activity in your workspace.

Push notifications

Get notified about mentions and replies.

Product news

Occasional updates about new releases.

import { Switch } from '@/components/ui/switch'
import { Item, ItemActions, ItemContent, ItemDescription, ItemGroup, ItemSeparator, ItemTitle } from '@/components/ui/item'

const settings = [
  { id: 'email', title: 'Email digests', description: 'A weekly summary of activity in your workspace.', on: true },
  { id: 'push', title: 'Push notifications', description: 'Get notified about mentions and replies.', on: true },
  { id: 'marketing', title: 'Product news', description: 'Occasional updates about new releases.', on: false },
]

/** A settings list: Items in an ItemGroup, divided by ItemSeparators. */
export default function ItemSettings() {
  return (
    <ItemGroup className="w-full max-w-md rounded-lg border border-border">
      {settings.map((setting, index) => (
        <div key={setting.id} role="listitem">
          {index > 0 && <ItemSeparator />}
          <Item>
            <ItemContent>
              <ItemTitle id={`${setting.id}-label`}>{setting.title}</ItemTitle>
              <ItemDescription>{setting.description}</ItemDescription>
            </ItemContent>
            <ItemActions>
              <Switch defaultChecked={setting.on} aria-labelledby={`${setting.id}-label`} />
            </ItemActions>
          </Item>
        </div>
      ))}
    </ItemGroup>
  )
}

API Reference

NameTypeDefaultDescription
Item variant'default' | 'outline' | 'muted''default'Borderless, bordered, or softly filled.
Item size'default' | 'sm''default'Padding and spacing.
ItemMedia variant'default' | 'icon' | 'image''default'Bare, a bordered icon square, or a rounded thumbnail.
ItemContent, ItemTitle, ItemDescriptioncomponent—The text block in the middle.
ItemActionscomponent—Buttons, switches or badges at the end of the row.
ItemGroup, ItemSeparatorcomponent—Stack several items and divide them.
ItemHeader, ItemFootercomponent—Full-width rows above or below the main content.