- Accordion
- Alert Dialog
- Alert
- Aspect Ratio
- Avatar
- Badge
- Breadcrumb
- Button Group
- Button
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Form
- Hover Card
- Input Group
- Input OTP
- Input
- Item
- Kbd
- Label
- Menubar
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle Group
- Toggle
- Tooltip
- Typography
The Item component is a straightforward flex container that can house nearly any type of content. Use it to display a title, description, and actions. Group it with the ItemGroup component to create a list of items.
You can pretty much achieve the same result with the div element and some classes, but I've built this so many times that I decided to create a component for it. Now I use it all the time.
A simple item with title and description.
import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react" import { Button } from "@/components/ui/button" import { Item, ItemActions, ItemContent, ItemDescription, ItemMedia, ItemTitle, } from "@/components/ui/item" export function ItemDemo() { return ( <div className="flex w-full max-w-md flex-col gap-6"> <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" asChild> <a href="#"> <ItemMedia> <BadgeCheckIcon className="size-5" /> </ItemMedia> <ItemContent> <ItemTitle>Your profile has been verified.</ItemTitle> </ItemContent> <ItemActions> <ChevronRightIcon className="size-4" /> </ItemActions> </a> </Item> </div> ) } Installation
pnpm dlx shadcn@latest add item
Usage
import { Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemHeader, ItemMedia, ItemTitle, } from "@/components/ui/item"<Item> <ItemHeader>Item Header</ItemHeader> <ItemMedia /> <ItemContent> <ItemTitle>Item</ItemTitle> <ItemDescription>Item</ItemDescription> </ItemContent> <ItemActions /> <ItemFooter>Item Footer</ItemFooter> </Item>Item vs Field
Use Field if you need to display a form input such as a checkbox, input, radio, or select.
If you only need to display content such as a title, description, and actions, use Item.
Examples
Variants
Standard styling with subtle background and borders.
Outlined style with clear borders and transparent background.
Subdued appearance with muted colors for secondary content.
import { Button } from "@/components/ui/button" import { Item, ItemActions, ItemContent, ItemDescription, ItemTitle, } from "@/components/ui/item" export function ItemVariant() { return ( <div className="flex flex-col gap-6"> <Item> <ItemContent> <ItemTitle>Default Variant</ItemTitle> <ItemDescription> Standard styling with subtle background and borders. </ItemDescription> </ItemContent> <ItemActions> <Button variant="outline" size="sm"> Open </Button> </ItemActions> </Item> <Item variant="outline"> <ItemContent> <ItemTitle>Outline Variant</ItemTitle> <ItemDescription> Outlined style with clear borders and transparent background. </ItemDescription> </ItemContent> <ItemActions> <Button variant="outline" size="sm"> Open </Button> </ItemActions> </Item> <Item variant="muted"> <ItemContent> <ItemTitle>Muted Variant</ItemTitle> <ItemDescription> Subdued appearance with muted colors for secondary content. </ItemDescription> </ItemContent> <ItemActions> <Button variant="outline" size="sm"> Open </Button> </ItemActions> </Item> </div> ) } Size
The Item component has different sizes for different use cases. For example, you can use the sm size for a compact item or the default size for a standard item.
A simple item with title and description.
import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react" import { Button } from "@/components/ui/button" import { Item, ItemActions, ItemContent, ItemDescription, ItemMedia, ItemTitle, } from "@/components/ui/item" export function ItemSizeDemo() { return ( <div className="flex w-full max-w-md flex-col gap-6"> <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" asChild> <a href="#"> <ItemMedia> <BadgeCheckIcon className="size-5" /> </ItemMedia> <ItemContent> <ItemTitle>Your profile has been verified.</ItemTitle> </ItemContent> <ItemActions> <ChevronRightIcon className="size-4" /> </ItemActions> </a> </Item> </div> ) } Icon
New login detected from unknown device.
import { ShieldAlertIcon } from "lucide-react" import { Button } from "@/components/ui/button" import { Item, ItemActions, ItemContent, ItemDescription, ItemMedia, ItemTitle, } from "@/components/ui/item" export function ItemIcon() { return ( <div className="flex w-full max-w-lg flex-col gap-6"> <Item variant="outline"> <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> </div> ) } Avatar
Last seen 5 months ago
Invite your team to collaborate on this project.
import { Plus } from "lucide-react" 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 ItemAvatar() { return ( <div className="flex w-full max-w-lg flex-col gap-6"> <Item variant="outline"> <ItemMedia> <Avatar className="size-10"> <AvatarImage src="https://github.com/evilrabbit.png" /> <AvatarFallback>ER</AvatarFallback> </Avatar> </ItemMedia> <ItemContent> <ItemTitle>Evil Rabbit</ItemTitle> <ItemDescription>Last seen 5 months ago</ItemDescription> </ItemContent> <ItemActions> <Button size="icon-sm" variant="outline" className="rounded-full" aria-label="Invite" > <Plus /> </Button> </ItemActions> </Item> <Item variant="outline"> <ItemMedia> <div className="*:data-[slot=avatar]:ring-background flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:grayscale"> <Avatar className="hidden sm:flex"> <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" /> <AvatarFallback>CN</AvatarFallback> </Avatar> <Avatar className="hidden sm:flex"> <AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" /> <AvatarFallback>LR</AvatarFallback> </Avatar> <Avatar> <AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" /> <AvatarFallback>ER</AvatarFallback> </Avatar> </div> </ItemMedia> <ItemContent> <ItemTitle>No Team Members</ItemTitle> <ItemDescription> Invite your team to collaborate on this project. </ItemDescription> </ItemContent> <ItemActions> <Button size="sm" variant="outline"> Invite </Button> </ItemActions> </Item> </div> ) } Image
import Image from "next/image" import { Item, ItemContent, ItemDescription, ItemGroup, ItemMedia, ItemTitle, } from "@/components/ui/item" const music = [ { title: "Midnight City Lights", artist: "Neon Dreams", album: "Electric Nights", duration: "3:45", }, { title: "Coffee Shop Conversations", artist: "The Morning Brew", album: "Urban Stories", duration: "4:05", }, { title: "Digital Rain", artist: "Cyber Symphony", album: "Binary Beats", duration: "3:30", }, ] export function ItemImage() { return ( <div className="flex w-full max-w-md flex-col gap-6"> <ItemGroup className="gap-4"> {music.map((song) => ( <Item key={song.title} variant="outline" asChild role="listitem"> <a href="#"> <ItemMedia variant="image"> <Image src={`https://avatar.vercel.sh/${song.title}`} alt={song.title} width={32} height={32} className="object-cover grayscale" /> </ItemMedia> <ItemContent> <ItemTitle className="line-clamp-1"> {song.title} -{" "} <span className="text-muted-foreground">{song.album}</span> </ItemTitle> <ItemDescription>{song.artist}</ItemDescription> </ItemContent> <ItemContent className="flex-none text-center"> <ItemDescription>{song.duration}</ItemDescription> </ItemContent> </a> </Item> ))} </ItemGroup> </div> ) } Group
shadcn@vercel.com
maxleiter@vercel.com
evilrabbit@vercel.com
import * as React from "react" import { PlusIcon } from "lucide-react" import { Avatar, AvatarFallback, AvatarImage, } from "@/components/ui/avatar" import { Button } from "@/components/ui/button" import { Item, ItemActions, ItemContent, ItemDescription, ItemGroup, ItemMedia, ItemSeparator, ItemTitle, } from "@/components/ui/item" const people = [ { username: "shadcn", avatar: "https://github.com/shadcn.png", email: "shadcn@vercel.com", }, { username: "maxleiter", avatar: "https://github.com/maxleiter.png", email: "maxleiter@vercel.com", }, { username: "evilrabbit", avatar: "https://github.com/evilrabbit.png", email: "evilrabbit@vercel.com", }, ] export function ItemGroupExample() { return ( <div className="flex w-full max-w-md flex-col gap-6"> <ItemGroup> {people.map((person, index) => ( <React.Fragment key={person.username}> <Item> <ItemMedia> <Avatar> <AvatarImage src={person.avatar} className="grayscale" /> <AvatarFallback>{person.username.charAt(0)}</AvatarFallback> </Avatar> </ItemMedia> <ItemContent className="gap-1"> <ItemTitle>{person.username}</ItemTitle> <ItemDescription>{person.email}</ItemDescription> </ItemContent> <ItemActions> <Button variant="ghost" size="icon" className="rounded-full"> <PlusIcon /> </Button> </ItemActions> </Item> {index !== people.length - 1 && <ItemSeparator />} </React.Fragment> ))} </ItemGroup> </div> ) } Header
Everyday tasks and UI generation.
Advanced thinking or reasoning.
Open Source model for everyone.
import Image from "next/image" import { Item, ItemContent, ItemDescription, ItemGroup, ItemHeader, ItemTitle, } from "@/components/ui/item" const models = [ { name: "v0-1.5-sm", description: "Everyday tasks and UI generation.", image: "https://images.unsplash.com/photo-1650804068570-7fb2e3dbf888?q=80&w=640&auto=format&fit=crop", credit: "Valeria Reverdo on Unsplash", }, { name: "v0-1.5-lg", description: "Advanced thinking or reasoning.", image: "https://images.unsplash.com/photo-1610280777472-54133d004c8c?q=80&w=640&auto=format&fit=crop", credit: "Michael Oeser on Unsplash", }, { name: "v0-2.0-mini", description: "Open Source model for everyone.", image: "https://images.unsplash.com/photo-1602146057681-08560aee8cde?q=80&w=640&auto=format&fit=crop", credit: "Cherry Laithang on Unsplash", }, ] export function ItemHeaderDemo() { return ( <div className="flex w-full max-w-xl flex-col gap-6"> <ItemGroup className="grid grid-cols-3 gap-4"> {models.map((model) => ( <Item key={model.name} variant="outline"> <ItemHeader> <Image src={model.image} alt={model.name} width={128} height={128} className="aspect-square w-full rounded-sm object-cover" /> </ItemHeader> <ItemContent> <ItemTitle>{model.name}</ItemTitle> <ItemDescription>{model.description}</ItemDescription> </ItemContent> </Item> ))} </ItemGroup> </div> ) } Link
To render an item as a link, use the asChild prop. The hover and focus states will be applied to the anchor element.
import { ChevronRightIcon, ExternalLinkIcon } from "lucide-react" import { Item, ItemActions, ItemContent, ItemDescription, ItemTitle, } from "@/components/ui/item" export function ItemLink() { return ( <div className="flex w-full max-w-md flex-col gap-4"> <Item asChild> <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> </a> </Item> <Item variant="outline" asChild> <a href="#" target="_blank" rel="noopener noreferrer"> <ItemContent> <ItemTitle>External resource</ItemTitle> <ItemDescription> Opens in a new tab with security attributes. </ItemDescription> </ItemContent> <ItemActions> <ExternalLinkIcon className="size-4" /> </ItemActions> </a> </Item> </div> ) } <Item asChild> <a href="/dashboard"> <ItemMedia /> <ItemContent> <ItemTitle>Dashboard</ItemTitle> <ItemDescription>Overview of your account and activity.</ItemDescription> </ItemContent> <ItemActions /> </a> </Item>Dropdown
"use client" import { ChevronDownIcon } from "lucide-react" import { Avatar, AvatarFallback, AvatarImage, } from "@/components/ui/avatar" import { Button } from "@/components/ui/button" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { Item, ItemContent, ItemDescription, ItemMedia, ItemTitle, } from "@/components/ui/item" const people = [ { username: "shadcn", avatar: "https://github.com/shadcn.png", email: "shadcn@vercel.com", }, { username: "maxleiter", avatar: "https://github.com/maxleiter.png", email: "maxleiter@vercel.com", }, { username: "evilrabbit", avatar: "https://github.com/evilrabbit.png", email: "evilrabbit@vercel.com", }, ] export function ItemDropdown() { return ( <div className="flex min-h-64 w-full max-w-md flex-col items-center gap-6"> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" size="sm" className="w-fit"> Select <ChevronDownIcon /> </Button> </DropdownMenuTrigger> <DropdownMenuContent className="w-72 [--radius:0.65rem]" align="end"> {people.map((person) => ( <DropdownMenuItem key={person.username} className="p-0"> <Item size="sm" className="w-full p-2"> <ItemMedia> <Avatar className="size-8"> <AvatarImage src={person.avatar} className="grayscale" /> <AvatarFallback>{person.username.charAt(0)}</AvatarFallback> </Avatar> </ItemMedia> <ItemContent className="gap-0.5"> <ItemTitle>{person.username}</ItemTitle> <ItemDescription>{person.email}</ItemDescription> </ItemContent> </Item> </DropdownMenuItem> ))} </DropdownMenuContent> </DropdownMenu> </div> ) } API Reference
Item
The main component for displaying content with media, title, description, and actions.
| Prop | Type | Default |
|---|---|---|
variant | "default" | "outline" | "muted" | "default" |
size | "default" | "sm" | "default" |
asChild | boolean | false |
<Item size="" variant=""> <ItemMedia /> <ItemContent> <ItemTitle>Item</ItemTitle> <ItemDescription>Item</ItemDescription> </ItemContent> <ItemActions /> </Item>You can use the asChild prop to render a custom component as the item, for example a link. The hover and focus states will be applied to the custom component.
import { Item, ItemContent, ItemDescription, ItemMedia, ItemTitle, } from "@/components/ui/item" export function ItemLink() { return ( <Item asChild> <a href="/dashboard"> <ItemMedia variant="icon"> <Home /> </ItemMedia> <ItemContent> <ItemTitle>Dashboard</ItemTitle> <ItemDescription> Overview of your account and activity. </ItemDescription> </ItemContent> </a> </Item> ) }ItemGroup
The ItemGroup component is a container that groups related items together with consistent styling.
| Prop | Type | Default |
|---|---|---|
className | string |
<ItemGroup> <Item /> <Item /> </ItemGroup>ItemSeparator
The ItemSeparator component is a separator that separates items in the item group.
| Prop | Type | Default |
|---|---|---|
className | string |
<ItemGroup> <Item /> <ItemSeparator /> <Item /> </ItemGroup>ItemMedia
Use the ItemMedia component to display media content such as icons, images, or avatars.
| Prop | Type | Default |
|---|---|---|
variant | "default" | "icon" | "image" | "default" |
className | string |
<ItemMedia variant="icon"> <Icon /> </ItemMedia><ItemMedia variant="image"> <img src="..." alt="..." /> </ItemMedia>ItemContent
The ItemContent component wraps the title and description of the item.
You can skip ItemContent if you only need a title.
| Prop | Type | Default |
|---|---|---|
className | string |
<ItemContent> <ItemTitle>Item</ItemTitle> <ItemDescription>Item</ItemDescription> </ItemContent>ItemTitle
Use the ItemTitle component to display the title of the item.
| Prop | Type | Default |
|---|---|---|
className | string |
<ItemTitle>Item Title</ItemTitle>ItemDescription
Use the ItemDescription component to display the description of the item.
| Prop | Type | Default |
|---|---|---|
className | string |
<ItemDescription>Item description</ItemDescription>ItemActions
Use the ItemActions component to display action buttons or other interactive elements.
| Prop | Type | Default |
|---|---|---|
className | string |
<ItemActions> <Button>Action</Button> <Button>Action</Button> </ItemActions>ItemHeader
Use the ItemHeader component to display a header in the item.
| Prop | Type | Default |
|---|---|---|
className | string |
<ItemHeader>Item Header</ItemHeader>ItemFooter
Use the ItemFooter component to display a footer in the item.
| Prop | Type | Default |
|---|---|---|
className | string |
<ItemFooter>Item Footer</ItemFooter>