Components
Item
A versatile component for displaying content with media, title, description and actions.
Basic Item
A simple item with title and description.
Your profile has been verified.
Installation#
Install the dependencies
npm install class-variance-authority cn radix-uiCopy the source into your project
components/ui/item.tsximport * as React from "react"import { cva, type VariantProps } from "class-variance-authority"import { cn } from "cn"import { Slot } from "radix-ui"import { Separator } from "@/components/ui/separator"function ItemGroup({ className, ...props }: React.ComponentProps<"div">) { return ( <div role="list" data-slot="item-group" className={cn( "group/item-group flex w-full flex-col gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2", className )} {...props} /> )}function ItemSeparator({ className, ...props}: React.ComponentProps<typeof Separator>) { return ( <Separator data-slot="item-separator" orientation="horizontal" className={cn("my-2", className)} {...props} /> )}const itemVariants = cva( "group/item flex w-full flex-wrap items-center rounded-lg border text-sm transition-colors duration-100 outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 [a]:transition-colors [a]:hover:bg-muted", { variants: { variant: { default: "border-transparent", outline: "border-border", muted: "border-transparent bg-muted/50", }, size: { default: "gap-2.5 px-3 py-2.5", sm: "gap-2.5 px-3 py-2.5", xs: "gap-2 px-2.5 py-2 in-data-[slot=dropdown-menu-content]:p-0", }, }, defaultVariants: { variant: "default", size: "default", }, })function Item({ className, variant = "default", size = "default", asChild = false, ...props}: React.ComponentProps<"div"> & VariantProps<typeof itemVariants> & { asChild?: boolean }) { const Comp = asChild ? Slot.Root : "div" return ( <Comp data-slot="item" data-variant={variant} data-size={size} className={cn(itemVariants({ variant, size, className }))} {...props} /> )}const itemMediaVariants = cva( "flex shrink-0 items-center justify-center gap-2 group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start [&_svg]:pointer-events-none", { variants: { variant: { default: "bg-transparent", icon: "[&_svg:not([class*='size-'])]:size-4", image: "size-10 overflow-hidden rounded-sm group-data-[size=sm]/item:size-8 group-data-[size=xs]/item:size-6 [&_img]:size-full [&_img]:object-cover", }, }, defaultVariants: { variant: "default", }, })function ItemMedia({ className, variant = "default", ...props}: React.ComponentProps<"div"> & VariantProps<typeof itemMediaVariants>) { return ( <div data-slot="item-media" data-variant={variant} className={cn(itemMediaVariants({ variant, className }))} {...props} /> )}function ItemContent({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="item-content" className={cn( "flex flex-1 flex-col gap-1 group-data-[size=xs]/item:gap-0 [&+[data-slot=item-content]]:flex-none", className )} {...props} /> )}function ItemTitle({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="item-title" className={cn( "line-clamp-1 flex w-fit items-center gap-2 text-sm leading-snug font-medium underline-offset-4", className )} {...props} /> )}function ItemDescription({ className, ...props }: React.ComponentProps<"p">) { return ( <p data-slot="item-description" className={cn( "line-clamp-2 text-left text-sm leading-normal font-normal text-muted-foreground group-data-[size=xs]/item:text-xs [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary", className )} {...props} /> )}function ItemActions({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="item-actions" className={cn("flex items-center gap-2", className)} {...props} /> )}function ItemHeader({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="item-header" className={cn( "flex basis-full items-center justify-between gap-2", className )} {...props} /> )}function ItemFooter({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="item-footer" className={cn( "flex basis-full items-center justify-between gap-2", className )} {...props} /> )}export { Item, ItemMedia, ItemContent, ItemActions, ItemGroup, ItemSeparator, ItemTitle, ItemDescription, ItemHeader, ItemFooter,}Make sure the foundation is in place
Components read their colors, radius and surfaces from the tokens in
app/globals.css. See Theming.
Usage#
import { Item, ItemMedia, ItemContent, ItemActions, ItemGroup, ItemSeparator, ItemTitle, ItemDescription, ItemHeader, ItemFooter,} from "@/components/ui/item"Examples#
Avatar
ER
Evil Rabbit
Last seen 5 months ago
ER
No Team Members
Invite your team to collaborate on this project.
Dropdown
Group
m
maya
maya@example.com
m
maxleiter
maxleiter@vercel.com
e
evilrabbit
evilrabbit@vercel.com
Header
v0-1.5-sm
Everyday tasks and UI generation.
v0-1.5-lg
Advanced thinking or reasoning.
v0-2.0-mini
Open Source model for everyone.
Icon
Security Alert
New login detected from unknown device.
Image
Link
Size
Default Size
The standard size for most use cases.
Small Size
A compact size for dense layouts.
Variant
Default Variant
Transparent background with no border.
Outline Variant
Outlined style with a visible border.
Muted Variant
Muted background for secondary content.