Sabil UI

Search documentation

Search for a command to run...

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#

  1. Install the dependencies

    npm install class-variance-authority cn radix-ui
  2. Copy the source into your project

    components/ui/item.tsx
    import * 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,}
  3. 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
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.

Icon

Security Alert

New login detected from unknown device.

Size

Default Size

The standard size for most use cases.

Small Size

A compact size for dense layouts.

Extra Small Size

The most compact size available.

Variant

Default Variant

Transparent background with no border.

Outline Variant

Outlined style with a visible border.

Muted Variant

Muted background for secondary content.