KeyValue
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/key-value.jsonThe markup is the whole point. Every product builds this out of two
<div>s in a flex row, and it reads to a screen reader as four unrelated
pieces of text — “Created”, “2 hours ago”, “Owner”, “Ines” — with nothing
saying which value belongs to which name. A <dl> says it for free.
<KeyValue> <KeyValueRow label="Owner">Ines</KeyValueRow> <KeyValueRow label="Words"><NumberFormat value={4120} /></KeyValueRow> <KeyValueRow label="Updated"><RelativeTime value={row.updated} /></KeyValueRow></KeyValue>Two layouts, because the same list sits in two places. rows puts names in
a column of their own with values beside them — for a panel of properties,
where the eye scans the names. stacked puts the name above the value — for a
card, and for a column too narrow to pair without wrapping into a ladder.
They need different markup, which is why the row reads the layout from
context rather than taking a prop of its own. In rows the <dt> and <dd>
go straight into the grid, so every value lines up in one column; wrap each
pair and each pair becomes its own box, with the values landing at a different
place on every line. In stacked each pair must be wrapped, or the column
gap falls between a name and its value as readily as between pairs, and six
facts read as twelve loose lines.
Both are valid: a <dl> allows dt/dd as direct children, and allows one
<div> per pair. It allows nothing else between them — which is why the pair
is a component rather than something the caller assembles.
A value is a node, not a string. Half the values in a real panel are a Badge, a RelativeTime or a link.
Props
Read from the types in ui/key-value.tsx, the file a product copies - so the description of each prop is also what an editor shows over it there.
KeyValue
| Prop | Type | Default | |
|---|---|---|---|
layout | rows | stacked | 'rows' |
And every prop of React's HTMLAttributes<HTMLDListElement>, passed on.
KeyValueRow
One pair.
| Prop | Type | Default | |
|---|---|---|---|
labelrequired | ReactNode | The name of the fact. | |
childrenrequired | ReactNode | What it is. A node rather than a string: half the values in a real panel are a Badge, a RelativeTime or a link. | |
className | string | Dresses the pair as a whole when the layout is stacked, and the term alone in rows. |
Accessibility
The examples on the stand, through axe 4.14.0 in a browser, in both themes, against WCAG 2.2 A and AA and axe's best practices: 6 rules applied and passed, and none failed. The accessibility report has every item.
History
Each release that changed ui/key-value.tsx - the file a product copies - newest first.