shadcn.io is not affiliated with official shadcn/ui
Shadcn Item for React and Tailwind
A versatile component for displaying content.
Basic Item
A simple item with title and description.
Your profile has been verified.
Installation
bunx --bun shadcn@latest add https://kit.dev/r/item.jsonpnpm dlx shadcn@latest add https://kit.dev/r/item.jsonnpx shadcn@latest add https://kit.dev/r/item.jsonyarn shadcn@latest add https://kit.dev/r/item.jsonThis component depends on Separator. Install it first if you haven't already.
Install the following dependencies:
bun add @ark-ui/react tailwind-variantspnpm add @ark-ui/react tailwind-variantsnpm install @ark-ui/react tailwind-variantsyarn add @ark-ui/react tailwind-variantsCopy and paste the following code into your project.
"use client";
import { ark } from "@ark-ui/react/factory";
import type React from "react";
import { tv, type VariantProps } from "tailwind-variants";
import { cn } from "@/lib/utils";
import { Separator } from "@/components/ui/separator";
export const ItemGroup = (props: React.ComponentProps<typeof ark.div>) => {
const { className, ...rest } = props;
return (
<ark.div
className={cn(
"group/item-group",
"flex w-full flex-col gap-4",
className
)}
data-slot="item-group"
role="list"
{...rest}
/>
);
};
export const ItemSeparator = (
props: React.ComponentProps<typeof Separator>
) => {
const { className, ...rest } = props;
return (
<Separator
className={cn("my-2", className)}
data-slot="item-separator"
orientation="horizontal"
{...rest}
/>
);
};
const itemVariants = tv({
base: [
"[--space:--spacing(3)]",
"group/item",
"flex w-full flex-wrap items-center",
"gap-(--space) p-(--space)",
"in-data-[slot=menu-content]:p-0",
"text-sm",
"rounded-xl border",
"transition-colors duration-100",
"[a]:transition-colors [a]:hover:bg-muted",
"outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-ring/32",
"[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
],
variants: {
variant: {
default: "border-transparent",
outline: "border-border shadow-xs/5",
muted: "border-transparent bg-muted/48 shadow-muted/5 shadow-xs",
},
},
defaultVariants: {
variant: "default",
},
});
interface ItemProps
extends React.ComponentProps<typeof ark.div>,
VariantProps<typeof itemVariants> {}
export const Item = (props: ItemProps) => {
const { variant = "default", className, ...rest } = props;
return (
<ark.div
className={cn(itemVariants({ variant }), className)}
data-slot="item"
data-variant={variant}
{...rest}
/>
);
};
const itemMediaVariants = tv({
base: [
"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",
"rounded-xl",
"overflow-hidden",
"[&_img]:size-full [&_img]:object-cover",
],
},
},
defaultVariants: {
variant: "default",
},
});
interface ItemMediaProps
extends React.ComponentProps<typeof ark.div>,
VariantProps<typeof itemMediaVariants> {}
export const ItemMedia = (props: ItemMediaProps) => {
const { variant = "default", className, ...rest } = props;
return (
<ark.div
className={cn(itemMediaVariants({ variant, className }))}
data-slot="item-media"
data-variant={variant}
{...rest}
/>
);
};
export const ItemContent = (props: React.ComponentProps<typeof ark.div>) => {
const { className, ...rest } = props;
return (
<ark.div
className={cn(
"flex flex-1 flex-col gap-0.5",
"[&+[data-slot=item-content]]:flex-none",
className
)}
data-slot="item-content"
{...rest}
/>
);
};
export const ItemTitle = (props: React.ComponentProps<typeof ark.div>) => {
const { className, ...rest } = props;
return (
<ark.div
className={cn(
"w-fit",
"flex items-center gap-2",
"line-clamp-1 font-medium text-sm leading-snug",
"underline-offset-4",
className
)}
data-slot="item-title"
{...rest}
/>
);
};
export const ItemDescription = (props: React.ComponentProps<typeof ark.p>) => {
const { className, ...rest } = props;
return (
<ark.p
className={cn(
"line-clamp-2 text-left font-normal text-muted-foreground text-sm leading-normal",
"[&>a:hover]:text-primary",
"[&>a]:underline [&>a]:underline-offset-4",
className
)}
data-slot="item-description"
{...rest}
/>
);
};
export const ItemActions = (props: React.ComponentProps<typeof ark.div>) => {
const { className, ...rest } = props;
return (
<ark.div
className={cn("flex items-center gap-2", className)}
data-slot="item-actions"
{...rest}
/>
);
};
export const ItemHeader = (props: React.ComponentProps<typeof ark.div>) => {
const { className, ...rest } = props;
return (
<ark.div
className={cn(
"flex basis-full items-center justify-between gap-2",
"[&_img]:size-full [&_img]:rounded-xl [&_img]:object-cover",
className
)}
data-slot="item-header"
{...rest}
/>
);
};
export const ItemFooter = (props: React.ComponentProps<typeof ark.div>) => {
const { className, ...rest } = props;
return (
<ark.div
className={cn(
"flex basis-full items-center justify-between gap-2",
className
)}
data-slot="item-footer"
{...rest}
/>
);
};Update the import paths to match your project setup.
Usage
import { BadgeCheck, ChevronRight, Ellipsis } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
Item,
ItemActions,
ItemContent,
ItemDescription,
ItemMedia,
ItemTitle,
} from "@/components/ui/item";<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 size="icon-sm" variant="outline">
<Ellipsis />
</Button>
</ItemActions>
</Item>
<Item variant="outline">
<ItemMedia>
<BadgeCheck className="size-5" />
</ItemMedia>
<ItemContent>
<ItemTitle>Your profile has been verified.</ItemTitle>
</ItemContent>
<ItemActions>
<ChevronRight className="size-4" />
</ItemActions>
</Item>
</div>Accessibility
| Key | Description |
|---|---|
Enter | Activate the focused control. |
Space | Activate the focused control. |
Demos
Avatar
Basic
Custom Spacing
Dropdown
Group
Header
Icon
Image
Link
Variant Default
Variant Muted
Variant Outline
API Reference
Item
div
PropType
AttributeType
ItemGroup
div
PropType
AttributeType
ItemSeparator
div
PropType
AttributeType
CSS variableType
ItemMedia
div
PropType
AttributeType
ItemContent
div
PropType
AttributeType
ItemTitle
div
PropType
AttributeType
ItemDescription
p
PropType
AttributeType
ItemActions
div
PropType
AttributeType
ItemHeader
div
PropType
AttributeType
ItemFooter
div
PropType
AttributeType