Skip to content
Nerdfishui
Esc
navigateopen⌘Jpreview
On this page

Item

A versatile component that you can use to display any content.

'use client'

import { Button } from '@nerdfish/react/button'
import {
	Item,
	ItemActions,
	ItemContent,
	ItemDescription,
	ItemMedia,
	ItemTitle,
} from '@nerdfish/react/item'
import { BadgeCheckIcon, ChevronRightIcon } from 'lucide-react'

export default function ItemExample() {
	return (
		<div className="gap-casual flex w-full flex-col">
			<Item variant="outline">
				<ItemContent>
					<ItemTitle>Basic Item</ItemTitle>
					<ItemDescription>
						A simple item with title and description.
					</ItemDescription>
				</ItemContent>
				<ItemActions>
					<Button variant="outline" size="sm">
						Action
					</Button>
				</ItemActions>
			</Item>
			<Item variant="outline" size="sm" render={<a href="#" />}>
				<ItemMedia>
					<BadgeCheckIcon className="size-5" />
				</ItemMedia>
				<ItemContent>
					<ItemTitle>Your profile has been verified.</ItemTitle>
				</ItemContent>
				<ItemActions>
					<ChevronRightIcon className="size-4" />
				</ItemActions>
			</Item>
		</div>
	)
}

Item vs Field

Use Field if you need to display a form input such as a checkbox, input, radio, or select.

If you only need to display content such as a title, description, and actions, use Item.

Variants

'use client'

import { Button } from '@nerdfish/react/button'
import {
	Item,
	ItemActions,
	ItemContent,
	ItemDescription,
	ItemTitle,
} from '@nerdfish/react/item'

export default function ItemVariantsExample() {
	return (
		<div className="gap-casual flex flex-col">
			<Item>
				<ItemContent>
					<ItemTitle>Default Variant</ItemTitle>
					<ItemDescription>
						Standard styling with subtle background and borders.
					</ItemDescription>
				</ItemContent>
				<ItemActions>
					<Button variant="outline" size="sm">
						Open
					</Button>
				</ItemActions>
			</Item>
			<Item variant="outline">
				<ItemContent>
					<ItemTitle>Outline Variant</ItemTitle>
					<ItemDescription>
						Outlined style with clear borders and transparent background.
					</ItemDescription>
				</ItemContent>
				<ItemActions>
					<Button variant="outline" size="sm">
						Open
					</Button>
				</ItemActions>
			</Item>
			<Item variant="muted">
				<ItemContent>
					<ItemTitle>Muted Variant</ItemTitle>
					<ItemDescription>
						Subdued appearance with muted colors for secondary content.
					</ItemDescription>
				</ItemContent>
				<ItemActions>
					<Button variant="outline" size="sm">
						Open
					</Button>
				</ItemActions>
			</Item>
		</div>
	)
}

Sizes

'use client'

import { Button } from '@nerdfish/react/button'
import {
	Item,
	ItemActions,
	ItemContent,
	ItemDescription,
	ItemMedia,
	ItemTitle,
} from '@nerdfish/react/item'
import { BadgeCheckIcon, ChevronRightIcon } from 'lucide-react'

export default function ItemSizesExample() {
	return (
		<div className="gap-casual flex w-full flex-col">
			<Item variant="outline">
				<ItemContent>
					<ItemTitle>Basic Item</ItemTitle>
					<ItemDescription>
						A simple item with title and description.
					</ItemDescription>
				</ItemContent>
				<ItemActions>
					<Button variant="outline" size="sm">
						Action
					</Button>
				</ItemActions>
			</Item>
			<Item variant="outline" size="sm" render={<a href="#" />}>
				<ItemMedia>
					<BadgeCheckIcon className="size-5" />
				</ItemMedia>
				<ItemContent>
					<ItemTitle>Your profile has been verified.</ItemTitle>
				</ItemContent>
				<ItemActions>
					<ChevronRightIcon className="size-4" />
				</ItemActions>
			</Item>
		</div>
	)
}

Icon

'use client'

import { Button } from '@nerdfish/react/button'
import {
	Item,
	ItemActions,
	ItemContent,
	ItemDescription,
	ItemMedia,
	ItemTitle,
} from '@nerdfish/react/item'
import { ShieldAlertIcon } from 'lucide-react'

export default function ItemIconExample() {
	return (
		<div className="flex w-full flex-col gap-6">
			<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="outline">
						Review
					</Button>
				</ItemActions>
			</Item>
		</div>
	)
}

Avatar

'use client'

import { Avatar, AvatarFallback, AvatarImage } from '@nerdfish/react/avatar'
import { Button } from '@nerdfish/react/button'
import {
	Item,
	ItemActions,
	ItemContent,
	ItemDescription,
	ItemMedia,
	ItemTitle,
} from '@nerdfish/react/item'
import { PlusIcon } from 'lucide-react'

