Dots

Key Value

Label and value pairs for details and summaries, such as fees, transfer review and receipts.

You send
$250.00
Fee
$1.500.6% of the amount
Exchange rate
1 USD = 0.92 EUR
Arrives
Today, in a few minutes
Maya gets
€228.62
import {
  KeyValueLabel,
  KeyValueList,

KeyValueList shows label and value pairs: the fee and rate on a transfer review, the lines of a receipt, the details of a transaction or account. It renders a description list (dl), and rows are separated by spacing only. Pick it over Table when each row describes one thing with one value and nothing needs sorting or columns. Pick it over Item when the content is read, not tapped.

Installation

pnpm dlx shadcn@latest add @dots/key-value

Usage

import {
  KeyValueLabel,
  KeyValueList,
  KeyValueNote,
  KeyValueRow,
  KeyValueValue,
} from "@/components/ui/key-value"
<KeyValueList variant="inline">
  <KeyValueRow>
    <KeyValueLabel>Fee</KeyValueLabel>
    <KeyValueValue>
      $1.50
      <KeyValueNote>0.6% of the amount</KeyValueNote>
    </KeyValueValue>
  </KeyValueRow>
  <KeyValueRow emphasis>
    <KeyValueLabel>Total</KeyValueLabel>
    <KeyValueValue>$251.50</KeyValueValue>
  </KeyValueRow>
</KeyValueList>

Composition

Use the following composition to build a key value list:

KeyValueList
└── KeyValueRow
    ├── KeyValueLabel
    │   └── KeyValueNote
    └── KeyValueValue
        └── KeyValueNote

A row holds exactly one KeyValueLabel and one KeyValueValue. Put KeyValueNote inside one of them, never directly in the row.

Features

  • Stacked rows for narrow places and long values, or inline rows with the label at the start and the value at the end
  • An emphasized row for the line that sums up the rest, such as "Total"
  • A quiet note line under a label or a value
  • Mono values for IDs, account numbers and addresses that people copy or compare
  • Tabular digits; long values wrap and are never cut
  • A compact size for dense summaries and items
  • An optional rounded panel: card on a page, secondary inside a card or sheet
  • Works with MoneyAmount and CopyField in values

Stacked

The default variant stacks each label over its value. Use it in narrow places and for long values, such as bank details and addresses.

Account holder
Jordan Lee
Routing number
021000021
Bank addressFor transfers from outside the region
14 Harbour Lane, Floor 3, Northfield district, Riverton 40211
import {
  KeyValueLabel,
  KeyValueList,

Inline

Set variant="inline" to put the label at the start and the value at the end of one line. The label takes at most half the row; long values wrap and stay end-aligned.

Merchant
Coffee Point
Date
Nov 11, 2026 at 8:12 AM
Note
Breakfast with the team before the quarterly planning session
Amount
$14.00
import {
  KeyValueLabel,
  KeyValueList,

Emphasis

Set emphasis on the row that sums up the rest, such as "Total" or "They get". It sets weight 600 on the label and the value. Use it once per list, on the last row.

Subtotal
$12.40
Tip
$1.60
Total
$14.00
import {
  KeyValueLabel,
  KeyValueList,

Surface

By default the list has spacing only, for a container that already has padding. Set surface="card" to give it its own rounded panel on a page, or surface="secondary" inside a card or a sheet.

Card limits

Daily spending
$2,000
ATM withdrawals
$500 a day
Online payments
On
import { Card, CardContent } from "@/components/ui/card"
import {
  KeyValueLabel,

Compact

Set size="sm" for a dense summary, such as a few terms inside an item.

Savings plan
Rate
4.1% a year
Interest
Paid monthly
Earned so far
+$38.27
import {
  Item,
  ItemContent,

Mono and copy

Set mono on a value for strings people copy or compare, such as a transaction ID. It uses the mono font and breaks at any character. To let people copy the value, put a CopyField inside; it drops its own visible label, since the row label already names it.

Account number
Account number4839 2017 5562
Transaction ID
TX-AYD1EN1JCP
"use client"

import { CopyField } from "@/components/ui/copy-field"

Accessibility

KeyValueList renders a native dl, with dt for each label and dd for each value, so screen readers announce the pairs as a description list. There is nothing interactive in the list itself.

  • Keep each row to one label and one value, so the pairs stay matched.
  • Write labels as words. Do not rely on position or weight to say what a value is.
  • Give the CopyField inside a value the same label as the row, so its button is named.

API Reference

KeyValueList

The list. Renders a dl and takes its props.

PropTypeDefaultDescription
variant"default" | "inline""default"Stack each label over its value, or put both on one line.
size"default" | "sm""default"sm is the compact density.
surface"none" | "card" | "secondary""none"Gives the list its own rounded panel with padded rows.
classNamestring-Additional classes to apply to the list.

KeyValueRow

One pair. Renders a div and takes its props.

PropTypeDefaultDescription
emphasisbooleanfalseWeight 600 on the label and value, for a total.
classNamestring-Additional classes to apply to the row.

KeyValueLabel

What the value is. Renders a dt and takes its props. Never truncated.

PropTypeDefaultDescription
classNamestring-Additional classes to apply to the label.

KeyValueValue

The value: text, a MoneyAmount with size="inline", or a CopyField. Renders a dd and takes its props.

PropTypeDefaultDescription
monobooleanfalseMono font for IDs and account numbers. Breaks at any character.
classNamestring-Additional classes to apply to the value.

KeyValueNote

A quiet secondary line inside a label or a value. Renders a span and takes its props. In a compact stacked list, put it under the value.

PropTypeDefaultDescription
classNamestring-Additional classes to apply to the note.