Presets

Blocks

Get PRO

Need premium blocks and templates? Upgrade to PRO and get access.

Upgrade
JoinLogin
Presets
Monochrome
Overview
  • Introduction
  • Components
  • Installation
Components
  • Accordion
  • Alert
  • Alert Dialog
  • Aspect Ratio
  • Avatar
  • Badge
  • Breadcrumb
  • Button
  • Button Group
  • CalendarNEW
  • Card
  • CarouselNEW
  • Checkbox
  • Collapsible
  • Dialog
  • Dropdown Menu
  • Empty
  • Field
  • Input
  • Input Group
  • Item
  • Kbd
  • Label
  • Native Select
  • Scroll Area
  • SelectNEW
  • Separator
  • SwitchNEW
  • Table
  • Tabs
  • Textarea
  • TooltipNEW

Item

PreviousNext

A versatile component for displaying content with media, title, description, and actions.

1import { Button } from "@/components/ui/button";2import {3  Item,4  ItemActions,

Installation

pnpm dlx sprawlify@latest add item
npx sprawlify@latest add item
yarn sprawlify@latest add item
bunx --bun sprawlify@latest add item

Install the following dependencies:

pnpm add @sprawlify/primitives @sprawlify/solid
npm install @sprawlify/primitives @sprawlify/solid
yarn add @sprawlify/primitives @sprawlify/solid
bun add @sprawlify/primitives @sprawlify/solid

Add the following files to your project:

item.tsx
1import { cva, type VariantProps } from "class-variance-authority";2import { cn } from "@/lib/utils";3import { Separator } from "@/components/ui/separator";4import { sprawlify } from "@sprawlify/solid";5import type { ComponentProps } from "solid-js";6import { splitProps } from "solid-js";78function ItemGroup(props: ComponentProps<typeof sprawlify.div>) {9  const [local, others] = splitProps(props, ["class"]);1011  return (12    <sprawlify.div13      role="list"14      data-scope="item"15      data-part="group"16      data-slot="item-group"17      class={cn(18        "gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2 group/item-group flex w-full flex-col",19        local.class,20      )}21      {...others}22    />23  );24}2526function ItemSeparator(props: ComponentProps<typeof Separator>) {27  const [local, others] = splitProps(props, ["class"]);2829  return (30    <Separator31      data-scope="item"32      data-part="separator"33      data-slot="item-separator"34      orientation="horizontal"35      class={cn("my-2", local.class)}36      {...others}37    />38  );39}4041const itemVariants = cva(42  "[a]:hover:bg-muted rounded-lg border text-sm w-full group/item focus-visible:border-ring focus-visible:ring-ring/50 flex items-center flex-wrap outline-none transition-colors duration-100 focus-visible:ring-[3px] [a]:transition-colors",43  {44    variants: {45      variant: {46        default: "border-transparent",47        outline: "border-border",48        muted: "bg-muted/50 border-transparent",49      },50      size: {51        default: "gap-2.5 px-3 py-2.5",52        sm: "gap-2.5 px-3 py-2.5",53        xs: "gap-2 px-2.5 py-2 in-data-[slot=dropdown-menu-content]:p-0",54      },55    },56    defaultVariants: {57      variant: "default",58      size: "default",59    },60  },61);6263function Item(props: ComponentProps<typeof sprawlify.div> & VariantProps<typeof itemVariants>) {64  const [local, others] = splitProps(props, ["variant", "size", "class"]);65  const variant = () => local.variant ?? "default";66  const size = () => local.size ?? "default";6768  return (69    <sprawlify.div70      data-scope="item"71      data-part="root"72      data-slot="item"73      data-variant={variant()}74      data-size={size()}75      class={cn(itemVariants({ variant: variant(), size: size(), class: local.class }))}76      {...others}77    />78  );79}8081const itemMediaVariants = cva(82  "gap-2 group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start flex shrink-0 items-center justify-center [&_svg]:pointer-events-none",83  {84    variants: {85      variant: {86        default: "bg-transparent",87        icon: "[&_svg:not([class*='size-'])]:size-4",88        image:89          "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",90      },91    },92    defaultVariants: {93      variant: "default",94    },95  },96);9798function ItemMedia(99  props: ComponentProps<typeof sprawlify.div> & VariantProps<typeof itemMediaVariants>,100) {101  const [local, others] = splitProps(props, ["variant", "class"]);102  const variant = () => local.variant ?? "default";103104  return (105    <sprawlify.div106      data-scope="item"107      data-part="media"108      data-slot="item-media"109      data-variant={variant()}110      class={cn(itemMediaVariants({ variant: variant(), class: local.class }))}111      {...others}112    />113  );114}115116function ItemContent(props: ComponentProps<typeof sprawlify.div>) {117  const [local, others] = splitProps(props, ["class"]);118119  return (120    <sprawlify.div121      data-scope="item"122      data-part="content"123      data-slot="item-content"124      class={cn(125        "gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none",126        local.class,127      )}128      {...others}129    />130  );131}132133function ItemTitle(props: ComponentProps<typeof sprawlify.div>) {134  const [local, others] = splitProps(props, ["class"]);135136  return (137    <sprawlify.div138      data-scope="item"139      data-part="title"140      data-slot="item-title"141      class={cn(142        "gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center",143        local.class,144      )}145      {...others}146    />147  );148}149150function ItemDescription(props: ComponentProps<typeof sprawlify.p>) {151  const [local, others] = splitProps(props, ["class"]);152153  return (154    <sprawlify.p155      data-scope="item"156      data-part="description"157      data-slot="item-description"158      class={cn(159        "text-muted-foreground text-left text-sm leading-normal group-data-[size=xs]/item:text-xs [&>a:hover]:text-primary line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4",160        local.class,161      )}162      {...others}163    />164  );165}166167function ItemActions(props: ComponentProps<typeof sprawlify.div>) {168  const [local, others] = splitProps(props, ["class"]);169170  return (171    <sprawlify.div172      data-scope="item"173      data-part="actions"174      data-slot="item-actions"175      class={cn("gap-2 flex items-center", local.class)}176      {...others}177    />178  );179}180181function ItemHeader(props: ComponentProps<typeof sprawlify.div>) {182  const [local, others] = splitProps(props, ["class"]);183184  return (185    <sprawlify.div186      data-scope="item"187      data-part="header"188      data-slot="item-header"189      class={cn("gap-2 flex basis-full items-center justify-between", local.class)}190      {...others}191    />192  );193}194195function ItemFooter(props: ComponentProps<typeof sprawlify.div>) {196  const [local, others] = splitProps(props, ["class"]);197198  return (199    <sprawlify.div200      data-scope="item"201      data-part="footer"202      data-slot="item-footer"203      class={cn("gap-2 flex basis-full items-center justify-between", local.class)}204      {...others}205    />206  );207}208209export {210  Item,211  ItemMedia,212  ItemContent,213  ItemActions,214  ItemGroup,215  ItemSeparator,216  ItemTitle,217  ItemDescription,218  ItemHeader,219  ItemFooter,220};221

Update the import paths to match your project setup.

Usage

1import {
2  ItemGroup,
3  ItemSeparator,
4  Item,
5  ItemMedia,
6  ItemContent,
7  ItemTitle,
8  ItemDescription,
9  ItemAction
10} from "@/components/ui/item"
1<Item>
2  <ItemMedia variant="icon">
3    <Icon />
4  </ItemMedia>
5  <ItemContent>
6    <ItemTitle>Title</ItemTitle>
7    <ItemDescription>Description</ItemDescription>
8  </ItemContent>
9  <ItemActions>
10    <Button>Action</Button>
11  </ItemActions>
12</Item>

Examples

Avatar

You can use ItemMedia with variant="avatar" to display an avatar.

1import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";2import { Button } from "@/components/ui/button";3import {4  Item,

Group

Use ItemGroup to group related items together.

1import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";2import { Button } from "@/components/ui/button";3import {4  Item,

Header

Use ItemHeader to add a header above the item content.

1import {2  Item,3  ItemContent,4  ItemDescription,

Icon

Use ItemMedia with variant="icon" to display an icon.

1import { Button } from "@/components/ui/button";2import {3  Item,4  ItemActions,

Image

Use ItemMedia with variant="image" to display an image.

1import {2  Item,3  ItemContent,4  ItemDescription,

Link

Use the asChild prop to render the item as a link. The hover and focus states will be applied to the anchor element.

1import { Item, ItemActions, ItemContent, ItemDescription, ItemTitle } from "@/components/ui/item";2import { ChevronRightIcon, ExternalLinkIcon } from "lucide-solid";34export default function Preview() {

On This Page

InstallationUsageExamplesAvatarGroupHeaderIconImageLink

Get PRO

Need premium blocks and templates? Upgrade to PRO and get access.