export default function ItemAvatarExample() {
	return (
		<div className="gap-casual flex w-full flex-col">
			<Item variant="outline">
				<ItemMedia>
					<Avatar className="size-10">
						<AvatarImage src="https://avatars.githubusercontent.com/u/56068461?v=4" />
						<AvatarFallback>ER</AvatarFallback>
					</Avatar>
				</ItemMedia>
				<ItemContent>
					<ItemTitle>Evil Rabbit</ItemTitle>
					<ItemDescription>Last seen 5 months ago</ItemDescription>
				</ItemContent>
				<ItemActions>
					<Button
						icon
						size="sm"
						variant="outline"
						className="rounded-full"
						aria-label="Invite"
					>
						<PlusIcon />
					</Button>
				</ItemActions>
			</Item>
			<Item variant="outline">
				<ItemMedia>
					<div className="*:data-[slot=avatar]:ring-background flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:grayscale">
						<Avatar>
							<AvatarImage
								src="https://avatars.githubusercontent.com/u/56068461?v=4"
								alt="@nerdfish"
							/>
							<AvatarFallback>CN</AvatarFallback>
						</Avatar>
						<Avatar>
							<AvatarImage
								src="https://avatars.githubusercontent.com/u/56068461?v=4"
								alt="@nerdfish"
							/>
							<AvatarFallback>LR</AvatarFallback>
						</Avatar>
						<Avatar>
							<AvatarImage
								src="https://avatars.githubusercontent.com/u/56068461?v=4"
								alt="@nerdfish"
							/>
							<AvatarFallback>ER</AvatarFallback>
						</Avatar>
					</div>
				</ItemMedia>
				<ItemContent>
					<ItemTitle>No Team Members</ItemTitle>
					<ItemDescription>
						Invite your team to collaborate on this project.
					</ItemDescription>
				</ItemContent>
				<ItemActions>
					<Button size="sm" variant="outline">
						Invite
					</Button>
				</ItemActions>
			</Item>
		</div>
	)
}

Image

'use client'
import {
	Item,
	ItemContent,
	ItemDescription,
	ItemGroup,
	ItemMedia,
	ItemTitle,
} from '@nerdfish/react/item'

const music = [
	{
		title: 'Midnight City Lights',
		artist: 'Neon Dreams',
		album: 'Electric Nights',
		duration: '3:45',
	},
	{
		title: 'Coffee Shop Conversations',
		artist: 'The Morning Brew',
		album: 'Urban Stories',
		duration: '4:05',
	},
	{
		title: 'Digital Rain',
		artist: 'Cyber Symphony',
		album: 'Binary Beats',
		duration: '3:30',
	},
]

export default function ItemImageExample() {
	return (
		<div className="flex w-full flex-col gap-6">
			<ItemGroup className="gap-4">
				{music.map((song) => (
					<Item
						key={song.title}
						variant="outline"
						render={<a href="#" />}
						role="listitem"
					>
						<ItemMedia variant="image">
							<img
								src={`https://avatar.vercel.sh/${song.title}`}
								alt={song.title}
								width={32}
								height={32}
								className="object-cover grayscale"
							/>
						</ItemMedia>
						<ItemContent>
							<ItemTitle className="line-clamp-1">
								{song.title} -{' '}
								<span className="text-muted-foreground">{song.album}</span>
							</ItemTitle>
							<ItemDescription>{song.artist}</ItemDescription>
						</ItemContent>
						<ItemContent className="flex-none text-center">
							<ItemDescription>{song.duration}</ItemDescription>
						</ItemContent>
					</Item>
				))}
			</ItemGroup>
		</div>
	)
}

Group

'use client'

import { Avatar, AvatarFallback, AvatarImage } from '@nerdfish/react/avatar'
import { Button } from '@nerdfish/react/button'
import {
	Item,
	ItemActions,
	ItemContent,
	ItemDescription,
	ItemGroup,
	ItemMedia,
	ItemSeparator,
	ItemTitle,
} from '@nerdfish/react/item'
import { PlusIcon } from 'lucide-react'
import * as React from 'react'

const people = [
	{
		username: 'nerdfish',
		avatar: 'https://avatars.githubusercontent.com/u/56068461?v=4',
		email: 'test@test.com',
	},
	{
		username: 'nerdfish1',
		avatar: 'https://avatars.githubusercontent.com/u/56068461?v=4',
		email: 'test@test.com',
	},
	{
		username: 'nerdfish2',
		avatar: 'https://avatars.githubusercontent.com/u/56068461?v=4',
		email: 'test@test.com',
	},
]

export default function ItemGroupExample() {
	return (
		<div className="gap-casual flex w-full flex-col">
			<ItemGroup>
				{people.map((person, index) => (
					<React.Fragment key={person.username}>
						<Item>
							<ItemMedia>
								<Avatar>
									<AvatarImage src={person.avatar} className="grayscale" />
									<AvatarFallback>{person.username.charAt(0)}</AvatarFallback>
								</Avatar>
							</ItemMedia>
							<ItemContent className="gap-bff">
								<ItemTitle>{person.username}</ItemTitle>
								<ItemDescription>{person.email}</ItemDescription>
							</ItemContent>
							<ItemActions>
								<Button variant="ghost" icon className="rounded-full">
									<PlusIcon />
								</Button>
							</ItemActions>
						</Item>
						{index !== people.length - 1 ? <ItemSeparator /> : null}
					</React.Fragment>
				))}
			</ItemGroup>
		</div>
	)
}