Skip to content

feat(instruments): new radial instruments and new variations - #1058

Merged
talpitoo merged 48 commits into
developfrom
feat/compass-heading-center-content
Jul 29, 2026
Merged

feat(instruments): new radial instruments and new variations#1058
talpitoo merged 48 commits into
developfrom
feat/compass-heading-center-content

Conversation

@talpitoo

@talpitoo talpitoo commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Implements the OpenBridge 6.1 instrument work across the radial/watch family: five new instruments (obc-rot-linear, obc-speed-directions, obc-top-view-propulsion, obc-pitch-roll-heave, obc-draft-trim) plus new variants on existing ones — compass/heading center readouts and arrow styles, flat-strip and rate-of-turn readouts, the rate-of-turn track bar, the heave bar type, and a shared tick ladder on the inclinometer arcs. Every design was verified against the Figma component sets via MCP.

New instruments

obc-pitch-roll-heave (WIP)

Pitch arc, roll arc and a linear heave column on one watch face (Figma node 19160-296360). single-scale puts pitch right, roll bottom and heave in the left band slot with the tick lane facing outward; dual-scale mirrors both arcs and moves the column to the centre; hasReadout swaps the vessel silhouettes for stacked Pitch/Roll/Heave readouts. Marked @experimental (wip story tag).

The heave column is not sized independently — its dimensions fall out of the arc geometry:

width  = band thickness
height = 2 * capRadius * sin(pitchArcAngle)

capRadius is the pitch arc's outer radius about its own origin (un-zoomed that is the outer ring; under zoom the arc sits on a shifted sub-watch, so the two differ). This yields Figma's 184 at the defaults and keeps the column's top and bottom edges level with the pitch arc's end caps. Every other boundary then follows from the two half-extents alone: both diagonal gaps are 90 - pitch - roll (15° at the defaults) and the complement ring spans [270+pitch, 90-pitch], i.e. exactly symmetric about the top. That the whole measured layout collapses to two angles is the evidence that 184 is derived rather than a magic number.

Design decisions:

  • Reuse over redraw: the column is built from watchfaceLinear() — the same building block obc-heave uses — rather than by embedding <obc-heave>, whose fixed box/gauge widths and viewBox would all have to become configurable on a @stable component.
  • Crosshair on the overlay, not crosshairEnabled: the design has the arc bands covering the crosshair arms, but obc-watch renders its crosshair after watchCircle()/renderBars(), i.e. on top. The component draws its own in the under-watch layer so the bands and the column mask it naturally; no change to obc-watch. It is dropped entirely when hasReadout, matching how obc-pitch-roll already gates its horizon line.
  • Zoom clearance: zoomToFitArc follows obc-pitch-roll's per-axis frames and ratio-preserving corner bisection, then adds two rules. Roll-vs-column uses point-to-rectangle distance rather than the corner-to-corner signedDist used between two arcs — a corner can clear a rectangle on one axis alone, and signedDist scores −12.8 for a pair that is actually 32.8 apart. dual-scale clamps the centred column's height only, never its width, which reads as a match for the band thickness. Both rules are no-ops at the un-zoomed defaults, which is what reproduces the design exactly.
  • Accepted deviation: the Figma art sits a uniform +4 units outward of the code constants (outer ring 188 vs OUTER_RING_RADIUS 184). Every relationship matches, so the implementation builds on the existing obc-watch radii to stay consistent with obc-pitch/obc-roll/obc-pitch-roll. If the offset turns out to be an intentional design-system change it affects every radial instrument and belongs in its own PR.

obc-draft-trim (WIP)

Draught at the bow and the stern on two vertical scales either side of a vessel side view (Figma node 20122-231157), each filled from the waterline down to its measured value; the difference between the two is the vessel's trim. Marked @experimental.

  • draftFore / draftAft, positive below the waterline
  • instrumentRange — each scale spans ±instrumentRange around the waterline, so the upper half reads as freeboard
  • advice (shared by both scales, each triggered by its own draught), vesselImage, priority

Design decisions:

  • Reuses obc-heave's scale wholesale: the same 72-unit column at the same ±132 offset, the same 336-unit height and the same tick configuration, with the aft column mirrored so its tick lane faces outward. The centre panel adds the waterline, the water fill below it and the vessel silhouette. Measured against Figma, the hull renders 133.1 units wide vs the design's 133.0.
  • The vessel is a static reference and does not pitch with the trim — the Figma variants show a level vessel while the two scales differ (5 m aft, 2.5 m fore), so the values are carried by the scales alone.
  • Scale space is positive-up, so draughts — measured downward from the waterline — are negated, and advice bounds are negated and swapped, since negating an interval reverses it.

obc-rot-linear

The linear rate-of-turn strip (Figma Bar/Bar Readout × Regular/Enhanced/PORT STBD) — numeric ± scale, a bar growing from the band center to the value with an end needle, and the bottom readout. Built as a thin wrapper over obc-watch-flat, which gains additive default-off barAreas/needles options (the linear analogues of the radial ones).

obc-speed-directions (WIP)

All-in-one directional speed instrument from Figma "Speed-directions" (node 323-27646): vessel top view + speed indicators on the vessel axes, 9 variants = 3 types × 3 styles. Marked @experimental — the API may change.

  • type: alongAthwartArrows (chevrons on along + bow/stern athwart axes), alongAthwartBars (proportional bars with chevron tips, same axes), longLatArrows (chevrons on along + single midship athwart axis)
  • frameStyle: standalone | framed (rounded square + axis lines) | compass (obc-watch face)
  • Signed knots; an axis renders only while its value is defined: speedAlongKnots (+fore/−aft), speedAthwartBowKnots / speedAthwartSternKnots / speedAthwartKnots (+stbd/−port)
  • Derivation knobs: alongSpeedStepKnots=3 / athwartSpeedStepKnots=1 (chevron count = min(ceil(|v|/step), 3), matching the vue-demo VesselMotion recipe), alongMaxSpeedKnots=9 / athwartMaxSpeedKnots=3 (bar length clamp), tintedArrows, vesselImage (framed/compass only)

Design decisions:

  • Reuse over redraw: chevron paths extracted from obc-speed-arrows into a shared speed-arrows-art.ts (speed-arrows snapshots unchanged); vessels from watch/vessel.ts; compass face is obc-watch through one computeRadialFrame() result shared with the overlay viewBox; framed square via svghelpers/rectangular.ts rect().
  • Geometry extracted from Figma into a pure speed-directions-geometry.ts (unit-tested): 384-unit flat canvas, cells/bars per type+style, bar tip chevrons top-anchored (apex straddles the bar tip), axis lines measured from Figma renders (3-axis types: vertical + horizontals at ±48 only); compass axis lines are chords capped at innerRingRadiusFor(single).
  • Standalone vessels follow Figma per type: simplified genericTop (arrows/long-lat, 2× placement scale) and psvTop (bars).
  • Accepted deviations: compass face uses watch radii (ring 160–184 vs Figma masters 164–188); north arrow is the standard obc-watch glyph (Figma shows the compact triangle at all sizes).
  • fix(watch): generic-top.ts was the only vessel art without vector-effect="non-scaling-stroke" (mask-filled outline band); redrawn in the family-standard fill+stroke pattern. generic-side.ts still has the legacy pattern (follow-up candidate).

