Item
A list item with leading media, content and trailing actions. Stack them with Item.Group or drop them into a card to compose richer layouts.
Installation
pnpm dlx @elyri/cli@latest add itemExamples
Inbox card
An Item.Group inside a Card, composed from avatars, titles, snippets and status tags.
Team inbox
3 conversations need a reply.
Ada Lovelace
Shipped the analytics dashboard — ready for review.
Alan Turing
Can you look at the auth flow before Friday?
Grace Hopper
Left two comments on the design tokens PR.
import { Avatar } from './components/elyri/Avatar';
import { Button } from './components/elyri/Button';
import { Card } from './components/elyri/Card';
import { Item } from './components/elyri/Item';
import { Tag } from './components/elyri/Tag';
export function Example() {
return (
<Card variant="elevated">
<Card.Header>
<div>
<Card.Title>Team inbox</Card.Title>
<Card.Description>3 conversations need a reply.</Card.Description>
</div>
<Card.Action>
<Tag size="sm" variant="accent">
3 new
</Tag>
</Card.Action>
</Card.Header>
<Card.Content>
<Item.Group>
<Item variant="muted" size="sm">
<Item.Media>
<Avatar name="Ada Lovelace" size="sm" />
</Item.Media>
<Item.Content>
<Item.Title>Ada Lovelace</Item.Title>
<Item.Description>Shipped the analytics dashboard — ready for review.</Item.Description>
</Item.Content>
<Item.Actions>
<Tag size="sm" variant="success">
Done
</Tag>
</Item.Actions>
</Item>
<Item variant="muted" size="sm">
<Item.Media>
<Avatar name="Alan Turing" size="sm" />
</Item.Media>
<Item.Content>
<Item.Title>Alan Turing</Item.Title>
<Item.Description>Can you look at the auth flow before Friday?</Item.Description>
</Item.Content>
<Item.Actions>
<Tag size="sm" variant="warning">
Pending
</Tag>
</Item.Actions>
</Item>
<Item variant="muted" size="sm">
<Item.Media>
<Avatar name="Grace Hopper" size="sm" />
</Item.Media>
<Item.Content>
<Item.Title>Grace Hopper</Item.Title>
<Item.Description>Left two comments on the design tokens PR.</Item.Description>
</Item.Content>
<Item.Actions>
<Tag size="sm">Open</Tag>
</Item.Actions>
</Item>
</Item.Group>
</Card.Content>
<Card.Footer align="between">
<span style={{ fontSize: 12, color: 'var(--elyri-ui-muted)' }}>Updated 2m ago</span>
<Button size="sm" variant="ghost">
Open inbox
</Button>
</Card.Footer>
</Card>
);
}Basic
Icon media, title and description, plus a trailing button — one row per entry.
Design review
Thursday, 14:00 · Figma
import { Button } from './components/elyri/Button';
import { Item } from './components/elyri/Item';
const calendarIcon = (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
<rect x="3" y="5" width="18" height="16" rx="3" />
<path d="M8 3v4M16 3v4M3 10h18" />
</svg>
);
export function Example() {
return (
<Item variant="outline">
<Item.Media variant="icon">{calendarIcon}</Item.Media>
<Item.Content>
<Item.Title>Design review</Item.Title>
<Item.Description>Thursday, 14:00 · Figma</Item.Description>
</Item.Content>
<Item.Actions>
<Button size="sm" variant="ghost">
Join
</Button>
</Item.Actions>
</Item>
);
}Variants
default transparent / outline bordered / muted filled.
default
variant="default"
outline
variant="outline"
muted
variant="muted"
import { Item } from './components/elyri/Item';
const variants = ['default', 'outline', 'muted'] as const;
const sparkIcon = (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
<path d="M12 3l1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9Z" />
</svg>
);
export function Example() {
return (
<div className="demo-ui-grid">
{variants.map((variant) => (
<Item key={variant} variant={variant}>
<Item.Media variant="icon">{sparkIcon}</Item.Media>
<Item.Content>
<Item.Title>{variant}</Item.Title>
<Item.Description>variant="{variant}"</Item.Description>
</Item.Content>
</Item>
))}
</div>
);
}Sizes
sm / md / lg; media sizes line up with Avatar so avatars drop straight in.
Small
Compact rows for dense lists.
Medium
The default row size.
Large
Roomier rows for emphasis.
import { Avatar } from './components/elyri/Avatar';
import { Item } from './components/elyri/Item';
export function Example() {
return (
<>
<Item size="sm" variant="muted">
<Item.Media>
<Avatar name="Ada Lovelace" size="sm" />
</Item.Media>
<Item.Content>
<Item.Title>Small</Item.Title>
<Item.Description>Compact rows for dense lists.</Item.Description>
</Item.Content>
</Item>
<Item size="lg" variant="muted">
<Item.Media>
<Avatar name="Grace Hopper" size="lg" />
</Item.Media>
<Item.Content>
<Item.Title>Large</Item.Title>
<Item.Description>Roomier rows for emphasis.</Item.Description>
</Item.Content>
</Item>
</>
);
}Interactive list
With interactive enabled the row highlights on hover; add tabIndex for keyboard focus — great for clickable settings.
Preferences
Push notifications
Get pinged on new mentions.
Privacy
Manage who can see your activity.
import { Card } from './components/elyri/Card';
import { Item } from './components/elyri/Item';
const bellIcon = (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
<path d="M18 8a6 6 0 1 0-12 0c0 6-2 7-2 7h16s-2-1-2-7Z" />
<path d="M10.5 20a2 2 0 0 0 3 0" />
</svg>
);
export function Example() {
return (
<Card>
<Card.Header>
<Card.Title>Preferences</Card.Title>
</Card.Header>
<Item.Group>
<Item variant="muted" interactive tabIndex={0}>
<Item.Media variant="icon">{bellIcon}</Item.Media>
<Item.Content>
<Item.Title>Push notifications</Item.Title>
<Item.Description>Get pinged on new mentions.</Item.Description>
</Item.Content>
</Item>
</Item.Group>
</Card>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'outline' | 'muted' | 'default' | Visual style |
size | 'sm' | 'md' | 'lg' | 'md' | Padding and font size |
interactive | boolean | false | Interactive: highlight on hover, focus ring on focus |
Item.Group | HTMLAttributes<HTMLDivElement> | — | Group container stacking multiple items vertically |
Item.Media | { variant?: 'default' | 'icon' | 'image' } | — | Leading media area; variant controls its backing |
Item.Content | HTMLAttributes<HTMLDivElement> | — | Content area stacking the title and description |
Item.Title | HTMLAttributes<HTMLHeadingElement> | — | Title |
Item.Description | HTMLAttributes<HTMLParagraphElement> | — | Description, clamped to two lines |
Item.Actions | HTMLAttributes<HTMLDivElement> | — | Trailing actions |
...rest | HTMLAttributes | — | Remaining props are forwarded to the native div |