Meet Frontfriend.Your brand. Your rules. Your agents, connected.Explore what’s new

Item

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

Interactive preview

Rendered from the shared Frontfriend stories with React Base, the same preview Studio shows. Styling comes from your Design System; the code below is native to Radix UI.

Installation

Complete project setup first. Your configuration must select react/radix and include your Design System ID.

pnpm exec frontfriend download item -f react --primitive radix

Review dependencies reported by the downloader and keep your source changes in version control.

Usage

import {
  Item,
  ItemContent,
  ItemTitle,
  ItemDescription,
  ItemActions,
} from "@/components/ui/item";
import { Button } from "@/components/ui/button";
<div className="w-[28rem] max-w-full">
  <Item size="default" variant="outline">
    <ItemContent>
      <ItemTitle>Basic Item</ItemTitle>
      <ItemDescription>
        A simple item with title and description.
      </ItemDescription>
    </ItemContent>
    <ItemActions>
      <Button variant="tertiary" size="sm">
        Action
      </Button>
    </ItemActions>
  </Item>
</div>;

Examples

Default

import {
  Item,
  ItemContent,
  ItemTitle,
  ItemDescription,
  ItemActions,
} from "@/components/ui/item";
import { Button } from "@/components/ui/button";
<div className="w-[28rem] max-w-full">
  <Item  variant="outline">
    <ItemContent>
      <ItemTitle>Basic Item</ItemTitle>
      <ItemDescription>
        A simple item with title and description.
      </ItemDescription>
    </ItemContent>
    <ItemActions>
      <Button variant="tertiary" size="sm">
        Action
      </Button>
    </ItemActions>
  </Item>
</div>;

Variant

import {
  Item,
  ItemMedia,
  ItemContent,
  ItemTitle,
  ItemDescription,
} from "@/components/ui/item";
import { InboxIcon } from "lucide-react";
<div className="flex w-[28rem] max-w-full flex-col gap-6">
  <Item>
    <ItemMedia variant="icon">
      <InboxIcon />
    </ItemMedia>
    <ItemContent>
      <ItemTitle>Default Variant</ItemTitle>
      <ItemDescription>Transparent background with no border.</ItemDescription>
    </ItemContent>
  </Item>
  <Item variant="outline">
    <ItemMedia variant="icon">
      <InboxIcon />
    </ItemMedia>
    <ItemContent>
      <ItemTitle>Outline Variant</ItemTitle>
      <ItemDescription>Outlined style with a visible border.</ItemDescription>
    </ItemContent>
  </Item>
  <Item variant="muted">
    <ItemMedia variant="icon">
      <InboxIcon />
    </ItemMedia>
    <ItemContent>
      <ItemTitle>Muted Variant</ItemTitle>
      <ItemDescription>Muted background for secondary content.</ItemDescription>
    </ItemContent>
  </Item>
</div>;

Size

import {
  Item,
  ItemContent,
  ItemTitle,
  ItemDescription,
} from "@/components/ui/item";
<div className="flex w-[28rem] max-w-full flex-col gap-6">
  <Item variant="outline">
    <ItemContent>
      <ItemTitle>Default Size</ItemTitle>
      <ItemDescription>Comfortable padding and spacing.</ItemDescription>
    </ItemContent>
  </Item>
  <Item variant="outline" size="sm">
    <ItemContent>
      <ItemTitle>Small Size</ItemTitle>
      <ItemDescription>Compact padding and spacing.</ItemDescription>
    </ItemContent>
  </Item>
</div>;

Icon