obc-top-view-propulsion (WIP)

Propulsion gauge from Figma "Top-view-propulsion" (node 37391-137941): watch face + center propeller, value arc on the inner track, needle at the arc end, radial setpoint marker. Marked @experimental.

  • type: power (single track) | pitch-rpm (primary track + thin secondary pitch arc)
  • power / rpm with full prefixed setpoint families (SetpointBundle each); pitch (value only — the design shows no secondary setpoint marker; deferred with a designer TODO)
  • state / priority / loading (% progress arc on the outer ring while loading), azimuth-style tickmark intervals with the thick zero line (TickmarkType.zeroLineThick), hasLabelSpacer, faceDiameter
  • propeller: PropellerImage — interchangeable center art

Design decisions:

  • Thin wrapper per the watch-radial instructions: the power/rpm display is the existing rate-of-turn track-bar recipe (barAreas gray track + tint arc, needles pill at the arc end).
  • Pitch-rpm band subdivision (design-review correction): the 112..160 band splits into the primary sub-band (128..160, rpm fill + shorter needle), a white divider ring (120..128) and an 8px secondary lane (112..120) holding the pitch line — a plain arc with a flat cut at zero and rounded tip at the value. Enabled by additive snapshot-neutral obc-watch knobs: optional WatchBarArea.outerRadius/innerRadius and WatchNeedle.length.
  • feat(watch): propeller registry — eight top-view propeller types exported from Figma (node 37391-148397), cleaned of page chrome and converted via script/convert-vessel-svg-to-ts.ts into the 160-box vessel coordinate system: watch/propellers/*.ts + watch/propeller.ts (PropellerImage, propellerImages, topPropellers). Two extra canonical color mappings applied post-conversion (#BEBEBE → tick-mark-tertiary, #DDDDDD → border-outline). Figma's unnamed "Type9" variant is named cap-five-blade with a designer TODO.
  • Accepted deviations (WIP): track band 112..160 watch units vs Figma 120..164; white disc inside the track vs Figma's faint gray; off state follows watch's off rendering; Figma's enhanced pitch-rpm variant instantiates needle components with regular colors — the implementation follows the visible result (priority-driven colors).

New variants on existing instruments

Compass & heading

  • Center readouts (centerReadouts on obc-compass and obc-heading): replaces the vessel with 1–3 obc-readouts in the four Figma "Center label" arrangements — single primary; two primaries; primary + secondary; primary + two secondaries side by side — separated by a horizontal divider. Entries are source-bound; labels/units/colors are defaulted:

    interface CompassCenterReadout {
      source: 'hdg' | 'cog' | 'rot'; // value auto-bound: heading / courseOverGround / rateOfTurnDegreesPerMinute
      label?: string;                // defaults HDG / COG / ROT
      unit?: string;                 // defaults DEG / DEG / °/min
      fractionDigits?: number;       // default 0
      size?: ReadoutSize;            // default: large for the first entry, medium for the rest
    }

    Colors follow the existing per-element priorityElements model (e.g. enhanced HDG over neutral COG, exactly as in the Figma heading center-label variant). Readouts reuse the existing obc-readout API only (closest-match rule; no new typography knobs).

  • Arrow styles: hdgArrowStyle (arrowHead | needle | vector | beamLine) and cogArrowStyle (arrowHead | needle | vector | velocityVector) on both instruments. The art lives in a new shared course-arrows module: the existing compass arrowheads and heading needles moved verbatim, plus the four new Figma glyphs (HDG vector/beam-line with beam crossbar + dotted astern line; COG dashed vector with single/double open arrowhead, fixed length).

  • Heading parity (Figma type: Regular | Vessel type | Center label): obc-heading gains an optional vesselImage (face auto-switches to the double-band ring while center content shows), the same center readouts and arrow styles, plus a full JSDoc/autodocs documentation upgrade.

  • Map graphics stays a story recipe over granular props (new MapGraphics story): psv-top vessel, HDG vector, COG arrowHead, ROT bar, outside NSWE labels. (The Figma design uses a CCRP vessel variant; that image is deferred to its own PR via the convert-vessel-svg-to-ts pipeline.)

Flat strip & rate of turn

  • obc-compass-flat: hasReadout + label/unit/fractionDigits (compass-sector-identical API) renders a heading readout below the strip via the shared helper.
  • obc-rate-of-turn: hasReadout (centered ROT DEG/min readout, dash until the physical value is set) and hasTrackBar — a bar in the ring band from twelve o'clock to the measured value with a needle marker at its end and sector tickmarks, composed purely from existing obc-watch inputs (barAreas + needles + tickmarks on the double face), with rot-sector's port/starboard and priority coloring.

Heave

ObcHeaveType (vessel | bar). bar drops the frame, reference line and vessel silhouette and switches the viewBox to the Figma 128×384 frame with the 72-unit scale column centred; watchfaceLinear() is called with unchanged arguments, so the tick pattern matches the standalone design. vessel stays the default and renders identically — its three baselines pass untouched. vesselImage, gainScale and draftOffset are annotated @availableWhen type==vessel.

Pitch, roll & pitch-roll

The 5° secondary tick ladder measured on the Figma watch face (radial extent 164→172, no primary ticks) is backported to obc-pitch, obc-roll and both obc-pitch-roll render paths via the new shared arcTickmarks(). The zoomed path passes the clamped half-extent, not the requested one, so ticks cannot fall outside the band that is actually drawn.

Shared modules

  • readout/center-readout.tsrenderCenterReadouts() gains an optional CenterReadoutArrangement: primarySecondary (default, unchanged — first entry, one divider, then the rest side by side) and stacked (new — a divider between every entry, used by pitch-roll-heave's Pitch/Roll/Heave column). The default is unchanged, so all seven existing consumers keep their output.
  • watch/tickmark.tsarcTickmarks(centerAngle, halfExtent, interval = 5) emits the secondary ladder along an arc band, skipping the arc centre (which carries its own main mark) and the ends, where the rounded end cap already reads as a boundary.
  • building-blocks/instrument-linearresolveLinearAdvice() (the hinted/regular/triggered mapping, extracted from obc-heave) and verticalScaleTickmarks(range) (the tick configuration for a scale spanning ±range around a zero reference) are now shared by obc-heave and obc-draft-trim. watchfaceLinear also gains options.maskId: the container clip-mask id was hard-coded to boxMask, and since ids are document-scoped, a component drawing two gauges in one shadow root had both resolving to the first one's mask — harmless only because the two masks happened to be identical. linearTickInterval(height, range, minSpacing = 16) picks a 1-2-5 tick step by on-screen spacing so a linear scale keeps a readable density when its height is dictated by the surrounding layout. It independently reproduces the intervals obc-heave hard-codes at its natural 336-unit height (1 at ±10, 0.5 at ±5) and the sparser 10-division ladder Figma shows on the compact pitch-roll-heave column — which is what fixes the constant. obc-heave keeps its literals so its baselines do not move.
  • course-arrows/ — HDG/COG arrow art shared by compass, heading and (via the deprecated compass/arrow.ts shim) compass-sector.
  • speed-arrows-art.ts — chevron art shared by obc-speed-arrows and obc-speed-directions.

Migration / snapshot notes

  • pitch-roll and compass-sector now render their readouts through the shared cluster helper (public APIs unchanged). compass-sector: zero pixel diffs; pitch-roll: intentional baseline update (the cluster gains the Figma-accurate 8px gaps around the divider).
  • The tick-ladder backport intentionally updates pitch (6), roll (7) and pitch-roll (8) baselines. Note that --update alone leaves two zoomed-in-narrow baselines stale: the ladder does change them (52 px) but the addon's anti-alias tolerance passes them, so they were regenerated explicitly.
  • The generic-top vessel redraw deliberately regenerates wind (4), ar/chart-object-vessel-button (1) and speed-directions (3) baselines.
  • All other defaults reproduce the previous rendering: existing compass, heading, compass-sector, compass-flat, watch-flat, rudder, gauge-radial, rot-sector, speed-gauge, azimuth-thruster, instrument-radial and watch baselines pass unchanged.
  • The instrument-linear extraction is behaviour-preserving: heave, thruster and main-engine baselines pass unchanged.
  • New stories are tagged 6.1 (story-level on extended 6.0 components; file-level on new components).

Cascade / zoomToFitArc safety

  • radial-frame.ts, arc-frame.ts and the advice dual-path are untouched. Deliberate, verified core-renderer touches: watch.ts renderBars now applies its area cut mask only when areas exist (band bars on full-circle faces no longer rely on lax dangling-reference handling; zero-diff for all existing consumers); watch-flat.ts gains the additive band bar/needle options (default off; compass-flat pixel-identical); obc-watch gains optional WatchBarArea.outerRadius/innerRadius and WatchNeedle.length (all eight barAreas/needles consumer suites verified unchanged).
  • compass-sector (zoom family) imports arrow() from compass/arrow.ts passing its zoom radiusOffset; both legacy arrow.ts modules remain as deprecated shims delegating to course-arrows with byte-identical signatures and output, so that path cannot drift.
  • obc-pitch-roll-heave reuses the obc-pitch-roll buildFrame contract verbatim; its two extra clearance rules run only under zoom and are no-ops at the un-zoomed defaults.

Verified as achievable with existing components (not implemented)

  • Figma "Heading sector"obc-compass-sector (arrowheads + hasReadout + priority variants); deltas are cosmetic (single-band arc face, no degree labels).
  • Figma "Heading linear"obc-compass-flat + the new hasReadout; deltas cosmetic (boxed strip, in-band arrow icons).
  • Whether either warrants a dedicated component or story is left as a designer decision.

Agent-doc updates

  • @availableWhen grammar extended with empty-array conditions (arr==[] / arr!=[]); vesselImage on compass/heading annotated accordingly.
  • AGENTS.md § 12 baseline-update command fixed: the filter must precede --update (the documented order ran the full suite in update mode).
  • AGENTS.md § 8: npm run analyze is required before testing stories of a newly created component (storybook arg mapping reads the manifest).
  • watch-radial-instruments.instructions.md: scope extended to pitch/**, pitch-roll-heave/**, rate-of-turn/**, course-arrows/** and the single-axis-inclinometer building block; documents the shared course-arrows / center-readout / arcTickmarks / linearTickInterval modules, the rate-of-turn track-bar recipe, and the pitch-roll-heave geometry contract (derived column size, the angular spans that follow from the two half-extents, and the zoom-only clearance rules — all no-ops at the un-zoomed defaults, which is what reproduces the design, so verify that before retuning their constants).

Open items

  • The zoomed pitch-roll-heave crosshair ends in open space at the top, because the complement ring that caps it un-zoomed is not drawn in the zoomed path. This matches how obc-pitch-roll's horizon line already behaves, but is untested against a design.
  • The two zoom clearance constants (CORNER_GAP_PX 32, inherited from obc-pitch-roll, and HEAVE_CENTRE_GAP_PX 10) have no design reference and may want visual iteration.
  • indicator-graph, donut-chart and pie-chart fail the visual suite locally (uPlot/canvas rendering, environment-sensitive); unrelated to this branch, baselines untouched, and they regenerate in the CI image.

🤖 Generated with Claude Code

Summary by CodeRabbit

Summary

  • New Features
    • Added shared centered multi-entry readouts with primary/secondary and stacked layouts across radial instruments, plus centered-heading readouts for compass variants.
    • Added configurable HDG/COG arrow styles using shared course-arrow rendering (legacy arrow helper deprecated).
    • Added new instruments: obc-rot-linear, obc-speed-directions, obc-top-view-propulsion; enhanced obc-rate-of-turn and obc-watch-flat (track bands).
  • Documentation
    • Expanded Storybook controls and demos for compass/heading and new/extended readout + arrow variants.
  • Bug Fixes
    • Improved watch crosshair center cutout handling and prevented bar-mask rendering when no areas exist.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 82bd79b7-24e0-403c-8efd-3a1a4dfe7beb

📥 Commits

Reviewing files that changed from the base of the PR and between 0079a72 and 6f44b30.

⛔ Files ignored due to path filters (1)
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/draft-trim/draft-trim.stories.ts/default-auto.png is excluded by !**/*.png
📒 Files selected for processing (4)
  • .github/instructions/building-blocks.instructions.md
  • packages/openbridge-webcomponents/src/building-blocks/instrument-linear/instrument-linear.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/draft-trim/draft-trim.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/draft-trim/draft-trim.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/openbridge-webcomponents/src/navigation-instruments/draft-trim/draft-trim.stories.ts
  • .github/instructions/building-blocks.instructions.md
  • packages/openbridge-webcomponents/src/navigation-instruments/draft-trim/draft-trim.ts

