Key-value facts
The record-header staple: labeled facts (Vendor · Cost center · Terms · Total) as a real description list — not readonly inputs, not hand-rolled markup. One grid, responsive by construction; values are normal content, so badges and dates compose. Not when the values are editable — a description list is a read surface, and styling inputs to look like one hides that they are editable. Use a form, or the seamless inline-edit pattern if the screen is read-mostly.
Facts strip — a record header
- Vendor
- Umbrella Logistics
- Cost center
- CC-4021
- Payment terms
- Net 30
- Total
- $12,400.00
- Requested
- Status
- Approved
View code
<dl class="bo-kv">
<div><dt>Vendor</dt><dd>Umbrella Logistics</dd></div>
<div><dt>Cost center</dt><dd>CC-4021</dd></div>
<div><dt>Payment terms</dt><dd>Net 30</dd></div>
<div><dt>Total</dt><dd class="bo-u-tabular">$12,400.00</dd></div>
<div><dt>Requested</dt><dd><time datetime="2026-08-10">10 Aug 2026</time></dd></div>
<div><dt>Status</dt><dd><span class="bo-badge bo-badge--success">Approved</span></dd></div>
</dl> Columns pack to the space
(auto-fit): four across a detail header, a single stack
at phone width — no breakpoints to manage. Give money and counts
.bo-u-tabular so digits align.
--rows — dense sidebar facts
- Warehouse
- HAM-02
- Bin
- A-14-3
- On hand
- 1,240
- Reserved
- 380
View code
<dl class="bo-kv bo-kv--rows">
<div><dt>Warehouse</dt><dd>HAM-02</dd></div>
<div><dt>Bin</dt><dd>A-14-3</dd></div>
<div><dt>On hand</dt><dd class="bo-u-tabular">1,240</dd></div>
<div><dt>Reserved</dt><dd class="bo-u-tabular">380</dd></div>
</dl> One fact per line with the label column auto-sized and aligned — inventory panels, filter summaries, print footers. Same markup, one modifier.
Why a description list
Display data in a disabled or readonly <input>
tells assistive tech "this is a form control you can't use" — wrong
semantics and heavier chrome for something the user only reads. A
<dl> says exactly what it is: terms and their
values. Screen readers announce the pairing; nothing pretends to be
editable. Use the detail
form when values ARE editable — this component is for facts.
Markup
<!-- A native description list: each fact is a <div>-wrapped dt/dd
pair (valid HTML, and the pair is the grid item). Values are real
content — badges, times, links all compose inside dd. -->
<dl class="bo-kv">
<div><dt>Vendor</dt><dd>Umbrella Logistics</dd></div>
<div><dt>Total</dt><dd class="bo-u-tabular">$12,400.00</dd></div>
</dl>
<!-- Dense sidebar/card variant: one fact per line, aligned columns -->
<dl class="bo-kv bo-kv--rows">
<div><dt>Bin</dt><dd>A-14-3</dd></div>
</dl> Quick reference generated
| Class | Role |
|---|---|
| .bo-kv | block (root) |
| .bo-kv--rows | variant: rows |
API generated from CSS
| Blocks | bo-kv |
|---|---|
| Variants | bo-kv--rows |
| JS required | None — CSS-only. |
- Each pair is a
<div><dt>…</dt><dd>…</dd></div>— the div wrapper is valid HTML inside a dl and is what the grid lays out. - Values are content, not strings: badges,
<time>, links, and avatars compose insidedd. - Numeric facts want
.bo-u-tabularon the dd so digits align across the strip. - For editable values use form fields (detail form pattern) — a fact that is secretly an input misleads assistive tech in both directions.
- Density-aware: values track
--bo-density-font-size; the grid itself needs no density hooks.
Contrast — 9 AA pairs this component uses (generated, CI-gated)
| Text | on | Light | Dark |
|---|---|---|---|
| text-primary | bg-surface | 17.74 | 16.15 |
| text-primary | bg-canvas | 16.98 | 18.08 |
| text-muted | bg-surface | 7.56 | 6.65 |
| text-muted | bg-muted | 6.87 | 5.66 |
| bg-surface | text-primary | 17.74 | 16.15 |
| text-primary | bg-hover | 16.12 | 13.75 |
| text-primary | bg-selected | 17.01 | 11.86 |
| text-primary | bg-surface-raised | 17.74 | 14.51 |
| text-primary | bg-muted | 16.12 | 13.75 |
Maturity generated
- Introduced
- v0.3.0
- CSS floor
- Chrome/Edge 99 · Firefox 97 · Safari 15.4
- Alignment scored
- 2026-08-21
- Assistive-tech evidence
- None recorded
Pin this component's first release with npm i @busy-office/ui@0.3.0.
The floor is derived from this component's stylesheet alone — set by
@layer — so it sits at or below the
whole framework's Chrome/Edge 119 · Firefox 129 · Safari 17.5.
No assistive-technology runtime result is recorded for any component: it needs a human listening to VoiceOver and NVDA on owner hardware; no gate in this repo can simulate announcement behaviour.
What automation covers instead is test:axe across every page at 1440 and 390, and check:forced-colors — see
accessibility.
Design-system alignment generated
100% (15/15) — how closely this component follows the design language. Each rule is scored 0-3 against a checkable citation; rules that don't apply leave the denominator. Scored 2026-08-21.
| Rule | Score | Evidence |
|---|---|---|
| Typography | 3 / 3 | --bo-font-size-xs on dt; the 0.04em letter-spacing is intrinsic, same basis as form and combobox |
| Colour | 3 / 3 | zero raw colour |
| Spacing | 3 / 3 | grid gaps from space tokens; no uncommented dimension literal |
| Interaction | n/a | a static <dl>; values may contain controls but the component ships none |
| Content | 3 / 3 | the opener carries the required wrong-choice clause and links the alternative (94.10) |
| Fit | 3 / 3 | the record-header staple — labeled facts as a real description list, values as content (badges, <time>, links) rather than strings |