Zum Hauptinhalt springen

KeyValue

Every example on this page is live, drawn by the library's Storybook, where you can also change its props and see the result.

Displays a list of key-value pairs in vertical (definition list) or horizontal (side-by-side) layout.

Import​

import { KeyValue } from "~lib/data-display/key-value";

Props​

NameTypeRequiredDefaultDescription
dataKeyValueRow[] | KeyValueSection[]YesN/AThe rows, or sections of rows each under a heading
orientation"vertical" | "horizontal"No"vertical"Layout direction
dividerbooleanNotrueShow dividers between rows, and between columns with columns
size"xs" | "sm"No"sm"Text size and row spacing
truncatebooleanNofalseKeep every key and value to one line ending in "…", the key giving way first
columnsnumberNoOne columnSplit the rows across up to this many columns, down the first before the next
minColumnWidthnumberNo160Narrowest a column gets, in pixels, before the list drops to fewer columns

A KeyValueRow is one fact:

NameTypeRequiredDescription
keystringYesThe fact's name
valueReactNodeNoThe fact's value. Left out or empty, the key has the row to itself
descriptionstringNoA second line under the key at the xs size, past any leading node
leadingReactNodeNoSits before the key, centered on its line
trailingReactNodeNoSits beside the value
donebooleanNoStrikes the key, the description and the value's text through, for a finished task

A KeyValueSection is { heading: string; rows: KeyValueRow[] }: the heading is set as a bold xs line above its rows.

Examples​

Vertical​

Vertical in Storybook öffnen

Horizontal​

Horizontal in Storybook öffnen

No Divider​

No Divider in Storybook öffnen

Compact​

Use size="xs" in narrow columns: smaller text and tighter rows fit more facts in the same height.

Compact in Storybook öffnen

With Trailing Content​

Give a row trailing content, such as a Badge or a Sparkline, to show it beside the value instead of writing it into the value's text.

<KeyValue
orientation="horizontal"
data={[{ key: "AAPL", value: "$517.53", trailing: <Badge>▲ 0.92%</Badge> }]}
/>
With Trailing in Storybook öffnen

With Leading Content​

Give a row leading content, such as a Badge for a train's line, to show it before the key, centered on the key's line, the way a departure board reads.

<KeyValue
orientation="horizontal"
data={[{ key: "Howard", value: "7:53 pm", leading: <Badge>Red</Badge> }]}
/>
With Leading in Storybook öffnen

Vertical Rows With Leading and Trailing Content​

A vertical row draws leading before the key, centered on its line, in a column of its own, so the value lines up under the key's text; trailing sits beside the value. A to-do list down a slim column keeps the same row shape as one across a band: the tick box before the task, the overdue badge beside its date.

<KeyValue
size="xs"
truncate
data={tasks.map((task) => ({
key: task.name,
value: task.due,
leading: <Icon name={task.done ? "square-check" : "square"} size={18} />,
trailing: task.overdue ? <Badge size="xs">Overdue</Badge> : undefined,
done: task.done,
}))}
/>
Vertical With Leading And Trailing in Storybook öffnen

With a Description​

Give a row a description to set a smaller second line under its key, at the xs size whatever the list's size, such as the stop a departure leaves from. It starts past any leading node, so it lines up with the key's text, and the value stays on the key's line. With truncate it is kept to one line ending in "…" like the key. The description is part of its row, so every row still keeps whole in columns and the columns balance to one height; a done row strikes its description through with the rest of its text.

<KeyValue
orientation="horizontal"
size="xs"
truncate
data={departures.map((departure) => ({
key: departure.destination,
description: `from ${departure.stop}`,
value: departure.due,
leading: <Badge size="xs">{departure.line}</Badge>,
}))}
/>
With Description in Storybook öffnen
Descriptions In Columns in Storybook öffnen

Done​

Set done on a row to strike its key, its description and its value's text through, in full ink, the way a finished task or a bought item is crossed off. Its leading and trailing content, and a value that is a node of its own such as a Badge, are left as they are.

<KeyValue
orientation="horizontal"
data={[
{ key: "Oat milk", value: "2 L", done: true },
{ key: "Eggs", value: "12" },
]}
/>
Done in Storybook öffnen

No Value​

Leave a row's value out, or empty, for a fact that is a name alone, such as an ingredient with no amount: the key has the whole row to itself rather than stopping short of a blank column.

<KeyValue
orientation="horizontal"
data={[
{ key: "Plain flour", value: "200 g" },
{ key: "A pinch of sea salt, or to taste" },
]}
/>
No Value in Storybook öffnen

Truncated​

Keys and values wrap by default, so a long key such as an ingredient reads in full. Set truncate to keep every key and value to one line ending in "…" instead, so each row keeps one height and a box that counts its rows never meets a row that grew. The key gives way first: in a horizontal row the value is cut short only once the key has no room left, and leading and trailing content is never cut.

<KeyValue
orientation="horizontal"
truncate
data={[
{
key: "Harlem/Lake via the Loop",
value: "8:04 pm",
leading: <Badge>Green</Badge>,
},
]}
/>
Truncated in Storybook öffnen

Columns​

Set columns to split a long list into columns side by side, such as a line-status board in a wide, short box. The rows run down the first column and then the next, every column is the same width, and a rule sits between them (divider={false} leaves only a gap). Use it with truncate, and give every row the same kind of content, such as a badge in each, so the rows are one height and line up across the columns.

<KeyValue
orientation="horizontal"
size="xs"
truncate
columns={3}
data={lines.map((line) => ({
key: line.name,
value: <Badge variant="outline">{line.status}</Badge>,
}))}
/>
Columns in Storybook öffnen

A box too narrow for every column at minColumnWidth gets fewer columns. The browser works this out from the box, so a saved preview shown in a narrower box drops a column the same way.

Fewer Columns In A Narrow Box in Storybook öffnen

The columns are balanced to one height, so in a Brim a list taller than its box is cut across every column at the same line, under the fade.

<Brim>
<KeyValue
orientation="horizontal"
size="xs"
truncate
columns={3}
data={rows}
/>
</Brim>
Columns In A Brim in Storybook öffnen

Sections​

Pass data as sections, each a heading over its rows, to group a list the way it is read, such as a statement's payments under the day they were made. Each heading is a bold xs line across the list with a rule above it and none between it and its own rows, so the rules keep one rhythm from the first row to the last.

<KeyValue
orientation="horizontal"
size="xs"
truncate
data={[
{
heading: "Today",
rows: [
{ key: "Tesco Express", value: "−£12.40" },
{ key: "Pret A Manger", value: "−£5.10" },
],
},
{ heading: "Yesterday", rows: [{ key: "Spotify", value: "−£11.99" }] },
]}
/>
Sections in Storybook öffnen

With columns the sections flow down one column and into the next the way rows do, balanced to one height, and a heading never stays at the foot of a column without its first row. In a Brim the list is cut across every column at the same line.

Sections In Columns in Storybook öffnen

See Also​

  • Table - Full table display
  • Stat - Single metric
  • List - Simple lists