📝 Walkthrough

Walkthrough

Shared navigation-instrument rendering is expanded with reusable arrows and center readouts, configurable compass and heading displays, ROT track bars, linear ROT and speed-direction instruments, a propulsion gauge, propeller artwork, watch geometry support, additional instrument variants, and Storybook coverage.

Changes

Navigation instrument rendering

Layer / File(s) Summary
Shared rendering primitives
packages/openbridge-webcomponents/src/navigation-instruments/{course-arrows,readout,watch}/*, packages/openbridge-webcomponents/src/building-blocks/instrument-linear/*
Adds reusable arrows, center readouts, arc tickmarks, watch geometry controls, linear tick helpers, and advice resolution.
Compass and radial instrument integration
packages/openbridge-webcomponents/src/navigation-instruments/{compass,compass-sector,heading,compass-flat,pitch-roll,rate-of-turn}/*
Adds configurable arrows, center-readout rendering, responsive layouts, ROT track bars, and Storybook scenarios.
New instrument components and assets
packages/openbridge-webcomponents/src/navigation-instruments/{speed-directions,rot-linear,top-view-propulsion,pitch-roll-heave,draft-trim}/*
Adds speed-direction, linear ROT, propulsion, pitch-roll-heave, and draft-trim instruments with geometry, rendering, and stories.
Artwork and repository guidance
packages/openbridge-webcomponents/src/navigation-instruments/{speed-arrows,watch/propellers,watch/vessels}/*, .github/instructions/*, AGENTS.md
Adds reusable SVG artwork, propeller variants, vessel outline updates, documentation, and workflow guidance.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Instrument
  participant CenterReadoutResolver
  participant ArrowRenderer
  participant ObcWatch
  participant CenterReadoutRenderer
  Instrument->>CenterReadoutResolver: Resolve configured heading, course, and ROT entries
  CenterReadoutResolver->>CenterReadoutRenderer: Provide normalized values, sizes, and priorities
  Instrument->>ArrowRenderer: Render selected HDG and COG styles
  Instrument->>ObcWatch: Pass vessels, bars, needles, and center-cutout state
  CenterReadoutRenderer->>Instrument: Render centered readout cluster
Loading

Possibly related issues

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: tibnor

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: new radial instruments and additional instrument variations.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/compass-heading-center-content

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (6)
packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts (2)

368-373: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

.center-readout-overlay CSS duplicates compass.ts's rule verbatim.

Consider sharing this via centerReadoutStyles (see consolidated comment).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts`
around lines 368 - 373, Remove the duplicate .center-readout-overlay
declarations from heading.ts and reuse the shared centerReadoutStyles definition
already used by compass.ts. Ensure the heading component still applies the same
centered, non-interactive overlay styling through that shared style.

130-134: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

vesselImage's conditional visibility should use @availableWhen instead of prose.

Same pattern as compass.ts's vesselImage — visibility is gated by centerReadouts being empty but isn't expressed via @availableWhen (see consolidated comment).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts`
around lines 130 - 134, Update the heading instrument’s vesselImage
declaration/documentation to use the `@availableWhen` condition, matching
compass.ts, so visibility is explicitly gated on centerReadouts being empty
rather than described only in prose.

Source: Coding guidelines

packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts (4)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

vesselImage's dependency on centerReadouts should use @availableWhen, not prose. Both instruments document the same gating relationship (vessel hidden while centerReadouts is non-empty) as free-text instead of the repo's @availableWhen convention used elsewhere in these same classes.

  • packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts#L192-193: replace the prose note with @availableWhen centerReadouts.length==0 on the vesselImage JSDoc.
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts#L130-134: same annotation change on vesselImage's JSDoc.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts`
at line 1, Update the vesselImage JSDoc in both Compass and Heading to replace
the prose about centerReadouts gating with the repository-standard
`@availableWhen` centerReadouts.length==0 annotation, leaving the property
behavior unchanged.

Source: Coding guidelines


510-515: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

.center-readout-overlay CSS is duplicated verbatim with heading.ts.

Consider hoisting this rule into centerReadoutStyles in center-readout.ts so both instruments share one definition (see consolidated comment).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts`
around lines 510 - 515, Remove the duplicated .center-readout-overlay rule from
compass.ts and hoist the shared definition into centerReadoutStyles in
center-readout.ts. Preserve the existing flex centering and pointer-events
behavior so both compass and heading reuse the single style definition.

192-193: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

vesselImage's conditional visibility should use @availableWhen instead of prose.

Its rendering is gated by centerReadouts being empty; per repo convention this should be expressed as an @availableWhen tag on the dependent property rather than free text. Same issue exists in heading.ts (see consolidated comment).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts`
around lines 192 - 193, Update the vesselImage property in the compass component
to use the repository’s `@availableWhen` annotation expressing that it is
available only when centerReadouts is empty, and remove the equivalent
conditional-visibility prose from its documentation. Apply the same change to
the corresponding vesselImage property in heading.ts.

Source: Coding guidelines


1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate .center-readout-overlay CSS across compass.ts and heading.ts. Both instruments define the identical wrapper rule (display: flex; align-items: center; justify-content: center; pointer-events: none;) locally instead of sharing it.

  • packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts#L510-515: remove the local .center-readout-overlay rule once it's hoisted into centerReadoutStyles.
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts#L368-373: same removal, relying on the shared rule.
  • Add the shared .center-readout-overlay rule to centerReadoutStyles in packages/openbridge-webcomponents/src/navigation-instruments/readout/center-readout.ts so both consumers stay in sync going forward.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts`
at line 1, Move the shared .center-readout-overlay rule into centerReadoutStyles
in center-readout.ts, preserving its existing flex centering and pointer-events
declarations. Remove the duplicate local rule from the styles in Compass and
Heading so both components rely on the shared definition.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/superpowers/plans/2026-07-23-compass-heading-center-content.md`:
- Around line 197-201: Update the arrowhead SVG template in the withHead branch
to render open arrowheads: use no fill and apply colorName to the stroke while
preserving the existing border silhouette stroke, stroke width, and
vector-effect styling. Ensure the corresponding requirement at the later
arrowhead example uses the same open, stroked treatment.
- Line 551: Update the Step 3 documentation plan for the vesselImage prop so its
dependency on centerReadouts is captured through the approved machine-readable
availability mechanism; if the current `@availableWhen` grammar cannot represent
array emptiness, revise the grammar or documentation rule to support this
condition rather than relying only on prose. Preserve the existing
`@availableWhen` documentation for the setpoint family.
- Line 553: Update the Step 4 Stories metadata so the Storybook version tag uses
6.1 instead of 6.0, while preserving the existing autodocs tag and story
configuration.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts`:
- Around line 473-484: Update the ROT value supplied in the center-readout
resolution within the compass render template to use the same effective
rate-of-turn value as the bar/dot visualization, including the deprecated
rotationsPerMinute fallback. Keep the other readout inputs and priority handling
unchanged.

---

Nitpick comments:
In
`@packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts`:
- Line 1: Update the vesselImage JSDoc in both Compass and Heading to replace
the prose about centerReadouts gating with the repository-standard
`@availableWhen` centerReadouts.length==0 annotation, leaving the property
behavior unchanged.
- Around line 510-515: Remove the duplicated .center-readout-overlay rule from
compass.ts and hoist the shared definition into centerReadoutStyles in
center-readout.ts. Preserve the existing flex centering and pointer-events
behavior so both compass and heading reuse the single style definition.
- Around line 192-193: Update the vesselImage property in the compass component
to use the repository’s `@availableWhen` annotation expressing that it is
available only when centerReadouts is empty, and remove the equivalent
conditional-visibility prose from its documentation. Apply the same change to
the corresponding vesselImage property in heading.ts.
- Line 1: Move the shared .center-readout-overlay rule into centerReadoutStyles
in center-readout.ts, preserving its existing flex centering and pointer-events
declarations. Remove the duplicate local rule from the styles in Compass and
Heading so both components rely on the shared definition.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts`:
- Around line 368-373: Remove the duplicate .center-readout-overlay declarations
from heading.ts and reuse the shared centerReadoutStyles definition already used
by compass.ts. Ensure the heading component still applies the same centered,
non-interactive overlay styling through that shared style.
- Around line 130-134: Update the heading instrument’s vesselImage
declaration/documentation to use the `@availableWhen` condition, matching
compass.ts, so visibility is explicitly gated on centerReadouts being empty
rather than described only in prose.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7b8cb0e4-06a5-4646-affe-4c7fd6f84e94

📥 Commits

Reviewing files that changed from the base of the PR and between 5c94459 and 9252faf.

⛔ Files ignored due to path filters (12)
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/map-graphics-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-center-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-cog-arrow-styles-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-hdg-arrow-styles-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-primary-secondary-readouts-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-three-readouts-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-two-primary-readouts-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-center-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-vector-arrows-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-vessel-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-with-readout-auto.png is excluded by !**/*.png
📒 Files selected for processing (15)
  • docs/superpowers/plans/2026-07-23-compass-heading-center-content.md
  • docs/superpowers/specs/2026-07-23-compass-heading-center-content-design.md
  • packages/openbridge-webcomponents/src/navigation-instruments/compass-sector/compass-sector.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/compass/arrow.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/course-arrows/course-arrows-art.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/course-arrows/course-arrows.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/arrow.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/pitch-roll/pitch-roll.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/readout/center-readout.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/vessel.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/vessels/psv-top-ccrp.ts

