Readout block
The block a readout builds its value, setpoint and advice from.
On this page
Code
import {
ObcTextboxAlignment,
ObcTextboxFontWeight,
ObcTextboxSize,
ReadoutBlock,
ReadoutDataQuality,
ReadoutSize,
ReadoutValueType,
} from "@bosunkit/instruments";
import { MapPin, Navigation, Waves } from "lucide-react";
import { useEffect, useState } from "react";
import type { CSSProperties, Dispatch, ReactElement, ReactNode, SetStateAction } from "react";
export const description: string =
"A cockpit repeater built from bare blocks on a one-second feed: three sizes and a larger number size, the enhanced tone, three weights, marker icons, degrees with hinted zeros, reserved widths and alignment, a text position, an off value and both data quality marks.";
const CELL_STYLE: CSSProperties = {
display: "grid",
gap: 4,
justifyItems: "end",
padding: "10px 12px",
borderRadius: 8,
background: "var(--container-section-color)",
};
const CAPTION_STYLE: CSSProperties = { fontSize: 11, color: "var(--element-neutral-color)", justifySelf: "start" };
function Cell({ caption, children }: { caption: string; children: ReactNode }): ReactElement {
return (
<div style={CELL_STYLE}>
<span style={CAPTION_STYLE}>{caption}</span>
{children}
</div>
);
}
export default function Showcase(): ReactElement {
const [step, setStep]: [number, Dispatch<SetStateAction<number>>] = useState<number>(0);
useEffect((): (() => void) => {
const timer: number = window.setInterval((): void => {
setStep((previous: number): number => previous + 1);
}, 1000);
return (): void => {
window.clearInterval(timer);
};
}, []);
const heading: number = 58 + 3 * Math.sin(step / 4);
const speed: number = 6.2 + 0.4 * Math.sin(step / 3);
const depth: number = 9.6 + 0.8 * Math.sin(step / 5);
const distance: number = 14.2 - (step % 60) * 0.02;
return (
<div
style={{
display: "grid",
gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))",
gap: 8,
width: "100%",
maxWidth: 600,
}}
>
<Cell caption="Heading, autopilot in command">
<ReadoutBlock
value={heading}
size={ReadoutSize.large}
enhanced
weight={ObcTextboxFontWeight.bold}
hasDegree
maxDigits={3}
hintedZeros
hasIcon
icon={<Navigation size={18} aria-hidden />}
/>
</Cell>
<Cell caption="Speed over ground, kn">
<ReadoutBlock
value={speed}
size={ReadoutSize.medium}
weight={ObcTextboxFontWeight.semibold}
fractionDigits={1}
maxDigits={2}
spaceReserver="00.0"
alignment={ObcTextboxAlignment.Right}
/>
</Cell>
<Cell caption="Depth, m, large digits in a small block">
<ReadoutBlock
value={depth}
size={ReadoutSize.small}
valueSize={ObcTextboxSize.xl}
fractionDigits={1}
hasIcon
icon={<Waves size={14} aria-hidden />}
/>
</Cell>
<Cell caption="Distance to Sóller, nmi">
<ReadoutBlock
value={distance}
fractionDigits={2}
maxDigits={3}
hintedZeros
alignment={ObcTextboxAlignment.Left}
/>
</Cell>
<Cell caption="Position, GPS">
<ReadoutBlock
value="39°47.6′N 2°41.9′E"
valueType={ReadoutValueType.text}
hasIcon
icon={<MapPin size={14} aria-hidden />}
/>
</Cell>
<Cell caption="Radar range">
<ReadoutBlock value={0} off offText="Standby" size={ReadoutSize.medium} />
</Cell>
<Cell caption="True wind, kn, sensor uncalibrated">
<ReadoutBlock value={17.6} fractionDigits={1} dataQuality={ReadoutDataQuality.lowIntegrity} />
</Cell>
<Cell caption="Sea temperature, °C, no reading">
<ReadoutBlock value={null} dataQuality={ReadoutDataQuality.invalid} />
</Cell>
</div>
);
}
A readout block is one number set on the cap-height grid, with an optional marker icon in front and a degree sign after
it. Its variant is the value, a setpoint or an advice, and the variant sets the marker icon and the color.
fractionDigits sets the decimals and maxDigits reserves the integer width. off shows offText in place of the
number.
Marker icons center on the value even when valueSize differs from the block's size. alignment positions the
text inside its reserved width; the parent layout places the whole block.
The readout and the readout list item are built from these blocks. A block is not normally used on its own.
Examples
Value
Code
import { ReadoutBlock } from "@bosunkit/instruments";
import type { ReactElement } from "react";
export const description: string = "The default block, a plain value, at its default size.";
export default function Value(): ReactElement {
return (
<ReadoutBlock value={12.4} fractionDigits={1} />
);
}
Reserve the value, preserve its meaning
Choose maxDigits for the largest expected integer, then verify negative values, decimals, degree markers and
off text at the selected size. alignment positions content inside that reservation; it does not align sibling
labels or move the whole block. Use ReadoutList for shared row columns.
fractionDigits is display precision, not a domain-specific rounding policy. Prepare safety-sensitive values
through the quantity formatter before rendering. A standalone block needs surrounding label, unit, source and
quality context; its visual variant only distinguishes a value, setpoint or advice.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | ReadoutBlockVariant | undefined | ReadoutBlockVariant.value | Semantic variant (value / setpoint / advice). |
| value | number | string | null | undefined | null | The value; null/undefined renders a dash. A number by default, or text
when {@link ReadoutBlockProps.valueType} is text. |
| valueType | ReadoutValueType | undefined | ReadoutValueType.number | How {@link ReadoutBlockProps.value} is interpreted. number (default)
formats it via fractionDigits; text renders it verbatim and ignores
the numeric format options. |
| size | ReadoutBlockSize | undefined | ReadoutBlockSize.small | Density tier — icon size, gap, degree tier. |
| valueSize | ObcTextboxSize | undefined | – | Resolved number-typography size. When unset it is derived from size
(small→s, medium→m, large→l), so a parent that de-emphasizes a block (e.g.
a secondary setpoint) can pass a smaller size without changing the tier. |
| enhanced | boolean | undefined | false | Accent (in-command) color tone. |
| weight | ObcTextboxFontWeight | undefined | ObcTextboxFontWeight.regular | Number font weight (regular / semibold / bold); color is independent. |
| hasDegree | boolean | undefined | false | Render the trailing cap-height degree glyph (°). |
| hasIcon | boolean | undefined | false | Show the leading marker-icon container (always on for setpoint/advice). |
| fractionDigits | number | undefined | 0 | Number of fraction digits. Available when valueType is number. |
| maxDigits | number | undefined | 0 | Integer digits to reserve / hint (independent of fractionDigits).
Available when valueType is number. |
| hintedZeros | boolean | undefined | false | Render muted leading zeros filling the integer part to maxDigits.
A negative value keeps them all — the sign is hoisted ahead of them — and
an unavailable value renders dashes across the whole reserved width.
Available when valueType is number. |
| hasSignSpacer | boolean | undefined | false | Reserve a minus-sign column ahead of the digits: an invisible sign
placeholder holds the column open while the value is non-negative and the
real sign fills it when negative, so the width does not change across
zero. Available when valueType is number. |
| spaceReserver | string | undefined | – | Explicit longest string to reserve width for (e.g. "0000.0"). |
| off | boolean | undefined | false | Render offText instead of a number (e.g. equipment powered down). |
| offText | string | undefined | "OFF" | Text shown when off is true. |
| alignment | ObcTextboxAlignment | undefined | ObcTextboxAlignment.Right | Text alignment of the number within its reserved width. |
| dataQuality | ReadoutBlockDataQuality | undefined | – | Per-block measurement quality (outline chip). |
| alert | boolean | AlertFrameConfig | undefined | false | Per-block alert frame; nests inside any parent alert frame. |
| touching | boolean | undefined | false | Setpoint focus (touch) state — only meaningful for the setpoint variant. |
| hidePhase | ReadoutBlockHidePhase | undefined | ReadoutBlockHidePhase.none | Setpoint pop-up fade phase — only meaningful for the setpoint variant. |
| icon | ReactNode | undefined | – | Replaces the variant's default marker icon (the upstream icon slot). |
| className | string | undefined | – | Class name added to the root element. |
Related
- Readout: a value with its label, unit and source.
- Readout list item: the blocks as a row in a list.
- Instruments: the other instruments.