Textbox
A text container with a precise height, alignment and a width that can be reserved.
On this page
Five sizes, 16 to 40 px high
Weights and alignments in a reserved width
Distance to go, nmi
Code
import { ObcTextboxAlignment, ObcTextboxFontWeight, ObcTextboxSize, Textbox } from "@bosunkit/instruments";
import { useEffect, useState } from "react";
import type { CSSProperties, Dispatch, ReactElement, SetStateAction } from "react";
export const description: string =
"Althea's log line set in textboxes on a one-second feed: all five sizes on the cap-height grid, three weights, three alignments inside reserved widths, and the same changing distance in tabular and proportional digits, so one column holds still and the other moves.";
const SIZES: { size: ObcTextboxSize; text: string }[] = [
{ size: ObcTextboxSize.xs, text: "Source: echosounder" },
{ size: ObcTextboxSize.s, text: "Depth under keel" },
{ size: ObcTextboxSize.m, text: "10.2 m" },
{ size: ObcTextboxSize.l, text: "12.4 m" },
{ size: ObcTextboxSize.xl, text: "12.4" },
];
const PANEL_STYLE: CSSProperties = {
display: "grid",
gap: 6,
padding: 12,
borderRadius: 10,
background: "var(--container-section-color)",
color: "var(--element-active-color)",
minWidth: 0,
};
const HEADING_STYLE: CSSProperties = {
margin: 0,
fontSize: 12,
fontWeight: 600,
color: "var(--element-neutral-color)",
};
const RULE_STYLE: CSSProperties = { borderBottom: "1px dashed var(--element-disabled-color)" };
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);
};
}, []);
// Counting down through every digit, so the proportional column visibly changes width.
const distance: string = (111.1 - (step % 100) * 1.11).toFixed(1);
return (
<div
style={{
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(270px, 1fr))",
gap: 12,
width: "100%",
maxWidth: 600,
}}
>
<div style={PANEL_STYLE}>
<p style={HEADING_STYLE}>Five sizes, 16 to 40 px high</p>
{SIZES.map((entry: { size: ObcTextboxSize; text: string }): ReactElement => (
<div key={entry.size} style={{ display: "flex", alignItems: "center", gap: 10, ...RULE_STYLE }}>
<span style={{ ...HEADING_STYLE, fontWeight: 400, width: 22 }}>{entry.size}</span>
<Textbox size={entry.size} alignment={ObcTextboxAlignment.Left} tabularNums>
{entry.text}
</Textbox>
</div>
))}
</div>
<div style={PANEL_STYLE}>
<p style={HEADING_STYLE}>Weights and alignments in a reserved width</p>
<div style={{ display: "grid", justifyItems: "stretch", gap: 2 }}>
<div style={RULE_STYLE}>
<Textbox
alignment={ObcTextboxAlignment.Left}
fontWeight={ObcTextboxFontWeight.regular}
length="Port de Sóller, 18:00"
>
Fornells
</Textbox>
</div>
<div style={RULE_STYLE}>
<Textbox
alignment={ObcTextboxAlignment.Center}
fontWeight={ObcTextboxFontWeight.semibold}
length="Port de Sóller, 18:00"
>
Cap de Formentor
</Textbox>
</div>
<div style={RULE_STYLE}>
<Textbox
alignment={ObcTextboxAlignment.Right}
fontWeight={ObcTextboxFontWeight.bold}
length="Port de Sóller, 18:00"
>
Port de Sóller, 18:00
</Textbox>
</div>
</div>
<p style={{ ...HEADING_STYLE, marginTop: 8 }}>Distance to go, nmi</p>
<div style={{ display: "flex", gap: 16, alignItems: "center" }}>
<div style={{ display: "grid", gap: 2 }}>
<span style={{ ...HEADING_STYLE, fontWeight: 400 }}>Tabular, reserved</span>
<div style={RULE_STYLE}>
<Textbox size={ObcTextboxSize.l} tabularNums length="000.0">
{distance}
</Textbox>
</div>
</div>
<div style={{ display: "grid", gap: 2 }}>
<span style={{ ...HEADING_STYLE, fontWeight: 400 }}>Proportional</span>
<div style={{ ...RULE_STYLE, justifySelf: "start" }}>
<Textbox size={ObcTextboxSize.l} alignment={ObcTextboxAlignment.Left}>
{distance}
</Textbox>
</div>
</div>
</div>
</div>
</div>
);
}
A textbox holds a short, read-only string, such as a value, a label or a unit, at a size whose cap height falls on a
fixed grid. The five sizes, xs to xl, are 16, 20, 24, 32 and 40 pixels high, with the text aligned to the right by
default. length reserves the width of the longest string the box will show, so the box does not resize as the text
changes. tabularNums gives the digits a fixed width, so a number that updates stays aligned.
The readout components are built from textboxes. Use an input for text the crew edits.
Examples
Large value
Code
import { ObcTextboxSize, Textbox } from "@bosunkit/instruments";
import type { ReactElement } from "react";
export const description: string = "A large value in tabular numerals, so the digits keep their width.";
export default function LargeValue(): ReactElement {
return (
<Textbox size={ObcTextboxSize.l} tabularNums>
12.4
</Textbox>
);
}
Reserve space without hiding content
Use length for a known display width, such as the largest expected value or unit, and test the actual strings
at that reservation. A character count does not establish that every translated word will occupy the same width.
Use tabular digits for changing numbers and keep ordinary prose in Text.
Textbox is a read-only presentation primitive. It does not supply field labeling, validation, input behavior or source quality. Place it inside the appropriate readout component when it represents a measured quantity.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| alignment | ObcTextboxAlignment | ObcTextboxAlignment.Right | Horizontal position of the text within the box. Default: right. |
| size | ObcTextboxSize | ObcTextboxSize.m | Box size — maps to a fixed height (16 / 20 / 24 / 32 / 40 px) with 4px padding above and below, giving cap heights of 8 / 12 / 16 / 24 / 32 px so text aligns to a predictable grid. Default: m. |
| fontWeight | ObcTextboxFontWeight | ObcTextboxFontWeight.regular | Font weight: regular (default), semibold, or bold. |
| tabularNums | boolean | false | Render digits as fixed-width, lining numerals (tabular-nums lining-nums
+ the ss04/tnum/lnum features) so numeric values stay column-aligned
and width-stable as they update — use for readouts and other live numeric
displays. Default: off. |
| length | ReactNode | – | Reserves a minimum width invisibly (the upstream length slot) so the box
does not resize as the visible text changes. Pass the longest expected
string, e.g. "888.8" or "Wind speed". |
| children | ReactNode | – | The visible text content. |
| className | string | – | Class name added to the root element. |
Related
- Readout: a value with a label, a unit and a source.
- Typography: the type scale and the numerals.
- Instruments: the other instruments.