Skip to content
design
Components

Ship data

The vessel's own data in one panel, with the compass at the center, the heading figures and position at the left, and the wind and current at the right.

On this page

Own ship data

270
HDG
°
259
COG
°
0
ROT
deg/min
62° 27.590′ N
006° 11.954′ E

Wind

4.5
Speed
kn
051
Direction
°

Current

2.0
Speed
kn
045
Direction
°
Own ship data for Althea under way: the heading figures and position, the compass, and the wind and current.
Code
import { ShipData, type ShipDataLabels } from "@bosunkit/components/ship-data";
import type { ReactElement } from "react";

export const description: string =
  "Althea under way: heading 270°, course over ground 259° and no rate of turn, a position off the Norwegian coast, wind " +
  "4.5 kn from 051° and a 2.0 kn current setting from 045°, the compass drawing each of them.";

export const LABELS: ShipDataLabels = {
  heading: "HDG",
  courseOverGround: "COG",
  rateOfTurn: "ROT",
  wind: "Wind",
  current: "Current",
  speed: "Speed",
  direction: "Direction",
};

export default function Showcase(): ReactElement {
  return (
    <div style={{ width: "100%", maxWidth: 640 }}>
      <ShipData
        title="Own ship data"
        labels={LABELS}
        heading={270}
        courseOverGround={259}
        rateOfTurn={0}
        position={{ latitude: 62.45983, longitude: 6.19923 }}
        wind={{ speedKnots: 4.5, fromDirection: 51 }}
        current={{ speedKnots: 2, fromDirection: 45 }}
      />
    </div>
  );
}

Ship data is a panel that answers the questions a watchkeeper asks first: where the bow points, where the vessel is going, how fast it is turning, where it is, and what the wind and the water are doing. It draws nothing of its own. It is a card holding the compass with the wind and the current drawn on it, the heading, course over ground and rate of turn as readouts, the wind and the current as two groups of readouts under section headings, and the position as text.

The panel lays out in three columns where it has room and in one where it has not. A value no sensor reports shows a dash, and the position a dash, so the layout does not move when a sensor returns. Every word is passed in, translated, and the units are symbols: degrees, degrees per minute and knots.

01The questions in the order they are askedHeading and course at the left where the eye starts, the compass that shows them in the middle, the weather at the right.
02A dash keeps the layoutA missing sensor shows a dash in the same place, so a value arriving later does not push the others.
03Nothing new to learnEvery part is a component the crew already know: the compass, the readouts, the card.

Examples

No data

Own ship data

‒
HDG
°
‒
COG
°
‒
ROT
deg/min
—

Wind

‒.‒
Speed
kn
‒
Direction
°

Current

‒.‒
Speed
kn
‒
Direction
°
With no compass, no fix and no wind sensor the panel keeps its shape: every readout shows a dash and the position a dash, so nothing moves when a sensor returns.
Code
import { ShipData } from "@bosunkit/components/ship-data";
import type { ReactElement } from "react";
import { LABELS } from "./showcase";

export const description: string =
  "With no compass, no fix and no wind sensor the panel keeps its shape: every readout shows a dash and the position a dash, so nothing moves when a sensor returns.";

export default function NoData(): ReactElement {
  return (
    <div style={{ width: "100%", maxWidth: 640 }}>
      <ShipData
        title="Own ship data"
        labels={LABELS}
        heading={null}
        courseOverGround={null}
        rateOfTurn={null}
        position={null}
        wind={null}
        current={null}
      />
    </div>
  );
}

Trust

A value the caller gives its trust is drawn as a reading: a stale or lost value shows its age, a degraded one its reason, and one with a source opens it from the value. A value given no trust is a plain readout, and a missing one a dash.

Own ship data

3 min
0
ROT
deg/min
62° 27.590′ N
006° 11.954′ E
invalid, last seen 8 min

Wind

4.5
Speed
kn
051
Direction
°

Current

2.0
Speed
kn
045
Direction
°
The heading from a compass that stopped 3 min ago, and a position last fixed 8 min ago: each value the caller gives its trust is drawn as a reading, with its age, and the position says when it was last seen.
Code
import { ShipData } from "@bosunkit/components/ship-data";
import type { ReactElement } from "react";
import { LABELS } from "./showcase";

