Description list
Terms and their values as a list, stacked, in aligned columns or along a row.
On this page
- Name
- Althea
- State
- Underway
- MMSI
- 244 630 123From the ship station license; call sign PBAQ7.
- Flag
- Netherlands, home port Den Helder
- Length overall
- 14.2 m; beam 4.3 m; draft 2.1 m
- Insurance
- Pantaenius Yacht Insurance, policy 2026-NL-0441872, cover for European waters to 30 June 2027
Code
import { Badge } from "@bosunkit/components/badge";
import { DescriptionList, type DescriptionListItem } from "@bosunkit/components/description-list";
import { Anchor, Flag, Radio, Ruler, Ship, ShieldCheck } from "lucide-react";
import type { ReactElement } from "react";
export const description: string =
"SV Althea's particulars in aligned columns: an icon before each term, a badge for her state, a hint under the " +
"MMSI, and the insurer's long policy name cut to one line with the whole name on hover or focus.";
const PARTICULARS: readonly DescriptionListItem[] = [
{ term: "Name", value: "Althea", icon: <Ship /> },
{ term: "State", value: <Badge variant="green">Underway</Badge>, icon: <Anchor /> },
{
term: "MMSI",
value: "244 630 123",
icon: <Radio />,
hint: "From the ship station license; call sign PBAQ7.",
},
{ term: "Flag", value: "Netherlands, home port Den Helder", icon: <Flag /> },
{ term: "Length overall", value: "14.2 m; beam 4.3 m; draft 2.1 m", icon: <Ruler /> },
{
term: "Insurance",
value: "Pantaenius Yacht Insurance, policy 2026-NL-0441872, cover for European waters to 30 June 2027",
icon: <ShieldCheck />,
},
];
export default function Showcase(): ReactElement {
return (
<div style={{ width: "100%", maxWidth: 480 }}>
<DescriptionList items={PARTICULARS} truncate />
</div>
);
}
A description list shows terms and their values: a vessel's particulars, a leg's figures, a service record. It is a
<dl>, each pair a <dt> and a <dd>, so a screen reader reads each value with its term. Terms are small mono
capitals in the dim text color and values use tabular figures. A value is text or a node, such as a badge or a link;
each pair can take an icon before its term and a hint under its value. A live value from an instrument is a
reading, which shows its source, age and integrity; a description list is for text.
Examples
Columns
columns, the default, puts the terms in a column as wide as the longest term, and every value starts at the same
edge. On a phone, a screen up to the 40em breakpoint (640 px at 16 px), the columns stack, each term over its value,
so a long value takes the screen's width rather than what the longest term leaves it.
- From
- Brest
- To
- A Coruña
- Distance
- 412 NM
- Departure
- 06:00 UTC, 14 October
Code
import { DescriptionList, type DescriptionListItem } from "@bosunkit/components/description-list";
import type { ReactElement } from "react";
export const description: string = "The terms in a column as wide as the longest, every value starting at one edge.";
const LEG: readonly DescriptionListItem[] = [
{ term: "From", value: "Brest" },
{ term: "To", value: "A Coruña" },
{ term: "Distance", value: "412 NM" },
{ term: "Departure", value: "06:00 UTC, 14 October" },
];
export default function Columns(): ReactElement {
return <DescriptionList items={LEG} />;
}
Stacked
stacked puts each term over its value, for a narrow panel or values that run long.
- Last service
- Palma, 2 March 2026, 1 214 engine hours
- Next service
- At 1 714 engine hours, or by 2 March 2027
- Workshop
- Varadero Palma, Moll Vell
Code
import { DescriptionList, type DescriptionListItem } from "@bosunkit/components/description-list";
import type { ReactElement } from "react";
export const description: string = "Each term over its value, for a narrow panel or values that run long.";
const SERVICE: readonly DescriptionListItem[] = [
{ term: "Last service", value: "Palma, 2 March 2026, 1 214 engine hours" },
{ term: "Next service", value: "At 1 714 engine hours, or by 2 March 2027" },
{ term: "Workshop", value: "Varadero Palma, Moll Vell" },
];
export default function Stacked(): ReactElement {
return (
<div style={{ width: "100%", maxWidth: 320 }}>
<DescriptionList items={SERVICE} layout="stacked" />
</div>
);
}
Inline
inline runs the pairs along a row and wraps them where it ends, for a short summary under a title.
- Crew
- 4
- Watch
- Marta, to 16:00 UTC
- Logged
- 98 NM
- Engine
- 1 412 hr
Code
import { DescriptionList, type DescriptionListItem } from "@bosunkit/components/description-list";
import type { ReactElement } from "react";
export const description: string = "The pairs along a row, wrapping where it ends, for a summary under a title.";
const SUMMARY: readonly DescriptionListItem[] = [
{ term: "Crew", value: "4" },
{ term: "Watch", value: "Marta, to 16:00 UTC" },
{ term: "Logged", value: "98 NM" },
{ term: "Engine", value: "1 412 hr" },
];
export default function Inline(): ReactElement {
return <DescriptionList items={SUMMARY} layout="inline" />;
}
Icons and hints
An icon before a term is decorative and hidden from assistive technology. A hint sits under the value in the same
<dd>, so it is read with the value.
- Diesel
- 212 L of 400 LSounded by hand at 08:00 UTC.
- Water
- 365 L of 600 LTanks 2 and 3, from the tank senders.
Code
import { DescriptionList, type DescriptionListItem } from "@bosunkit/components/description-list";
import { Droplets, Fuel } from "lucide-react";
import type { ReactElement } from "react";
export const description: string =
"An icon before each term, hidden from assistive technology, and a hint under a value saying where it comes from.";
const TANKS: readonly DescriptionListItem[] = [
{ term: "Diesel", value: "212 L of 400 L", icon: <Fuel />, hint: "Sounded by hand at 08:00 UTC." },
{ term: "Water", value: "365 L of 600 L", icon: <Droplets />, hint: "Tanks 2 and 3, from the tank senders." },
];
export default function IconsAndHints(): ReactElement {
return <DescriptionList items={TANKS} />;
}
Values that are nodes
A value can be a badge, a link or any other node; it is drawn as it is.
- Registration
- Valid until March 2029
- Liferaft
- Service overdue by 12 days
- Survey
- Survey report, May 2025
Code
import { Badge } from "@bosunkit/components/badge";
import { DescriptionList, type DescriptionListItem } from "@bosunkit/components/description-list";
import type { ReactElement } from "react";
export const description: string = "Values that are nodes: a badge for a state and a link to a record.";
const DOCUMENTS: readonly DescriptionListItem[] = [
{ term: "Registration", value: <Badge variant="green">Valid until March 2029</Badge> },
{ term: "Liferaft", value: <Badge variant="amber">Service overdue by 12 days</Badge> },
{ term: "Survey", value: <a href="#survey-2025">Survey report, May 2025</a> },
];
export default function NodeValues(): ReactElement {
return <DescriptionList items={DOCUMENTS} />;
}
Truncated
truncate keeps each text value to one line, cut with an ellipsis where it does not fit. A value that is cut takes
focus and shows its whole text in a tooltip on hover or focus; a value that fits stays
plain text. Values that are nodes are not cut. Nothing the crew need to act safely belongs in a cut value, since its
end shows only on hover or focus.
- Anchorage
- Baie de Morgat, off the lifeboat slip, 9 m of water over sand and mud
- Holding
- Good
- Shelter
- From west through north to east; open to the south and a swell round Cap de la Chèvre
Code
import { DescriptionList, type DescriptionListItem } from "@bosunkit/components/description-list";
import type { ReactElement } from "react";
export const description: string =
"Long text values cut to one line; a cut value takes focus and shows its whole text in a tooltip.";
const ANCHORAGE: readonly DescriptionListItem[] = [
{ term: "Anchorage", value: "Baie de Morgat, off the lifeboat slip, 9 m of water over sand and mud" },
{ term: "Holding", value: "Good" },
{ term: "Shelter", value: "From west through north to east; open to the south and a swell round Cap de la Chèvre" },
];
export default function Truncate(): ReactElement {
return (
<div style={{ width: "100%", maxWidth: 360 }}>
<DescriptionList items={ANCHORAGE} truncate />
</div>
);
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| itemsrequired | readonly DescriptionListItem[] | – | The pairs, in order. |
| layout | DescriptionListLayout | undefined | "columns" | How the pairs are laid out: columns (the default) puts the terms in a column whose width is the longest term,
each value beside its term, and stacks them on a screen (bk-screen) narrower than 700 px; stacked puts each
term over its value; inline runs the pairs along a row and wraps them. |
| truncate | boolean | undefined | false | Keeps each text value to one line, cut with an ellipsis where it does not fit. A value that is cut can take focus and shows its whole text in a tooltip on hover or focus. Values that are nodes are drawn as they are. |
| className | string | undefined | – | Classes added to the list. |
| testId | string | undefined | – | Becomes data-testid on the list; each pair's row is ${testId}--row. |
| ref | Ref<HTMLDListElement> | undefined | – | The <dl> element. |
- Distance
- 4.8 NM
- ETA Audierne
- 10:34 UTC
- Distance
- 4.8
- ETA Audierne
- 10:34
Related
- Reading: a live value with its source, age and integrity.
- Card: the surface a list of particulars usually sits on.
- Section heading: the heading over a group of pairs.
- Tooltip: the tooltip a cut value opens.