Comment thread docs/superpowers/plans/2026-07-23-compass-heading-center-content.md Outdated
Comment thread docs/superpowers/plans/2026-07-23-compass-heading-center-content.md Outdated
Comment thread docs/superpowers/plans/2026-07-23-compass-heading-center-content.md Outdated
talpitoo added a commit that referenced this pull request Jul 23, 2026
Story-level tags merge with the file meta, so the components stay in the
6.0 documentation set while the new variations are filterable as 6.1.
Addresses CodeRabbit review feedback on PR #1058.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.ts`:
- Around line 152-166: Update the zero-rotation branch of trackNeedleColor so it
falls through to the existing priority-based enhanced/regular color selection,
matching trackBarColor and getRotColors(). Preserve the port/starboard colors
for positive and negative rotation values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d348d23c-53f0-4695-9014-d788cfe0d38c

📥 Commits

Reviewing files that changed from the base of the PR and between 7ae11b8 and cbecb10.

⛔ Files ignored due to path filters (4)
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-port-starboard-auto.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/watch.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.ts (1)

19-50: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Complete the component guidance.

Add a Best Practices section and document priority’s supported values/default behavior alongside the existing configuration guidance. As per coding guidelines, component JSDoc must include practical best practices and important property defaults/enum behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.ts`
around lines 19 - 50, Update the <obc-rot-linear> component JSDoc to add a Best
Practices section with practical usage guidance, and document the supported
values and default behavior of the priority property alongside the existing
configuration guidance. Keep the documentation consistent with the component’s
actual priority API and other documented defaults.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/instructions/watch-radial-instruments.instructions.md:
- Line 2: Expand the applyTo scope in the instruction metadata to include the
documented consumer directories, particularly
packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/** and
packages/openbridge-webcomponents/src/navigation-instruments/readout/**, along
with compass-sector, pitch-roll, compass-flat, and watch-flat. Preserve all
existing paths.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts`:
- Around line 192-195: Remove the unsupported `@availableWhen` annotation from the
vessel image documentation near centerReadouts, while retaining the prose
stating that the image is hidden when centerReadouts is non-empty. Do not
replace it with another availability expression.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.ts`:
- Line 60: Update rotMaxValue in the rot-linear component so Infinity and other
non-finite or non-positive values are replaced with a finite positive bound
before scale geometry and tick generation use it. Ensure value initialization
and scaleTickmarks both consume the guarded value, preventing non-advancing
loops while preserving normal finite positive configurations.

---

Nitpick comments:
In
`@packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.ts`:
- Around line 19-50: Update the <obc-rot-linear> component JSDoc to add a Best
Practices section with practical usage guidance, and document the supported
values and default behavior of the priority property alongside the existing
configuration guidance. Keep the documentation consistent with the component’s
actual priority API and other documented defaults.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ef7c9736-f48e-49b0-a179-1455dd0b13c6

📥 Commits

Reviewing files that changed from the base of the PR and between 7ae11b8 and cc570ef.

⛔ Files ignored due to path filters (10)
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-port-starboard-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/default-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/port-starboard-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/port-starboard-port-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/with-readout-enhanced-auto.png is excluded by !**/*.png
📒 Files selected for processing (12)
  • .github/instructions/watch-radial-instruments.instructions.md
  • AGENTS.md
  • packages/openbridge-webcomponents/src/navigation-instruments/compass-flat/compass-flat.css
  • packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.css
  • packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch-flat/watch-flat.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/watch.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/openbridge-webcomponents/src/navigation-instruments/compass-flat/compass-flat.css
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/watch.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts

Comment thread .github/instructions/watch-radial-instruments.instructions.md Outdated
talpitoo and others added 20 commits July 27, 2026 09:04
Verified against Figma OpenBridge 6.1 (center-label arrangements, HDG/COG
arrow style sets, heading type set, CCRP vessel). Records the obc-readout
closest-API reuse rule and the zoomToFitArc / compass-sector impact analysis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ed readout helper

User-approved: same-pass migration with small intentional snapshot diffs;
helper takes resolved entries so it is source-agnostic. PR body will be a
condensed version of the spec.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…acy arrow shims

Moves the compass arrow-head art and heading needle art verbatim into
course-arrows.ts (HdgArrowStyle/CogArrowStyle); compass/arrow.ts and
heading/arrow.ts become deprecated delegating shims so compass-sector's
radiusOffset call path is untouched. Visual suites pass with zero diffs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…yles

Art generated from the Figma OpenBridge 6.1 variant nodes (18306:91621/
91630/91650/91656) into course-arrows-art.ts; state color parameterized,
silhouette mapped to --border-silhouette-color, mask ids made descriptive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Public API unchanged. Intentional baseline update: the cluster gains the
Figma-accurate 8px gaps around the divider; all non-readout stories are
pixel-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Public API and top-% positioning unchanged; visual suite passes with zero
baseline diffs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hull offset within the 160 box so the rotation pivot sits on the CCRP;
exported from Figma node 208:29931, colors mapped to the psv-top tokens.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ponent

Adds vesselImage (double-band face while center content shows),
centerReadouts (source-bound cluster via the shared helper), and
hdgArrowStyle/cogArrowStyle (defaults keep today's needles). Class JSDoc
brought to the compass standard; stories gain autodocs and three new
snapshot stories. Existing heading baselines unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds centerReadouts (source-bound cluster replacing the vessel),
hdgArrowStyle/cogArrowStyle (defaults keep today's ring arrowheads), the
four center-label story arrangements, the MapGraphics story recipe and
per-style showcase stories. Existing compass baselines unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Plans are working documents and are not committed; the spec remains as the
reviewed design record.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Specs and plans are working documents and are not committed; the condensed
design record lives in the PR description.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…CRP asset

New vessel images should arrive via the convert-vessel-svg-to-ts pipeline
from designer exports; the CCRP variant is deferred to its own PR. Leaves
watch/vessel.ts untouched by this branch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Story-level tags merge with the file meta, so the components stay in the
6.0 documentation set while the new variations are filterable as 6.1.
Addresses CodeRabbit review feedback on PR #1058.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Readout rendered below the strip via the shared center-readout helper,
compass-sector-compatible API; default rendering unchanged (existing
stories zero-diff).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Track bar composes existing watch inputs (barAreas + needles + sector
tickmarks) on the double-band face; colors mirror rot-sector's
port/starboard and priority logic. Readout via the shared center-readout
helper (physical value only). renderBars now applies the area cut mask
only when areas exist, so band bars render reliably on full-circle faces
(zero-diff for all existing consumers, 199 tests across the radial family).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
watch-flat gains additive band bar/needle options (linear analogues of the
radial barAreas/needles, default off — compass-flat pixel-identical);
obc-rot-linear is a thin wrapper with numeric scale, center-growing bar,
end needle, port/starboard and priority coloring, and the bottom readout.
Also makes the flat hosts' grid rows definite so percent heights resolve
(fixes the readout being pushed below short hosts).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…shared-module map

Extends the @availableWhen grammar with `arr==[]` / `arr!=[]` and annotates
vesselImage on compass/heading accordingly; fixes the baseline-update
command (filter must precede --update); documents the analyze-before-
new-component-stories requirement; adds course-arrows, center-readout and
the rate-of-turn track-bar recipe to the watch-radial instructions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nstruction scope

Addresses CodeRabbit review: a non-finite or non-positive rotMaxValue no
longer freezes tick generation (falls back to the default range), and the
watch-radial instructions applyTo now covers every consumer the file
documents (compass-sector, pitch-roll, readout, flat family, rot-linear).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
talpitoo and others added 4 commits July 27, 2026 15:20
Watch-face propulsion gauge: signed-percent power arc on the inner track (barAreas + needles per the rate-of-turn track-bar recipe), thick tinted zero line, SetpointBundle-driven power setpoint, loading progress arc on the outer ring, interchangeable center propeller from the new PropellerImage registry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
rpm reuses the primary-track rendering with its own SetpointBundle; pitch renders as a thin secondary arc at the track's inner edge with a zero mark and end nub. Primary-axis setpoint marker follows power or rpm by type.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ver secondary track

Per design review: the secondary indicator is a plain arc line (butt cap at zero, rounded tip at the value) over a thin gray secondary track circle - no bar-style end nubs. Zero mark only while the arc is absent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d pitch lane

Per design correction: in pitch-rpm the 112..160 band splits into the primary sub-band (128..160) carrying the rpm fill and a shorter needle, a white divider ring (120..128, Figma 264-diameter outer edge), and an 8px secondary lane (112..120) holding the pitch line at the band's inner edge. Adds additive snapshot-neutral knobs to obc-watch: optional WatchBarArea.outerRadius/innerRadius and WatchNeedle.length (all 8 barAreas/needles consumer suites verified unchanged).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
packages/openbridge-webcomponents/src/navigation-instruments/top-view-propulsion/top-view-propulsion.ts (1)

50-66: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a small spec for these geometry helpers
Cover percentToAngle clamping/sign behavior and arcPath’s large-arc/sweep flags.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/top-view-propulsion/top-view-propulsion.ts`
around lines 50 - 66, Add focused tests for the geometry helpers percentToAngle
and arcPath. Verify percentToAngle converts signs correctly, clamps values
outside -100 through 100, and handles non-finite input; verify arcPath emits the
expected large-arc and sweep flags for representative angle ranges.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/openbridge-webcomponents/src/navigation-instruments/speed-arrows/speed-arrows-art.ts`:
- Around line 3-7: Expand the module-level JSDoc in the speed-arrows art module
to document its 96x96 coordinate contract, the obc-speed-arrows and
obc-speed-directions consumers, and how renderChevronBand() uses the exported
paths, while retaining the existing CHEVRON_PATHS description.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions-geometry.ts`:
- Around line 67-96: Update the longLatArrows standalone entry in CELL_TABLE so
its athwartRowY value is 0, matching the documented athwartMid invariant and the
inFrame configuration. Leave the other geometry values unchanged.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/top-view-propulsion/top-view-propulsion.ts`:
- Around line 92-99: Update all nine `@availableWhen` annotations in the
TopViewPropulsion property block to compare type against the serialized value
"pitch-rpm" rather than the TypeScript enum member name pitchRpm; leave the
existing type==power annotation unchanged.

---

Nitpick comments:
In
`@packages/openbridge-webcomponents/src/navigation-instruments/top-view-propulsion/top-view-propulsion.ts`:
- Around line 50-66: Add focused tests for the geometry helpers percentToAngle
and arcPath. Verify percentToAngle converts signs correctly, clamps values
outside -100 through 100, and handles non-finite input; verify arcPath emits the
expected large-arc and sweep flags for representative angle ranges.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fe90c2c5-ea66-41f4-97d0-64a0f4d53b58

📥 Commits

Reviewing files that changed from the base of the PR and between cc570ef and 4e7f391.

⛔ Files ignored due to path filters (54)
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/ar/chart-object-vessel-button/chart-object-vessel-button.stories.ts/cross-line-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass-flat/compass-flat.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/map-graphics-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-center-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-cog-arrow-styles-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-hdg-arrow-styles-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-primary-secondary-readouts-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-three-readouts-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-two-primary-readouts-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-center-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-vector-arrows-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-vessel-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-port-starboard-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/default-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/port-starboard-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/port-starboard-port-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/with-readout-enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-arrows-compass-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-arrows-framed-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-arrows-standalone-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-bars-compass-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-bars-framed-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-bars-standalone-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/bars-max-clamped-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/long-lat-arrows-compass-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/long-lat-arrows-framed-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/long-lat-arrows-standalone-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/negative-speeds-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/partial-axes--undefined-hidden--auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/zero-speed-tinted-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/pitch-rpm-at-setpoint-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/pitch-rpm-negative-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/pitch-rpm-off-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/pitch-rpm-regular-priority-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-at-setpoint-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-input-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-loading-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-negative-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-not-at-setpoint-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-off-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-ready-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-regular-priority-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/propellers-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/wind/wind.stories.ts/auto-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/wind/wind.stories.ts/large-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/wind/wind.stories.ts/medium-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/wind/wind.stories.ts/primary-auto.png is excluded by !**/*.png
📒 Files selected for processing (45)
  • .github/instructions/watch-radial-instruments.instructions.md
  • AGENTS.md
  • packages/openbridge-webcomponents/src/navigation-instruments/compass-flat/compass-flat.css
  • packages/openbridge-webcomponents/src/navigation-instruments/compass-flat/compass-flat.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/compass-flat/compass-flat.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/compass-sector/compass-sector.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/compass/arrow.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/course-arrows/course-arrows-art.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/course-arrows/course-arrows.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/arrow.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/pitch-roll/pitch-roll.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/readout/center-readout.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.css
  • packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/speed-arrows/speed-arrows-art.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/speed-arrows/speed-arrows.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions-art.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions-geometry.spec.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions-geometry.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions.css
  • packages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/top-view-propulsion/top-view-propulsion.css
  • packages/openbridge-webcomponents/src/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/top-view-propulsion/top-view-propulsion.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch-flat/watch-flat.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/propeller.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/cap-five-blade.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/five-blade.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/four-blade.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/shaftless-five-blade.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/shaftless-seven-blade.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/six-blade.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/storybook-helper.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/three-blade.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/vsp-seven-blade.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/vessels/generic-top.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/watch.ts
🚧 Files skipped from review as they are similar to previous changes (18)
  • packages/openbridge-webcomponents/src/navigation-instruments/compass-flat/compass-flat.css
  • packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.css
  • packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/readout/center-readout.ts
  • AGENTS.md
  • packages/openbridge-webcomponents/src/navigation-instruments/compass-flat/compass-flat.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/arrow.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/compass-sector/compass-sector.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/compass/arrow.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/course-arrows/course-arrows-art.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/pitch-roll/pitch-roll.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/compass/compass.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/course-arrows/course-arrows.ts

…ilableWhen values

Module-level JSDoc for the pure-function chevron module; correct the stale athwartRowY field doc and lock the standalone midship offset with a spec assertion; use the serialized 'pitch-rpm' value in availableWhen conditions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
talpitoo and others added 5 commits July 28, 2026 09:12
Adds `arcTickmarks(centerAngle, halfExtent, interval = 5)` to tickmark.ts:
the `secondary` ladder that runs along an arc band, skipping the arc centre
(which carries its own `main` mark) and the ends, where the band's rounded
end cap already reads as a boundary.

Measured from the Figma watch face: secondary ticks every 5°, radial extent
164→172, no primary ticks. Wired into `single-axis-inclinometer`
(obc-pitch, obc-roll) and both `obc-pitch-roll` render paths. The zoomed
path passes the CLAMPED half-extent, not the requested one, so ticks cannot
fall outside the band that is actually drawn.

Baselines regenerated for pitch (6), roll (7) and pitch-roll (8).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`renderCenterReadouts()` gains an optional `CenterReadoutArrangement`:

- `primarySecondary` (default, unchanged): first entry, one divider, then
  the remaining entries side by side.
- `stacked` (new): every entry on its own row with a divider between each
  pair — the Pitch/Roll/Heave column in the Figma pitch-roll-heave readout
  variant.

The default is unchanged, so compass, heading, compass-sector, pitch-roll,
rate-of-turn, compass-flat and rot-linear keep their current output and
baselines.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds `ObcHeaveType` (`vessel` | `bar`). `bar` drops the frame, reference
line and vessel silhouette and switches the viewBox to the Figma 128x384
frame with the 72-unit scale column centred; `watchfaceLinear()` is called
with unchanged arguments, so the tick pattern matches the standalone
design (primary every 5, secondary every 1, main line at 0).

`vessel` stays the default and renders identically — its three baselines
pass untouched. `vesselImage`, `gainScale` and `draftOffset` are annotated
`@availableWhen type==vessel`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Pitch arc, roll arc and a linear heave column on one watch face
(Figma node 19160-296360). `single-scale` puts pitch right, roll bottom
and heave in the left band slot with the tick lane facing outward;
`dual-scale` mirrors both arcs and moves the column to the centre.
`hasReadout` swaps the vessels for stacked Pitch/Roll/Heave readouts.

The column is not sized independently — its dimensions fall out of the arc
geometry:

    width  = band thickness
    height = 2 * capRadius * sin(pitchArcAngle)

which yields Figma's 184 at the defaults and keeps the column's edges level
with the pitch arc's end caps. Every other boundary follows from the two
half-extents: both diagonal gaps are 90 - pitch - roll (15° at the
defaults) and the complement ring spans [270+pitch, 90-pitch].

The column is built from `watchfaceLinear()` — the same building block
`obc-heave` uses — rather than by embedding the element, whose fixed
box/gauge widths and viewBox would all have to become configurable.

Adds `linearTickInterval(height, range, minSpacing = 16)` to
instrument-linear.ts, which picks a 1-2-5 tick step by on-screen spacing so
a linear scale keeps a readable density when its height is dictated by the
surrounding layout. It independently reproduces the intervals `obc-heave`
hard-codes at its natural 336-unit height, which is what fixes the
constant; obc-heave keeps its literals so its baselines do not move.

Two details differ from the un-zoomed design and are deliberate:

- The crosshair is drawn on the under-watch overlay rather than through
  `obc-watch`'s `crosshairEnabled`, because the design has the arc bands
  covering the arms while obc-watch renders its crosshair after the bands.
- Under zoom, roll-vs-column clearance uses point-to-rectangle distance,
  not the corner-to-corner `signedDist` used between two arcs: a corner can
  clear a rectangle on one axis alone, and `signedDist` would score -12.8
  for a pair that is actually 32.8 apart. `dual-scale` clamps the centred
  column's height only, never its width, which reads as a match for the
  band thickness. Both rules are no-ops at the un-zoomed defaults.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ules

- Scope extended to pitch/**, pitch-roll-heave/** and the
  single-axis-inclinometer building block.
- Documents the pitch-roll-heave geometry contract: the derived heave
  column size, the table of angular spans that follow from the two
  half-extents, and the three zoom-only clearance rules (all no-ops at the
  un-zoomed defaults, which is what reproduces the design — verify that
  before retuning their constants).
- Shared-module map gains `arcTickmarks`, `linearTickInterval` and the two
  center-readout arrangements, and notes that `primarySecondary` must stay
  the default.
- Component quick reference gains pitch/roll, pitch-roll and
  pitch-roll-heave.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@talpitoo talpitoo changed the title feat(instruments): compass & heading center readouts, arrow styles and map graphics feat(instruments): new radial instruments and new variations Jul 28, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/openbridge-webcomponents/src/building-blocks/single-axis-inclinometer/single-axis-inclinometer.ts (1)

239-239: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider a single normalized arc-angle accessor.

normalizeArcAngle(this.arcAngle, 45) is now recomputed in render() (Line 156), renderScale (Line 239) and advices (Line 280). Since the areas, the tick ladder and the caution clamp must agree on the same extent, a protected get normalizedArcAngle() would keep them in sync.

♻️ Suggested extraction
-    const arcAngle = normalizeArcAngle(this.arcAngle, 45);
+    const arcAngle = this.normalizedArcAngle;

Add alongside the other protected accessors:

protected get normalizedArcAngle(): number {
  return normalizeArcAngle(this.arcAngle, 45);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/openbridge-webcomponents/src/building-blocks/single-axis-inclinometer/single-axis-inclinometer.ts`
