Skip to content

KeyValue

Terminal window
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/key-value.json
See it liveA panel of properties, and the same facts stacked for a card.→

The 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

PropTypeDefault
layoutrows | stacked'rows'

And every prop of React's HTMLAttributes<HTMLDListElement>, passed on.

KeyValueRow

One pair.

PropTypeDefault
labelrequiredReactNodeThe name of the fact.
childrenrequiredReactNodeWhat it is. A node rather than a string: half the values in a real panel are a Badge, a RelativeTime or a link.
classNamestringDresses 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.

  1. v0.41.0
    • docs read every props table from the component's types ee3b159
  2. v0.22.0
    • feat a long list, a deep one, and the facts beside them 4cbd42e