feat(instruments): new radial instruments and new variations - #1058
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughShared 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. ChangesNavigation instrument rendering
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
Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
The demo can be viewed at https://openbridge-next-demo--1058-feat-instruments-new-radial-lexji7lu.web.app |
|
The storybook can be viewed at https://openbridge-next-storybook--1058-feat-instruments-new-r-1cic8w5g.web.app |
There was a problem hiding this comment.
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-overlayCSS duplicatescompass.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@availableWheninstead of prose.Same pattern as
compass.ts'svesselImage— visibility is gated bycenterReadoutsbeing 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 oncenterReadoutsshould use@availableWhen, not prose. Both instruments document the same gating relationship (vessel hidden whilecenterReadoutsis non-empty) as free-text instead of the repo's@availableWhenconvention 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==0on thevesselImageJSDoc.packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts#L130-134: same annotation change onvesselImage'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-overlayCSS is duplicated verbatim withheading.ts.Consider hoisting this rule into
centerReadoutStylesincenter-readout.tsso 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@availableWheninstead of prose.Its rendering is gated by
centerReadoutsbeing empty; per repo convention this should be expressed as an@availableWhentag on the dependent property rather than free text. Same issue exists inheading.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 winDuplicate
.center-readout-overlayCSS acrosscompass.tsandheading.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-overlayrule once it's hoisted intocenterReadoutStyles.packages/openbridge-webcomponents/src/navigation-instruments/heading/heading.ts#L368-373: same removal, relying on the shared rule.- Add the shared
.center-readout-overlayrule tocenterReadoutStylesinpackages/openbridge-webcomponents/src/navigation-instruments/readout/center-readout.tsso 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
⛔ Files ignored due to path filters (12)
packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/map-graphics-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-center-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-cog-arrow-styles-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-hdg-arrow-styles-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-primary-secondary-readouts-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-three-readouts-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-two-primary-readouts-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-center-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-vector-arrows-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-vessel-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-with-readout-auto.pngis excluded by!**/*.png
📒 Files selected for processing (15)
docs/superpowers/plans/2026-07-23-compass-heading-center-content.mddocs/superpowers/specs/2026-07-23-compass-heading-center-content-design.mdpackages/openbridge-webcomponents/src/navigation-instruments/compass-sector/compass-sector.tspackages/openbridge-webcomponents/src/navigation-instruments/compass/arrow.tspackages/openbridge-webcomponents/src/navigation-instruments/compass/compass.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/compass/compass.tspackages/openbridge-webcomponents/src/navigation-instruments/course-arrows/course-arrows-art.tspackages/openbridge-webcomponents/src/navigation-instruments/course-arrows/course-arrows.tspackages/openbridge-webcomponents/src/navigation-instruments/heading/arrow.tspackages/openbridge-webcomponents/src/navigation-instruments/heading/heading.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/heading/heading.tspackages/openbridge-webcomponents/src/navigation-instruments/pitch-roll/pitch-roll.tspackages/openbridge-webcomponents/src/navigation-instruments/readout/center-readout.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/vessel.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/vessels/psv-top-ccrp.ts
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>
There was a problem hiding this comment.
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
⛔ 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.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-port-starboard-auto.pngis excluded by!**/*.png
📒 Files selected for processing (3)
packages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/watch.ts
There was a problem hiding this comment.
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 winComplete 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
⛔ 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.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-port-starboard-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/default-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/port-starboard-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/port-starboard-port-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/with-readout-enhanced-auto.pngis excluded by!**/*.png
📒 Files selected for processing (12)
.github/instructions/watch-radial-instruments.instructions.mdAGENTS.mdpackages/openbridge-webcomponents/src/navigation-instruments/compass-flat/compass-flat.csspackages/openbridge-webcomponents/src/navigation-instruments/compass/compass.tspackages/openbridge-webcomponents/src/navigation-instruments/heading/heading.tspackages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.tspackages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.csspackages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.tspackages/openbridge-webcomponents/src/navigation-instruments/watch-flat/watch-flat.tspackages/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
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>
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>
There was a problem hiding this comment.
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 winAdd a small spec for these geometry helpers
CoverpercentToAngleclamping/sign behavior andarcPath’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
⛔ 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.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass-flat/compass-flat.stories.ts/with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/map-graphics-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-center-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-cog-arrow-styles-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-hdg-arrow-styles-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-primary-secondary-readouts-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-three-readouts-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/compass/compass.stories.ts/with-two-primary-readouts-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-center-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-vector-arrows-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heading/heading.stories.ts/with-vessel-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rate-of-turn/rate-of-turn.stories.ts/with-track-bar-port-starboard-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/default-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/port-starboard-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/port-starboard-port-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/rot-linear/rot-linear.stories.ts/with-readout-enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-arrows-compass-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-arrows-framed-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-arrows-standalone-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-bars-compass-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-bars-framed-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/along-athwart-bars-standalone-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/bars-max-clamped-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/long-lat-arrows-compass-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/long-lat-arrows-framed-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/long-lat-arrows-standalone-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/negative-speeds-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/partial-axes--undefined-hidden--auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/speed-directions/speed-directions.stories.ts/zero-speed-tinted-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/pitch-rpm-at-setpoint-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/pitch-rpm-negative-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/pitch-rpm-off-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/pitch-rpm-regular-priority-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-at-setpoint-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-input-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-loading-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-negative-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-not-at-setpoint-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-off-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-ready-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/power-regular-priority-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.ts/propellers-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/wind/wind.stories.ts/auto-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/wind/wind.stories.ts/large-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/wind/wind.stories.ts/medium-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/wind/wind.stories.ts/primary-auto.pngis excluded by!**/*.png
📒 Files selected for processing (45)
.github/instructions/watch-radial-instruments.instructions.mdAGENTS.mdpackages/openbridge-webcomponents/src/navigation-instruments/compass-flat/compass-flat.csspackages/openbridge-webcomponents/src/navigation-instruments/compass-flat/compass-flat.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/compass-flat/compass-flat.tspackages/openbridge-webcomponents/src/navigation-instruments/compass-sector/compass-sector.tspackages/openbridge-webcomponents/src/navigation-instruments/compass/arrow.tspackages/openbridge-webcomponents/src/navigation-instruments/compass/compass.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/compass/compass.tspackages/openbridge-webcomponents/src/navigation-instruments/course-arrows/course-arrows-art.tspackages/openbridge-webcomponents/src/navigation-instruments/course-arrows/course-arrows.tspackages/openbridge-webcomponents/src/navigation-instruments/heading/arrow.tspackages/openbridge-webcomponents/src/navigation-instruments/heading/heading.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/heading/heading.tspackages/openbridge-webcomponents/src/navigation-instruments/pitch-roll/pitch-roll.tspackages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/rate-of-turn/rate-of-turn.tspackages/openbridge-webcomponents/src/navigation-instruments/readout/center-readout.tspackages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.csspackages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/rot-linear/rot-linear.tspackages/openbridge-webcomponents/src/navigation-instruments/speed-arrows/speed-arrows-art.tspackages/openbridge-webcomponents/src/navigation-instruments/speed-arrows/speed-arrows.tspackages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions-art.tspackages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions-geometry.spec.tspackages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions-geometry.tspackages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions.csspackages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/speed-directions/speed-directions.tspackages/openbridge-webcomponents/src/navigation-instruments/top-view-propulsion/top-view-propulsion.csspackages/openbridge-webcomponents/src/navigation-instruments/top-view-propulsion/top-view-propulsion.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/top-view-propulsion/top-view-propulsion.tspackages/openbridge-webcomponents/src/navigation-instruments/watch-flat/watch-flat.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/propeller.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/cap-five-blade.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/five-blade.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/four-blade.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/shaftless-five-blade.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/shaftless-seven-blade.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/six-blade.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/storybook-helper.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/three-blade.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/propellers/vsp-seven-blade.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/vessels/generic-top.tspackages/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>
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>
There was a problem hiding this comment.
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 valueConsider a single normalized arc-angle accessor.
normalizeArcAngle(this.arcAngle, 45)is now recomputed inrender()(Line 156),renderScale(Line 239) andadvices(Line 280). Since the areas, the tick ladder and the caution clamp must agree on the same extent, aprotected 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
⛔ Files ignored due to path filters (34)
packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heave/heave.stories.ts/bar-advice-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heave/heave.stories.ts/bar-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/heave/heave.stories.ts/bar-enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/advice-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/dual-scale-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/dual-scale-enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/primary-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/with-readout-enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/zoomed-in-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/zoomed-in-dual-scale-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.ts/zoomed-in-narrow-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/primary-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/rov-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/scaled-fore-image-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-narrow-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-rectangular-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch-roll/pitch-roll.stories.ts/zoomed-in-with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/dual-scale-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/primary-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/zoomed-in-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/pitch/pitch.stories.ts/zoomed-in-narrow-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/dual-scale-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/primary-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/rov-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/with-readout-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/zoomed-in-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/roll/roll.stories.ts/zoomed-in-narrow-auto.pngis excluded by!**/*.png
📒 Files selected for processing (11)
.github/instructions/watch-radial-instruments.instructions.mdpackages/openbridge-webcomponents/src/building-blocks/instrument-linear/instrument-linear.spec.tspackages/openbridge-webcomponents/src/building-blocks/instrument-linear/instrument-linear.tspackages/openbridge-webcomponents/src/building-blocks/single-axis-inclinometer/single-axis-inclinometer.tspackages/openbridge-webcomponents/src/navigation-instruments/heave/heave.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/heave/heave.tspackages/openbridge-webcomponents/src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/pitch-roll-heave/pitch-roll-heave.tspackages/openbridge-webcomponents/src/navigation-instruments/pitch-roll/pitch-roll.tspackages/openbridge-webcomponents/src/navigation-instruments/readout/center-readout.tspackages/openbridge-webcomponents/src/navigation-instruments/watch/tickmark.ts
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>
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (5)
packages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/draft-trim/draft-trim.stories.ts/advice-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/draft-trim/draft-trim.stories.ts/enhanced-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/draft-trim/draft-trim.stories.ts/even-keel-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/draft-trim/draft-trim.stories.ts/regular-auto.pngis excluded by!**/*.pngpackages/openbridge-webcomponents/__vis__/linux/__baselines__/navigation-instruments/draft-trim/draft-trim.stories.ts/trim-by-bow-auto.pngis excluded by!**/*.png
📒 Files selected for processing (6)
.github/instructions/building-blocks.instructions.mdpackages/openbridge-webcomponents/src/building-blocks/instrument-linear/advice.tspackages/openbridge-webcomponents/src/building-blocks/instrument-linear/instrument-linear.tspackages/openbridge-webcomponents/src/navigation-instruments/draft-trim/draft-trim.stories.tspackages/openbridge-webcomponents/src/navigation-instruments/draft-trim/draft-trim.tspackages/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>
## [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))
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 heavebartype, 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-scaleputs pitch right, roll bottom and heave in the left band slot with the tick lane facing outward;dual-scalemirrors both arcs and moves the column to the centre;hasReadoutswaps the vessel silhouettes for stacked Pitch/Roll/Heave readouts. Marked@experimental(wipstory tag).The heave column is not sized independently — its dimensions fall out of the arc geometry:
capRadiusis 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 are90 - 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:
watchfaceLinear()— the same building blockobc-heaveuses — rather than by embedding<obc-heave>, whose fixed box/gauge widths and viewBox would all have to become configurable on a@stablecomponent.crosshairEnabled: the design has the arc bands covering the crosshair arms, butobc-watchrenders its crosshair afterwatchCircle()/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 toobc-watch. It is dropped entirely whenhasReadout, matching howobc-pitch-rollalready gates its horizon line.zoomToFitArcfollowsobc-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-cornersignedDistused between two arcs — a corner can clear a rectangle on one axis alone, andsignedDistscores −12.8 for a pair that is actually 32.8 apart.dual-scaleclamps 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.OUTER_RING_RADIUS184). Every relationship matches, so the implementation builds on the existingobc-watchradii to stay consistent withobc-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 waterlineinstrumentRange— each scale spans±instrumentRangearound the waterline, so the upper half reads as freeboardadvice(shared by both scales, each triggered by its own draught),vesselImage,priorityDesign decisions:
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.obc-rot-linearThe 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 overobc-watch-flat, which gains additive default-offbarAreas/needlesoptions (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)speedAlongKnots(+fore/−aft),speedAthwartBowKnots/speedAthwartSternKnots/speedAthwartKnots(+stbd/−port)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:
obc-speed-arrowsinto a sharedspeed-arrows-art.ts(speed-arrows snapshots unchanged); vessels fromwatch/vessel.ts; compass face isobc-watchthrough onecomputeRadialFrame()result shared with the overlay viewBox; framed square viasvghelpers/rectangular.tsrect().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 atinnerRingRadiusFor(single).genericTop(arrows/long-lat, 2× placement scale) andpsvTop(bars).fix(watch):generic-top.tswas the only vessel art withoutvector-effect="non-scaling-stroke"(mask-filled outline band); redrawn in the family-standard fill+stroke pattern.generic-side.tsstill 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/rpmwith 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,faceDiameterpropeller: PropellerImage— interchangeable center artDesign decisions:
barAreasgray track + tint arc,needlespill at the arc end).obc-watchknobs: optionalWatchBarArea.outerRadius/innerRadiusandWatchNeedle.length.feat(watch): propeller registry — eight top-view propeller types exported from Figma (node37391-148397), cleaned of page chrome and converted viascript/convert-vessel-svg-to-ts.tsinto 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 namedcap-five-bladewith a designer TODO.New variants on existing instruments
Compass & heading
Center readouts (
centerReadoutsonobc-compassandobc-heading): replaces the vessel with 1–3obc-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:Colors follow the existing per-element
priorityElementsmodel (e.g. enhanced HDG over neutral COG, exactly as in the Figma heading center-label variant). Readouts reuse the existingobc-readoutAPI only (closest-match rule; no new typography knobs).Arrow styles:
hdgArrowStyle(arrowHead|needle|vector|beamLine) andcogArrowStyle(arrowHead|needle|vector|velocityVector) on both instruments. The art lives in a new sharedcourse-arrowsmodule: 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-headinggains an optionalvesselImage(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
MapGraphicsstory):psv-topvessel, HDGvector, COGarrowHead, ROT bar, outside NSWE labels. (The Figma design uses a CCRP vessel variant; that image is deferred to its own PR via theconvert-vessel-svg-to-tspipeline.)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(centeredROT DEG/minreadout, dash until the physical value is set) andhasTrackBar— 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 existingobc-watchinputs (barAreas+needles+tickmarkson thedoubleface), with rot-sector's port/starboard and priority coloring.Heave
ObcHeaveType(vessel|bar).bardrops 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.vesselstays the default and renders identically — its three baselines pass untouched.vesselImage,gainScaleanddraftOffsetare 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-rolland bothobc-pitch-rollrender paths via the new sharedarcTickmarks(). 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.ts—renderCenterReadouts()gains an optionalCenterReadoutArrangement:primarySecondary(default, unchanged — first entry, one divider, then the rest side by side) andstacked(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.ts—arcTickmarks(centerAngle, halfExtent, interval = 5)emits thesecondaryladder along an arc band, skipping the arc centre (which carries its ownmainmark) and the ends, where the rounded end cap already reads as a boundary.building-blocks/instrument-linear—resolveLinearAdvice()(the hinted/regular/triggered mapping, extracted fromobc-heave) andverticalScaleTickmarks(range)(the tick configuration for a scale spanning±rangearound a zero reference) are now shared byobc-heaveandobc-draft-trim.watchfaceLinearalso gainsoptions.maskId: the container clip-mask id was hard-coded toboxMask, 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 intervalsobc-heavehard-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-heavekeeps its literals so its baselines do not move.course-arrows/— HDG/COG arrow art shared by compass, heading and (via the deprecatedcompass/arrow.tsshim) compass-sector.speed-arrows-art.ts— chevron art shared byobc-speed-arrowsandobc-speed-directions.Migration / snapshot notes
pitch-rollandcompass-sectornow 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).--updatealone leaves twozoomed-in-narrowbaselines stale: the ladder does change them (52 px) but the addon's anti-alias tolerance passes them, so they were regenerated explicitly.generic-topvessel redraw deliberately regenerates wind (4), ar/chart-object-vessel-button (1) and speed-directions (3) baselines.instrument-linearextraction is behaviour-preserving: heave, thruster and main-engine baselines pass unchanged.6.1(story-level on extended 6.0 components; file-level on new components).Cascade / zoomToFitArc safety
radial-frame.ts,arc-frame.tsand the advice dual-path are untouched. Deliberate, verified core-renderer touches:watch.tsrenderBarsnow applies its area cut mask only whenareasexist (band bars on full-circle faces no longer rely on lax dangling-reference handling; zero-diff for all existing consumers);watch-flat.tsgains the additive band bar/needle options (default off; compass-flat pixel-identical);obc-watchgains optionalWatchBarArea.outerRadius/innerRadiusandWatchNeedle.length(all eight barAreas/needles consumer suites verified unchanged).compass-sector(zoom family) importsarrow()fromcompass/arrow.tspassing its zoomradiusOffset; both legacyarrow.tsmodules remain as deprecated shims delegating tocourse-arrowswith byte-identical signatures and output, so that path cannot drift.obc-pitch-roll-heavereuses theobc-pitch-rollbuildFramecontract 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)
obc-compass-sector(arrowheads +hasReadout+ priority variants); deltas are cosmetic (single-band arc face, no degree labels).obc-compass-flat+ the newhasReadout; deltas cosmetic (boxed strip, in-band arrow icons).Agent-doc updates
@availableWhengrammar extended with empty-array conditions (arr==[]/arr!=[]);vesselImageon compass/heading annotated accordingly.--update(the documented order ran the full suite in update mode).npm run analyzeis required before testing stories of a newly created component (storybook arg mapping reads the manifest).watch-radial-instruments.instructions.md: scope extended topitch/**,pitch-roll-heave/**,rate-of-turn/**,course-arrows/**and thesingle-axis-inclinometerbuilding block; documents the sharedcourse-arrows/center-readout/arcTickmarks/linearTickIntervalmodules, 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
obc-pitch-roll's horizon line already behaves, but is untested against a design.CORNER_GAP_PX32, inherited fromobc-pitch-roll, andHEAVE_CENTRE_GAP_PX10) have no design reference and may want visual iteration.indicator-graph,donut-chartandpie-chartfail 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