at line 239, Extract the repeated normalizeArcAngle(this.arcAngle, 45) logic
into a protected normalizedArcAngle accessor, then update render(),
renderScale(), and advices to use it so all geometry and caution calculations
share the same normalized extent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/instructions/watch-radial-instruments.instructions.md:
- Line 2: Update the applyTo glob in the watch-radial instruments instructions
to include
packages/openbridge-webcomponents/src/building-blocks/instrument-linear/**,
ensuring the documented instrument-linear module and its linearTickInterval
contracts are covered.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/pitch-roll/pitch-roll.ts`:
- Line 13: Update renderCenterReadouts() in the pitch-roll instrument to import
CenterReadoutArrangement and explicitly pass CenterReadoutArrangement.stacked,
preserving the documented pitch-above-roll layout instead of the default
primarySecondary arrangement.

---

Nitpick comments:
In
`@packages/openbridge-webcomponents/src/building-blocks/single-axis-inclinometer/single-axis-inclinometer.ts`:
- Line 239: Extract the repeated normalizeArcAngle(this.arcAngle, 45) logic into
a protected normalizedArcAngle accessor, then update render(), renderScale(),
and advices to use it so all geometry and caution calculations share the same
normalized extent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6b63671d-81a2-4e76-8a0a-1440df0c85b1

📥 Commits

Reviewing files that changed from the base of the PR and between 0e6cf97 and 8c6da40.

⛔ Files ignored due to path filters (34)
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heave/heave.stories.ts/bar-advice-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heave/heave.stories.ts/bar-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heave/heave.stories.ts/bar-enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/advice-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/dual-scale-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/dual-scale-enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/primary-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/with-readout-enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/zoomed-in-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/zoomed-in-dual-scale-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/zoomed-in-narrow-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/primary-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/rov-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/scaled-fore-image-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-narrow-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-rectangular-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/dual-scale-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/primary-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/zoomed-in-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/zoomed-in-narrow-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/dual-scale-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/primary-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/rov-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/with-readout-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/zoomed-in-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/zoomed-in-narrow-auto.png is excluded by !**/*.png
📒 Files selected for processing (11)
  • .github/instructions/watch-radial-instruments.instructions.md
  • packages/openbridge-webcomponents/src/building-blocks/instrument-linear/instrument-linear.spec.ts
  • packages/openbridge-webcomponents/src/building-blocks/instrument-linear/instrument-linear.ts
  • packages/openbridge-webcomponents/src/building-blocks/single-axis-inclinometer/single-axis-inclinometer.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heave/heave.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heave/heave.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/pitch-roll/pitch-roll.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/readout/center-readout.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/watch/tickmark.ts