import {
  Item,
  ItemMedia,
  ItemContent,
  ItemTitle,
  ItemDescription,
  ItemActions,
} from "@/components/ui/item";
import { ShieldAlertIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
<div className="w-[32rem] max-w-full">
  <Item variant="outline">
    <ItemMedia variant="icon">
      <ShieldAlertIcon />
    </ItemMedia>
    <ItemContent>
      <ItemTitle>Security Alert</ItemTitle>
      <ItemDescription>New login detected from unknown device.</ItemDescription>
    </ItemContent>
    <ItemActions>
      <Button size="sm" variant="tertiary">
        Review
      </Button>
    </ItemActions>
  </Item>
</div>;

Group

import {
  ItemGroup,
  Item,
  ItemMedia,
  ItemContent,
  ItemTitle,
  ItemDescription,
  ItemActions,
  ItemSeparator,
} from "@/components/ui/item";
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { PlusIcon } from "lucide-react";
import * as React from "react";
const people = [
  {
    username: "shadcn",
    avatar: "https://github.com/shadcn.png",
    email: "shadcn@vercel.com",
  },
  {
    username: "maxleiter",
    avatar: "https://github.com/maxleiter.png",
    email: "maxleiter@vercel.com",
  },
  {
    username: "evilrabbit",
    avatar: "https://github.com/evilrabbit.png",
    email: "evilrabbit@vercel.com",
  },
];
<ItemGroup className="w-sm max-w-full">
  {people.map((person, index) => (
    <React.Fragment key={person.username}>
      <Item variant="outline">
        <ItemMedia>
          <Avatar>
            <AvatarImage src={person.avatar} className="grayscale" />
            <AvatarFallback>{person.username.charAt(0)}</AvatarFallback>
          </Avatar>
        </ItemMedia>
        <ItemContent className="gap-1">
          <ItemTitle>{person.username}</ItemTitle>
          <ItemDescription>{person.email}</ItemDescription>
        </ItemContent>
        <ItemActions>
          <Button variant="ghost" size="icon" className="rounded-full">
            <PlusIcon />
          </Button>
        </ItemActions>
      </Item>
      {index < people.length - 1 && <ItemSeparator />}
    </React.Fragment>
  ))}
</ItemGroup>;

Header

import {
  Item,
  ItemHeader,
  ItemTitle,
  ItemContent,
  ItemDescription,
} from "@/components/ui/item";
import { Button } from "@/components/ui/button";
<div className="w-[28rem] max-w-full">
  <Item variant="outline">
    <ItemHeader>
      <ItemTitle>Notifications</ItemTitle>
      <Button variant="ghost" size="sm">
        Mark all read
      </Button>
    </ItemHeader>
    <ItemContent>
      <ItemDescription>
        You have 3 unread messages in your inbox.
      </ItemDescription>
    </ItemContent>
  </Item>
</div>;
import {
  Item,
  ItemContent,
  ItemTitle,
  ItemDescription,
  ItemActions,
} from "@/components/ui/item";
import { ChevronRightIcon, ExternalLinkIcon } from "lucide-react";
<div className="flex w-[28rem] max-w-full flex-col gap-4">
  <Item asChild>
    <a href="#">
      <ItemContent>
        <ItemTitle>Visit our documentation</ItemTitle>
        <ItemDescription>
          Learn how to get started with our components.
        </ItemDescription>
      </ItemContent>
      <ItemActions>
        <ChevronRightIcon className="size-4" />
      </ItemActions>
    </a>
  </Item>
  <Item variant="outline" asChild>
    <a href="#" target="_blank" rel="noopener noreferrer">
      <ItemContent>
        <ItemTitle>External resource</ItemTitle>
        <ItemDescription>
          Opens in a new tab with security attributes.
        </ItemDescription>
      </ItemContent>
      <ItemActions>
        <ExternalLinkIcon className="size-4" />
      </ItemActions>
    </a>
  </Item>
</div>;

API reference

Frontfriend-owned props. Native HTML and inherited primitive props remain documented by Radix UI.

Item

Prop Type Default Description
asChild boolean false Render the item as its child element (e.g. a link).
size "default" | "sm" | "xs" "default" Change the size of the item.
variant "default" | "outline" | "muted" "default" Change the visual style of the item.

ItemMedia

Prop Type Default Description
variant "default" | "icon" | "image" "default"

Configuration determines the actual classes and available styling hooks. See Theming & component configuration before introducing a repeated local override.