Item
PortedA row: media at the start, a title and a description, and actions at the end. Put rows in an ItemGroup, or use one on its own. With render, the whole row is a link or a button.
Ana RuizASIC design engineerInterviewing
import { Avatar } from "@etched/monet/avatar";
import { Pill } from "@etched/monet/pill";
import { Item } from "@etched/monet/item";
export function Preview() {
return (
<div style={{ inlineSize: "20rem" }}>
<Item
variant="outline"
size="sm"
media={<Avatar name="Ana Ruiz" size="sm" alt="" />}
title="Ana Ruiz"
description="ASIC design engineer"
actions={<Pill tone="cyan">Interviewing</Pill>}
/>
</div>
);
}Installation
import { Item, ItemGroup } from "@etched/monet/item";Examples
Media, text and actions
An icon gets a filled box; an avatar shows as it is. The description stops after two lines.
Weekly digestA summary of new referrals, stage changes and interviews, sent every Monday at 09:00 in your time zone.
Kai ItoHiring manager, Physical design
import { BellIcon } from "@phosphor-icons/react";
import { Avatar } from "@etched/monet/avatar";
import { Button } from "@etched/monet/button";
import { Item } from "@etched/monet/item";
const panel = { inlineSize: "100%", maxInlineSize: "30rem" };
export function Anatomy() {
return (
<div style={{ ...panel, display: "grid", gap: "var(--et-space-2)" }}>
<Item
media={<BellIcon />}
title="Weekly digest"
description="A summary of new referrals, stage changes and interviews, sent every Monday at 09:00 in your time zone."
actions={<Button size="sm">Edit</Button>}
/>
<Item
media={<Avatar name="Kai Ito" alt="" />}
title="Kai Ito"
description="Hiring manager, Physical design"
actions={
<Button size="sm" variant="ghost">
Message
</Button>
}
/>
</div>
);
}Outline and sizes
outline gives a row its own edge. sm is denser, with a smaller icon box.
API keyCreated Oct 2 by Sam Lee. Last used today.
Webhook secretCreated Sep 18 by Kai Ito.
import { KeyIcon } from "@phosphor-icons/react";
import { Button } from "@etched/monet/button";
import { Item } from "@etched/monet/item";
const panel = { inlineSize: "100%", maxInlineSize: "30rem" };
export function OutlineAndSizes() {
return (
<div style={{ ...panel, display: "grid", gap: "var(--et-space-2)" }}>
<Item variant="outline" media={<KeyIcon />} title="API key" description="Created Oct 2 by Sam Lee. Last used today." actions={<Button size="sm">Rotate</Button>} />
<Item variant="outline" size="sm" media={<KeyIcon />} title="Webhook secret" description="Created Sep 18 by Kai Ito." actions={<Button size="sm">Rotate</Button>} />
</div>
);
}A group with separators
ItemGroup is a list: screen readers announce it and its count. separators draws a line between rows. The app puts the group in its own panel.
- Ana RuizASIC design engineerInterviewing
- José NúñezFirmware engineerScheduled
- Mira OseiPhysical design leadHired
import { Avatar } from "@etched/monet/avatar";
import { Pill, type PillTone } from "@etched/monet/pill";
import { Item, ItemGroup } from "@etched/monet/item";
const panel = { inlineSize: "100%", maxInlineSize: "30rem" };
const team: [string, string, string, PillTone][] = [
["Ana Ruiz", "ASIC design engineer", "Interviewing", "cyan"],
["José Núñez", "Firmware engineer", "Scheduled", "purple"],
["Mira Osei", "Physical design lead", "Hired", "green"],
];
export function GroupWithSeparators() {
return (
<div className="card" style={panel}>
<ItemGroup separators aria-label="Referrals">
{team.map(([name, role, stage, tone]) => (
<Item key={name} size="sm" media={<Avatar name={name} size="sm" alt="" />} title={name} description={role} actions={<Pill tone={tone}>{stage}</Pill>} />
))}
</ItemGroup>
</div>
);
}A group of links
Without separators, rows have a small gap, for outline rows.
import { BellIcon, CaretRightIcon, KeyIcon } from "@phosphor-icons/react";
import { Item, ItemGroup } from "@etched/monet/item";
const panel = { inlineSize: "100%", maxInlineSize: "30rem" };
export function GroupOfLinks() {
return (
<div style={panel}>
<ItemGroup aria-label="Settings">
<Item variant="outline" size="sm" render={<a href="#item" />} media={<BellIcon />} title="Notifications" actions={<CaretRightIcon />} />
<Item variant="outline" size="sm" render={<a href="#item" />} media={<KeyIcon />} title="API keys" actions={<CaretRightIcon />} />
</ItemGroup>
</div>
);
}Accessibility
- With
render, the row is one link or button:Enterfollows a link row, andEnterorSpacepresses a button row. - A row without
renderis adivwith no role. A link or button row is named by all its text in order: title, description, then actions. ItemGroupis a list (role="list", so Safari keeps it) with one list item per row, so screen readers say how many rows there are.- A link or button row holds no other controls: put a chevron or a badge in
actions. Setaria-labelfor a shorter name.
API reference
ItemGroup
| Prop | Type | Default | Description |
|---|---|---|---|
| separators | boolean | false | A line between rows, with no gap. Without it, rows have a small gap, for outline rows. |
| children * | ReactNode | – | Items. Each goes in its own list item, so put them directly inside, not in a fragment. |
Item
| Prop | Type | Default | Description |
|---|---|---|---|
| title * | ReactNode | – | The first line, such as a name or a setting. It names the row. |
| description | ReactNode | – | The second line, in the subtle ink. Long text stops after two lines. |
| media | ReactNode | – | An icon or an Avatar at the start. An icon gets a filled box. |
| actions | ReactNode | – | Buttons, a badge or a pill at the end. A row that is a link or a button holds no other controls: use a chevron or a badge here, never a button. |
| variant | "plain" | "outline" | "plain" | |
| size | "base" | "sm" | "base" | |
| render | ReactElement<{ className?: string }> | – | Makes the whole row another element with the row's look: a link, render={<a href="/settings/team" />} or a router link, or a button, render={<button type="button" />}. Then the row takes the hover fill and the focus ring. Its accessible name is its text, in order; set aria-label for a shorter one. |