Item
A versatile component for displaying content with media, title, description, and actions.
The ItemSeparator component is built on top of Kobalte Separator, which provides the accessible separator primitive.
A simple item with title and description.
import { BadgeCheck, ChevronRight } from "lucide-solid";
import { Button } from "~/components/ui/button";import { Item, ItemActions, ItemContent, ItemDescription, ItemMedia, ItemTitle,} from "~/components/ui/item";
export default function ItemDemo() { return ( <div class="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 as="a" href="#item-demo" variant="outline" size="sm"> <ItemMedia> <BadgeCheck class="size-5" /> </ItemMedia> <ItemContent> <ItemTitle>Your profile has been verified.</ItemTitle> </ItemContent> <ItemActions> <ChevronRight class="size-4" /> </ItemActions> </Item> </div> );}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 ItemGroup to create a list of items.
Installation
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
Use the following composition to build an Item:
ItemGroup└── Item ├── ItemHeader ├── ItemMedia ├── ItemContent │ ├── ItemTitle │ └── ItemDescription ├── ItemActions └── ItemFooterItem 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.
Variant
Use the variant prop to change the visual style of the item.
Transparent background with no border.
Outlined style with a visible border.
Muted background for secondary content.
import { Inbox } from "lucide-solid";
import { Item, ItemContent, ItemDescription, ItemMedia, ItemTitle,} from "~/components/ui/item";
export default function ItemVariant() { return ( <div class="flex w-full max-w-md flex-col gap-6"> <Item> <ItemMedia variant="icon"> <Inbox /> </ItemMedia> <ItemContent> <ItemTitle>Default Variant</ItemTitle> <ItemDescription>Transparent background with no border.</ItemDescription> </ItemContent> </Item> <Item variant="outline"> <ItemMedia variant="icon"> <Inbox /> </ItemMedia> <ItemContent> <ItemTitle>Outline Variant</ItemTitle> <ItemDescription>Outlined style with a visible border.</ItemDescription> </ItemContent> </Item> <Item variant="muted"> <ItemMedia variant="icon"> <Inbox /> </ItemMedia> <ItemContent> <ItemTitle>Muted Variant</ItemTitle> <ItemDescription>Muted background for secondary content.</ItemDescription> </ItemContent> </Item> </div> );}Size
Use the size prop to change the size of the item. Available sizes are default, sm, and xs.
The standard size for most use cases.
A compact size for dense layouts.
The most compact size available.
import { Inbox } from "lucide-solid";
import { Item, ItemContent, ItemDescription, ItemMedia, ItemTitle,} from "~/components/ui/item";
export default function ItemSize() { return ( <div class="flex w-full max-w-md flex-col gap-6"> <Item variant="outline"> <ItemMedia variant="icon"> <Inbox /> </ItemMedia> <ItemContent> <ItemTitle>Default Size</ItemTitle> <ItemDescription>The standard size for most use cases.</ItemDescription> </ItemContent> </Item> <Item variant="outline" size="sm"> <ItemMedia variant="icon"> <Inbox /> </ItemMedia> <ItemContent> <ItemTitle>Small Size</ItemTitle> <ItemDescription>A compact size for dense layouts.</ItemDescription> </ItemContent> </Item> <Item variant="outline" size="xs"> <ItemMedia variant="icon"> <Inbox /> </ItemMedia> <ItemContent> <ItemTitle>Extra Small Size</ItemTitle> <ItemDescription>The most compact size available.</ItemDescription> </ItemContent> </Item> </div> );}Icon
Use ItemMedia with variant="icon" to display an icon.
New login detected from unknown device.
import { ShieldAlert } from "lucide-solid";
import { Button } from "~/components/ui/button";import { Item, ItemActions, ItemContent, ItemDescription, ItemMedia, ItemTitle,} from "~/components/ui/item";
export default function ItemIcon() { return ( <div class="flex w-full max-w-lg flex-col gap-6"> <Item variant="outline"> <ItemMedia variant="icon"> <ShieldAlert /> </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
Wrap an Avatar in ItemMedia to display an avatar.
Last seen 5 months ago
Invite your team to collaborate on this project.
import { Plus } from "lucide-solid";
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 default function ItemAvatar() { return ( <div class="flex w-full max-w-lg flex-col gap-6"> <Item variant="outline"> <ItemMedia> <Avatar class="size-10"> <AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" /> <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" class="rounded-full" aria-label="Invite"> <Plus /> </Button> </ItemActions> </Item> <Item variant="outline"> <ItemMedia> <div class="flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background *:data-[slot=avatar]:grayscale"> <Avatar class="hidden sm:flex"> <AvatarImage src="https://github.com/carere.png" alt="@carere" /> <AvatarFallback>CR</AvatarFallback> </Avatar> <Avatar class="hidden sm:flex"> <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" /> <AvatarFallback>CN</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
Use ItemMedia with variant="image" to display an image.
import { For } from "solid-js";
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 default function ItemImage() { return ( <div class="flex w-full max-w-md flex-col gap-6"> <ItemGroup class="gap-4"> <For each={music}> {(song) => ( <Item as="a" href="#item-image" variant="outline" role="listitem"> <ItemMedia variant="image"> <img src={`https://avatar.vercel.sh/${song.title}`} alt={song.title} width="32" height="32" class="object-cover grayscale" /> </ItemMedia> <ItemContent> <ItemTitle class="line-clamp-1"> {song.title} - <span class="text-muted-foreground">{song.album}</span> </ItemTitle> <ItemDescription>{song.artist}</ItemDescription> </ItemContent> <ItemContent class="flex-none text-center"> <ItemDescription>{song.duration}</ItemDescription> </ItemContent> </Item> )} </For> </ItemGroup> </div> );}Group
Use ItemGroup to group related items together.
carere@example.com
shadcn@vercel.com
evilrabbit@vercel.com
import { Plus } from "lucide-solid";import { For } from "solid-js";
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";import { Button } from "~/components/ui/button";import { Item, ItemActions, ItemContent, ItemDescription, ItemGroup, ItemMedia, ItemTitle,} from "~/components/ui/item";
const people = [ { username: "carere", avatar: "https://github.com/carere.png", email: "carere@example.com" }, { username: "shadcn", avatar: "https://github.com/shadcn.png", email: "shadcn@vercel.com" }, { username: "evilrabbit", avatar: "https://github.com/evilrabbit.png", email: "evilrabbit@vercel.com", },];
export default function ItemGroupDemo() { return ( <ItemGroup class="max-w-sm"> <For each={people}> {(person) => ( <Item variant="outline" role="listitem"> <ItemMedia> <Avatar> <AvatarImage src={person.avatar} alt={`@${person.username}`} class="grayscale" /> <AvatarFallback>{person.username.charAt(0)}</AvatarFallback> </Avatar> </ItemMedia> <ItemContent class="gap-1"> <ItemTitle>{person.username}</ItemTitle> <ItemDescription>{person.email}</ItemDescription> </ItemContent> <ItemActions> <Button variant="ghost" size="icon" class="rounded-full" aria-label={`Add ${person.username}`} > <Plus /> </Button> </ItemActions> </Item> )} </For> </ItemGroup> );}Header
Use ItemHeader to add a header above the item content.
Everyday tasks and UI generation.
Advanced thinking or reasoning.
Open Source model for everyone.
import { For } from "solid-js";
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", }, { 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", }, { 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", },];
export default function ItemHeaderDemo() { return ( <div class="flex w-full max-w-xl flex-col gap-6"> <ItemGroup class="grid grid-cols-3 gap-4"> <For each={models}> {(model) => ( <Item variant="outline" role="listitem"> <ItemHeader> <img src={model.image} alt={model.name} width="128" height="128" class="aspect-square w-full rounded-sm object-cover" /> </ItemHeader> <ItemContent> <ItemTitle>{model.name}</ItemTitle> <ItemDescription>{model.description}</ItemDescription> </ItemContent> </Item> )} </For> </ItemGroup> </div> );}Link
Set as="a" to render the item as a link. The hover and focus states apply to the anchor element.
import { ChevronRight, ExternalLink } from "lucide-solid";
import { Item, ItemActions, ItemContent, ItemDescription, ItemTitle,} from "~/components/ui/item";
export default function ItemLink() { return ( <div class="flex w-full max-w-md flex-col gap-4"> <Item as="a" href="#item-link"> <ItemContent> <ItemTitle>Visit our documentation</ItemTitle> <ItemDescription>Learn how to get started with our components.</ItemDescription> </ItemContent> <ItemActions> <ChevronRight class="size-4" /> </ItemActions> </Item> <Item as="a" href="https://zaidan.dev" target="_blank" rel="noopener noreferrer" variant="outline" > <ItemContent> <ItemTitle>External resource</ItemTitle> <ItemDescription>Opens in a new tab with security attributes.</ItemDescription> </ItemContent> <ItemActions> <ExternalLink class="size-4" /> </ItemActions> </Item> </div> );}<Item as="a" href="/dashboard"> <ItemMedia variant="icon"> <Home /> </ItemMedia> <ItemContent> <ItemTitle>Dashboard</ItemTitle> <ItemDescription>Overview of your account and activity.</ItemDescription> </ItemContent></Item>Dropdown
import { ChevronDown } from "lucide-solid";import { For } from "solid-js";
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";import { buttonVariants } from "~/components/ui/button";import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuTrigger,} from "~/components/ui/dropdown-menu";import { Item, ItemContent, ItemDescription, ItemMedia, ItemTitle,} from "~/components/ui/item";
const people = [ { username: "carere", avatar: "https://github.com/carere.png", email: "carere@example.com" }, { username: "shadcn", avatar: "https://github.com/shadcn.png", email: "shadcn@vercel.com" }, { username: "evilrabbit", avatar: "https://github.com/evilrabbit.png", email: "evilrabbit@vercel.com", },];
export default function ItemDropdown() { return ( <DropdownMenu placement="bottom-end"> <DropdownMenuTrigger class={buttonVariants({ variant: "outline" })}> Select <ChevronDown /> </DropdownMenuTrigger> <DropdownMenuContent class="w-48"> <DropdownMenuGroup> <For each={people}> {(person) => ( <DropdownMenuItem textValue={person.username}> <Item size="xs" class="w-full p-2"> <ItemMedia> <Avatar class="size-[--spacing(6.5)]"> <AvatarImage src={person.avatar} alt={`@${person.username}`} class="grayscale" /> <AvatarFallback>{person.username.charAt(0)}</AvatarFallback> </Avatar> </ItemMedia> <ItemContent class="gap-0"> <ItemTitle>{person.username}</ItemTitle> <ItemDescription class="leading-none">{person.email}</ItemDescription> </ItemContent> </Item> </DropdownMenuItem> )} </For> </DropdownMenuGroup> </DropdownMenuContent> </DropdownMenu> );}API Reference
Item
The main component for displaying content with media, title, description, and actions.
ItemGroup
A container that groups related items together with consistent styling.
<ItemGroup> <Item /> <ItemSeparator /> <Item /></ItemGroup>ItemSeparator
A separator between items in a group. It accepts Kobalte Separator props.
ItemMedia
Use ItemMedia to display media content such as icons, images, or avatars.
<ItemMedia variant="icon"> <Icon /></ItemMedia>ItemContent
Wraps the title and description of the item.
<ItemContent> <ItemTitle>Title</ItemTitle> <ItemDescription>Description</ItemDescription></ItemContent>ItemTitle
Displays the title of the item.
ItemDescription
Displays the description of the item.
ItemActions
Container for action buttons or other interactive elements.
ItemHeader
Displays a header above the item content.
ItemFooter
Displays a footer below the item content.