Comment thread .github/instructions/watch-radial-instruments.instructions.md
talpitoo and others added 2 commits July 28, 2026 09:40
Extracts the parts `obc-heave` and the new `obc-draft-trim` genuinely
duplicate, rather than forcing their differing layouts into one abstraction:

- `resolveLinearAdvice(advice, trendMin, trendMax)` — the hinted/regular/
  triggered mapping, moved out of `obc-heave`.
- `verticalScaleTickmarks(range)` — the tick configuration for a scale
  spanning ±range around a zero reference.
- `watchfaceLinear` gains `options.maskId`. The container clip mask id was
  hard-coded to `boxMask`; ids are document-scoped, so a component drawing
  two gauges in one shadow root had both resolving to the first one's mask.
  It happened to be harmless only because both masks were identical.

`obc-heave` now uses the first two. All behaviour-preserving: heave, thruster
and main-engine baselines pass unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Draught at the bow and the stern on two vertical scales either side of a
vessel side view (Figma node 20122-231157), each filled from the waterline
down to its measured value; the difference between the two is the trim.
Marked `@experimental` (`wip` story tag).

Reuses `obc-heave`'s scale wholesale — same 72-unit column at the same
±132 offset, same 336-unit height, same tick configuration — with the aft
column mirrored so its tick lane faces outward. The centre panel adds the
waterline, the water fill below it and the vessel silhouette.

