ADR-036 — ?-chip cross-screen pattern: click navigates, hover tooltip on desktop
Status · Accepted Date · 2026-05-07 Closes · RFC-011 (with ADR-034, ADR-035) TA anchor · §components / primary-route-pages Related · PRD-008, ADR-018 (mobile-first), ADR-024 (deep-link URLs)
Context
PRD-008 promises a ? chip next to every technical label in the Orrery HUD that names a concept covered in /science. The chips appear on /plan (porkchop axes), /fly (HUD rows), /missions FLIGHT tab (C3, V∞, TLI, TMI, TCM, OI, total ∆v), /explore planet panels (Keplerian element rows), /earth (orbit-altitude regimes), /moon and /mars (trajectory-type narrative). ~30 attachment points total.
RFC-011 OQ-3 asked how the ? chip behaves: click only, click + hover tooltip, or click into a popover modal.
Decision
Behaviour (RFC OQ-3 — Option B)
The ? chip:
- Renders as a 14×14 px circle with a question-mark glyph. Min hit area 24×24 px (smaller than ADR-018's 44 px primary touch baseline because chips sit inline next to HUD labels and would crowd out content otherwise).
- On hover (desktop only): shows the section's
intro_sentence(≤ 80 chars) as atitleattribute / native browser tooltip. No custom popover JS, no portal, no positioning math. - On click / tap (both desktop and mobile): navigates to
/science/[tab]/[section]. Full SvelteKit page navigation; the user lands on the static-prerendered section page. - No popover modal: rejected per RFC-011 OQ-3 Option C. A modal on mobile click is exactly the context-loss anti-pattern PRD-008 wants to avoid.
Component (src/lib/components/ScienceChip.svelte)
Single reusable component with props { tab: string, section: string, hoverTitle?: string }:
<a
href={`${base}/science/${tab}/${section}`}
class="science-chip"
title={hoverTitle ?? ''}
aria-label={`Learn about ${section}`}
>?</a>CSS: 14 px circle, white-50 fill, white-90 question mark, 1 px border, 24 px hit area via padding. Hover/focus states bump to teal (#4ecdc4). Matches the mission LEARN tab link aesthetic.
Typography + placement contract
The chip lives inline with its label, not on a separate line. Examples:
<dt>C3 <ScienceChip tab="propulsion" section="c3" /></dt>
<span class="hud-key">∆V HELIO <ScienceChip tab="propulsion" section="dv" /></span>Keeps the label as a single visual unit; the chip reads as "tap for definition" punctuation.
Internationalisation
The hoverTitle prop comes from the section's intro_sentence (already localised per ADR-017). No additional i18n keys required for the chip itself; the chip's aria-label uses the section ID directly.
For surfaces where the label is not yet i18n'd (e.g. /earth LEO/MEO/GEO/HEO regime labels, /moon and /mars mission_type strings), Phase 2 work adds the i18n keys as a prerequisite — chip placement waits on label internationalisation.
Consequences
Positive: Zero new component infrastructure beyond ScienceChip.svelte. Hover tooltip is free (native title). Mobile UX preserves single-flow — no modal context-loss. Deep-linkable URLs (/science/[tab]/[section]) match the rest of the app's URL contract per ADR-024. Reuses the existing LEARN-tab link aesthetic, no new design tokens.
Negative: Native title tooltips are minimally styled and time out on long hovers — not a polished tooltip experience on desktop, but the click-navigate is the primary interaction so the tooltip is a desktop convenience, not a contract. ~30 attachment points across 7 routes is meaningful integration scope (Phase 2).
Implementation notes
- Component:
src/lib/components/ScienceChip.svelte. - Phase 1 (this ADR's scope): the chip component + the "see in app" inverse chip on the
/scienceside (SeeInAppChip.sveltelinking back to existing routes). - Phase 2 (separate batch): wire ~30 chip placements across
/plan,/fly,/missions,/explore,/earth,/moon,/mars. Tracked under issue #39 Phase D. - Section ID stability: the chip's
tab+sectionprops rely on the URL contract from PRD-008 §scope. Section IDs are an enum inscience-section.schema.json; renaming a section is a breaking change and requires migrating chip placements in lockstep.