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>
)
}