Description List
A semantic key/value detail view for records: profiles, invoices, settings read-outs. It renders a real dl/dt/dd tree, splits term and value at sm, and any value cell composes Koala parts like Badge or Avatar.
Installation#
Usage#
import {
DescriptionList,
DescriptionListItem,
DescriptionTerm,
DescriptionDetails,
} from "@/components/ui/description-list"
export function Example() {
return (
<DescriptionList>
<DescriptionListItem>
<DescriptionTerm>Email</DescriptionTerm>
<DescriptionDetails>jordi@koalaui.com</DescriptionDetails>
</DescriptionListItem>
</DescriptionList>
)
}Layout#
row (default) places the term in a fixed-width column with the value beside it, splitting at the sm breakpoint and stacking on mobile. stack keeps the term above the value at every width, better for narrow surfaces and long values. auto and inline follow below. A term that leads with an icon keeps the value on its text's baseline, not the icon's edge.
Values with pictures#
A value can lead with an Avatar, a Flag, a logo or icon, a Badge or a Select, and the row still reads on the text: the name sits on the term's baseline and the picture is centred on that line, 8px from the text after it. Put them straight in DescriptionDetails with no flex or alignment classes: a flex value takes its baseline from its first item, so a leading picture would hand the row its bottom edge and drop the text below the term.
Auto layout#
layout="auto" splits by the list's own width instead of the viewport's. The term asks for --dl-term (12rem) and the value for --dl-value (10rem); when both fit on one line they sit side by side, and when they don't, the value wraps under its term. So a narrow card on a wide screen stacks, a phone drawer with a short term keeps its rows, and the switch point moves with the term column you set. The same list is shown below in a 20rem and a 28rem column.
Inline#
layout="inline" flows the pairs along a line, each term straight before its value, and wraps when the line runs out: a strip of facts under a heading or inside a row. The pairs carry no row padding and no rule; the gaps between them do the separating.
Divided#
Set divided for a hairline rule between rows. Turns a loose list into a scannable, table-like read.
Density#
Density tunes the per-row vertical padding. compact (the default) suits dashboards; comfortable gives a roomier marketing read. It also honors a surrounding DensityProvider.
Custom term width#
In row layout the term column width is the CSS variable --dl-term (default 12rem). Override it per instance via an inline style or class, no recipe surgery needed.
API reference#
DescriptionList
The root <dl>. Forwards all native <dl> props.
layout:"row"(default, splits at thesmviewport) |"stack"|"auto"(splits by the list's own width) |"inline"(pairs flow along a line).divided:boolean; hairline rule between rows.density:"compact"(default) |"comfortable"; honorsDensityProvider.asChild:boolean; render via Radix Slot.--dl-term(CSS var): term column width inrowandautolayouts (default12rem).--dl-value(CSS var): inautolayout, the least room a value needs beside its term before it wraps under it (default10rem).
DescriptionListItem
Groups one term/value pair (a <div> inside the list). Accepts asChild and all native div props.
DescriptionTerm
The label (<dt>). Renders a leading Phosphor icon when given one. Forwards native <dt> props.
DescriptionDetails
The value (<dd>). Holds plain text or composed parts (Badge, Avatar, links). Forwards native <dd> props.