Skip to content
design
Components

Instrument pill group

Instrument pills in an even grid under a label, as many columns as the container fits.

On this page
Anchor watch
  • From anchor31 m
  • Swing radius35 m
  • Depth8.4 m
  • True wind22 kn
  • Barometer1009 hPa
  • Rode out40 m
The anchor watch in six pills under their label, in even columns that wrap as the panel narrows.
Code
import { InstrumentPill } from "@bosunkit/components/instrument-pill";
import { InstrumentPillGroup } from "@bosunkit/components/instrument-pill-group";
import type { ReactElement } from "react";

export const description: string =
  "The anchor watch at anchor in Morgat: six pills in even columns under their label, wrapping to fewer columns as " +
  "the panel narrows; drag its corner to see them wrap.";

export default function Showcase(): ReactElement {
  return (
    <div
      style={{
        width: "100%",
        maxWidth: "40em",
        minWidth: "10em",
        padding: "var(--space-sm)",
        border: "1px solid var(--border)",
        borderRadius: "var(--radius-md)",
        resize: "horizontal",
        overflow: "hidden",
      }}
    >
      <InstrumentPillGroup label="Anchor watch">
        <InstrumentPill label="From anchor" value="31" unit="m" priority="warning" trend="rising" />
        <InstrumentPill label="Swing radius" value="35" unit="m" />
        <InstrumentPill label="Depth" value="8.4" unit="m" trend="steady" />
        <InstrumentPill label="True wind" value="22" unit="kn" trend="rising" />
        <InstrumentPill label="Barometer" value="1009" unit="hPa" trend="falling" />
        <InstrumentPill label="Rode out" value="40" unit="m" />
      </InstrumentPillGroup>
    </div>
  );
}

An instrument pill group lays instrument pills out in an even grid: equal columns at least minPillWidth wide, as many as fit the container, and fewer as it narrows, down to one. It follows the width of the container it sits in, not the window, so the same group reads the same in a phone column, a side panel and a wide dashboard. The group is named by its label and the pills are a list, so a screen reader says what they are and how many there are.

01Even columnsEvery pill in a row is the same width, so the values line up down the columns and the eye finds the same reading in the same place.
02Wraps by its containerThe columns follow the space the group is given, so a pill is never squeezed below its narrowest width.
03Named as a setThe label says what the pills measure together; the pills keep their own labels.

Examples

Column width

minPillWidth sets the narrowest a pill gets, in em; 9em by default, which fits a label and a four-figure value.

Engine, 9em columns
  • RPM1850
  • Coolant82 °C
  • Oil3.9 bar
  • Fuel212 L
Engine, 14em columns
  • RPM1850
  • Coolant82 °C
  • Oil3.9 bar
  • Fuel212 L
The same four engine pills with the default 9em columns and with 14em columns, in the same width.
Code
import { InstrumentPill } from "@bosunkit/components/instrument-pill";
import { InstrumentPillGroup } from "@bosunkit/components/instrument-pill-group";
import type { ReactElement } from "react";

export const description: string =
  "The same four engine pills with the default 9em columns and with 14em columns, in the same width.";

export default function MinWidth(): ReactElement {
  return (
    <div style={{ display: "grid", gap: "var(--space-lg)", width: "100%", maxWidth: "36em" }}>
      <InstrumentPillGroup label="Engine, 9em columns">
        <InstrumentPill label="RPM" value="1850" />
        <InstrumentPill label="Coolant" value="82" unit="°C" />
        <InstrumentPill label="Oil" value="3.9" unit="bar" />
        <InstrumentPill label="Fuel" value="212" unit="L" />
      </InstrumentPillGroup>
      <InstrumentPillGroup label="Engine, 14em columns" minPillWidth="14em">
        <InstrumentPill label="RPM" value="1850" />
        <InstrumentPill label="Coolant" value="82" unit="°C" />
        <InstrumentPill label="Oil" value="3.9" unit="bar" />
        <InstrumentPill label="Fuel" value="212" unit="L" />
      </InstrumentPillGroup>
    </div>
  );
}

Hidden label

showLabel={false} keeps the label for screen readers only, for a group whose card or section already names it.

House bank
  • Voltage12.6 V
  • Charge52 %
Two pills under a card that already names them: the group's label is kept for screen readers only.
Code
import { InstrumentPill } from "@bosunkit/components/instrument-pill";
import { InstrumentPillGroup } from "@bosunkit/components/instrument-pill-group";
import type { ReactElement } from "react";

export const description: string =
  "Two pills under a card that already names them: the group's label is kept for screen readers only.";

export default function HiddenLabel(): ReactElement {
  return (
    <div style={{ width: "100%", maxWidth: "24em" }}>
      <InstrumentPillGroup label="House bank" showLabel={false}>
        <InstrumentPill label="Voltage" value="12.6" unit="V" />
        <InstrumentPill label="Charge" value="52" unit="%" priority="warning" trend="rising" />
      </InstrumentPillGroup>
    </div>
  );
}

Props

PropTypeDefaultDescription
labelrequiredstring–What the pills are together ("Anchor watch", "Engine"), as the caller displays it; it names the group.
showLabelboolean | undefinedtrueWhether the label shows; on by default. Off, it is kept for screen readers only, for a group whose place already says what it holds.
childrenrequiredReactNode–The pills, each an InstrumentPill; each goes in its own list item.
minPillWidthstring | undefined–The narrowest a pill gets before the grid wraps to fewer columns, as a CSS length in em; "9em" by default.
classNamestring | undefined–Classes added to the group's own.
testIdstring | undefined–data-testid on the group; its parts are ${testId}--label and ${testId}--list.
refRef<HTMLDivElement> | undefined–The group's element.
Do
Anchor watch
  • From anchor31 m
  • Depth8.4 m
Group the pills that belong together under one label, and let the group set the columns.
Don't
From anchor31 mDepth8.4 m
Don't run pills of different widths along a line. The values move from row to row and the eye has to hunt for them.
  • Instrument pill: one pill, its states and how it marks an update.
  • Mobile: the anchor watch's pills on a phone.
  • Telemetry strip: readings on one line, for a strip rather than a grid.