Elements
List item
View in FigmaList leaf that renders either a navigation row or a controlled filter tag.
Install
npx shadcn@latest add @alix/listItemPreview
Usage
<ListItem variant="text" text="Energy transition" href="/services/energy-transition" />
<ListItem
variant="tag"
text="Shipping"
value="shipping"
selected={selected.includes("shipping")}
onSelect={toggle}
/>Examples
01
Small navigation rows
Use the small text size for dense secondary navigation while preserving the full-row hit target.
<ul className="m-0 w-full max-w-sm list-none border-l border-border p-0 pl-2">
<ListItem
variant="text"
text="Turnaround and restructuring"
href="/services/turnaround"
size="small"
current
/>
<ListItem
variant="text"
text="Transactions and investor services"
href="/services/transactions"
size="small"
/>
<ListItem
variant="text"
text="Performance improvement"
href="/services/performance"
size="small"
/>
</ul>02
Controlled filter tags
Tag items emit their stable value and let the parent own selection state.
Insight filters2 active
const [selected, setSelected] = useState(["restructuring", "transactions"]);
const toggle = (value: string) =>
setSelected((current) =>
current.includes(value)
? current.filter((item) => item !== value)
: [...current, value],
);
return (
<div className="w-full max-w-md space-y-3">
<div className="flex items-center justify-between gap-4">
<span className="text-sm font-medium text-foreground">
Insight filters
</span>
<Badge variant="primary">{selected.length} active</Badge>
</div>
<ul className="m-0 flex list-none flex-wrap gap-2 p-0">
<ListItem
variant="tag"
text="Restructuring"
value="restructuring"
selected={selected.includes("restructuring")}
onSelect={toggle}
/>
<ListItem
variant="tag"
text="Performance"
value="performance"
selected={selected.includes("performance")}
onSelect={toggle}
/>
<ListItem
variant="tag"
text="Transactions"
value="transactions"
selected={selected.includes("transactions")}
onSelect={toggle}
/>
</ul>
</div>
);03
List parent recipe
Let List render repeated items from data when the row structure should stay uniform.
<div className="w-full max-w-sm">
<List
variant="list"
title="Capabilities"
size="small"
items={[
{
text: "Turnaround and restructuring",
href: "/services/turnaround",
current: true,
},
{
text: "Performance improvement",
href: "/services/performance",
},
{
text: "Investigations and disputes",
href: "/services/investigations",
},
]}
/>
</div>When to use it
Use it for
- Single navigation rows inside a locally owned `<ul>` when the parent needs exact control.
- Controlled filter chips where the selected values live beside the result set.
- Current-page state for section navigation that should set `aria-current`.
Reach for something else
- CMS-fed lists of repeated rows — use List instead.
- Static labels that do not toggle filtering — use Badge instead.
- Command menus or overflow actions — use Menu instead.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "text" | "tag" | — | Discriminates the item contract: text renders a navigation link; tag renders a filter button. |
| size | "default" | "small" | "default" | Text-item row height and padding; not valid on tag items. |
| current | boolean | false | Text-item current-page state, applied as aria-current. |
| selected / onSelect | boolean / (value: string) => void | — | Controlled tag state; ListItem emits its value and the parent owns selection. |