The vessel is a static reference and does not pitch with the trim: the
Figma variants show a level vessel while the two scales differ (5 m aft,
2.5 m fore), so the values are carried by the scales alone.

Scales run positive-up, so draughts — measured downward from the
waterline — are negated. Advice bounds are given in the same
positive-below-waterline units and are negated AND swapped, since
negating an interval reverses it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/openbridge-webcomponents/src/building-blocks/instrument-linear/instrument-linear.ts`:
- Around line 202-205: Update the verticalScaleTickmarks documentation in
packages/openbridge-webcomponents/src/building-blocks/instrument-linear/instrument-linear.ts
lines 202-205 to describe 1/0.5 intervals for ranges <=5 and 5/1 intervals
otherwise, while retaining the zero reference line and ±range context. Mirror
this branch-specific contract in
.github/instructions/building-blocks.instructions.md lines 118-133.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/draft-trim/draft-trim.stories.ts`:
- Around line 34-36: Rename the `Regular` story export to `Default` in the
draft-trim stories file, preserving its existing default args and story
configuration.
- Around line 62-65: Remove the negative advice entry from the advice
configuration in the draft-trim story, leaving only the documented
positive-below-waterline zone. Do not change ObcDraftTrim’s contract or
transformation unless two-sided advice is explicitly intended.
- Around line 9-12: Update the tags in the ObcDraftTrim Storybook meta to use
the supported experimental set ['alpha']; remove the unsupported 'autodocs',
'6.0', and 'wip' tags.