export const description: string =
  "The heading from a compass that stopped 3 min ago, and a position last fixed 8 min ago: each value the caller gives its trust is drawn as a reading, with its age, and the position says when it was last seen.";

export default function Trust(): ReactElement {
  return (
    <div style={{ width: "100%", maxWidth: 640 }}>
      <ShipData
        title="Own ship data"
        labels={LABELS}
        heading={270}
        courseOverGround={259}
        rateOfTurn={0}
        position={{ latitude: 62.45983, longitude: 6.19923 }}
        wind={{ speedKnots: 4.5, fromDirection: 51 }}
        current={{ speedKnots: 2, fromDirection: 45 }}
        trust={{
          heading: { integrity: "stale", ageSeconds: 190, source: "Fluxgate compass" },
          courseOverGround: { integrity: "fresh", source: "GPS" },
          position: { integrity: "invalid", ageSeconds: 480 },
        }}
      />
    </div>
  );
}

Small face

Own ship data

047
HDG
°
052
COG
°
8
ROT
deg/min
50° 08.526′ N
005° 03.102′ W

Wind

14.0
Speed
kn
310
Direction
°

Current

1.2
Speed
kn
190
Direction
°
`faceDiameter` of 140 for a panel in a narrower column, with the title one level down under a page heading.
Code
import { ShipData } from "@bosunkit/components/ship-data";
import type { ReactElement } from "react";
import { LABELS } from "./showcase";

export const description: string =
  "`faceDiameter` of 140 for a panel in a narrower column, with the title one level down under a page heading.";

export default function SmallFace(): ReactElement {
  return (
    <div style={{ width: "100%", maxWidth: 520 }}>
      <ShipData
        title="Own ship data"
        labels={LABELS}
        headingLevel={3}
        faceDiameter={140}
        heading={47}
        courseOverGround={52}
        rateOfTurn={8}
        position={{ latitude: 50.1421, longitude: -5.0517 }}
        wind={{ speedKnots: 14, fromDirection: 310 }}
        current={{ speedKnots: 1.2, fromDirection: 190 }}
      />
    </div>
  );
}

Props

PropTypeDefaultDescription
titlerequiredstring–The panel's title ("Own ship data"), translated by the caller.
labelsrequiredShipDataLabels–The words the readouts and the two groups carry.
headingrequirednumber | null–The vessel's heading in degrees true, or null when no compass reports it.
courseOverGroundrequirednumber | null–The course over ground in degrees true, or null.
rateOfTurnrequirednumber | null–The rate of turn in degrees per minute, positive to starboard, or null.
positionrequiredPosition | null–The vessel's position, or null when no fix is held.
windrequiredShipDataFlow | null–The wind the vessel feels, as it is measured, or null when there is no wind sensor.
currentrequiredShipDataFlow | null–The current under the vessel, or null when none is known.
trustPartial<Record<ShipDataValue, ShipDataTrust>> | undefined–How far each value can be trusted. A value given its trust is drawn as a Reading, with its age and its integrity treatment; a value without one is a plain readout, and a missing one a dash.
faceDiameternumber | undefined200The compass face's diameter in pixels; 200 by default.
headingLevelNestedHeadingLevel | undefined–The heading level of the title, as the card sets it.
classNamestring | undefined–Added to the panel's classes.
testIdstring | undefined–Becomes data-testid on the panel.
refRef<HTMLElement> | undefined–The panel element.
Do

Own ship data

Heading 270°, course over ground 259°
Keep the readouts in one panel with the compass, so the figures and the picture of them are read together.
Don't

Heading

270°

Course

259°

Wind

4.5 kn
Don't scatter the heading, the course and the wind over separate cards: the crew then assemble the picture themselves.
  • Compass: the heading card that shows the heading, the course, the wind and the current.
  • Readout: a value with its label and unit.
  • Card: the bordered surface the panel sits on.
  • Reading: a single live value with its age and source.