In
`@packages/openbridge-webcomponents/src/navigation-instruments/draft-trim/draft-trim.ts`:
- Around line 30-42: Expand the class-level JSDoc for the draft-trim component
with sections covering features/variants, usage guidance and use cases,
slots/content, and best practices. Keep the final tag block limited to actual
`@slot` and `@fires/`@event tags, documenting that this component has none rather
than inventing entries; update the documentation associated with the
obc-draft-trim class only.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6b40f0ca-05fa-4f7b-aece-1135026bb630

📥 Commits

Reviewing files that changed from the base of the PR and between 8c6da40 and 0079a72.

⛔ Files ignored due to path filters (5)
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/draft-trim/draft-trim.stories.ts/advice-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/draft-trim/draft-trim.stories.ts/enhanced-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/draft-trim/draft-trim.stories.ts/even-keel-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/draft-trim/draft-trim.stories.ts/regular-auto.png is excluded by !**/*.png
  • packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/draft-trim/draft-trim.stories.ts/trim-by-bow-auto.png is excluded by !**/*.png
📒 Files selected for processing (6)
  • .github/instructions/building-blocks.instructions.md
  • packages/openbridge-webcomponents/src/building-blocks/instrument-linear/advice.ts
  • packages/openbridge-webcomponents/src/building-blocks/instrument-linear/instrument-linear.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/draft-trim/draft-trim.stories.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/draft-trim/draft-trim.ts
  • packages/openbridge-webcomponents/src/navigation-instruments/heave/heave.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/openbridge-webcomponents/src/navigation-instruments/heave/heave.ts

- `verticalScaleTickmarks` documented halves/tenths, which only holds at
  range 10; describe the actual branch (1/0.5 at ≤5, 5/1 above) in both the
  helper JSDoc and the building-blocks instructions.
- Rename the `Regular` story to `Default` per the component checklist in
  AGENTS.md § 5 and IMPLEMENTATION_GUIDELINES.md.
- Expand the `obc-draft-trim` class JSDoc with the features and usage
  sections the JSDoc rules require. No `@slot`/`@fires` tags: the component
  renders no slots and dispatches no events.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@talpitoo
talpitoo merged commit ac780e2 into develop Jul 29, 2026
11 checks passed
@talpitoo
talpitoo deleted the feat/compass-heading-center-content branch July 29, 2026 09:42
openbridge-release-bot Bot pushed a commit that referenced this pull request Jul 29, 2026
## [2.0.0-next.105](v2.0.0-next.104...v2.0.0-next.105) (2026-07-29)

### Features

* **instruments:** new radial instruments and new variations ([#1058](#1058)) ([ac780e2](ac780e2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🟩 Maintenance/Address-update fine-details of circular instruments 🧭

2 participants