Skip to content

Keep the scenario message banner off the objectives panel - #150

Merged
Knorcedger merged 1 commit into
mainfrom
claude/mobile-hud-overlap-objectives-4hj5pv
Aug 23, 2026
Merged

Keep the scenario message banner off the objectives panel#150
Knorcedger merged 1 commit into
mainfrom
claude/mobile-hud-overlap-objectives-4hj5pv

Conversation

@Knorcedger

Copy link
Copy Markdown
Owner

What changed?

The scenario dialogue banner painted over the objectives panel's head, leaving the current goal and its progress as ghost text under it. The only clearance was a media query at the 720px narrow breakpoint — but that is not where the collision ends. The banner is centred at min(560px, 92%) and the panel is right-anchored at min(300px, 60vw), and both hang from the top bar, so their vertical ranges always meet and the overlap is decided horizontally:

w/2 + 280 > w - 306   →   w < 1172

Every viewport from 721px to ~1171px collided with no clearance applied — landscape phones, small tablets, and a windowed desktop browser. Above ~1172px the banner genuinely cannot reach the panel, which is why it looks fine maximised.

The panel now publishes its own footprint the way the HUD already publishes the top bar's and the command cluster's edges: --bf-objectives-message-top (the first clear y below everything it occupies) and --bf-objectives-left. The banner places itself from those measurements, with two ways out tried in order:

  1. Sideways, into the strip left of the panel — 524px on an 844px landscape phone. Nothing moves vertically, which matters most on a short screen where every row below the bar is already spoken for.
  2. Down, below the panel, where that strip would squeeze the text into a column (a portrait phone). The drop is bounded by the command cluster, because dodging one HUD onto another is not a fix: the banner is z-index 28 with pointer-events: auto, so landing on the command card would swallow its taps for the message's lifetime.

If neither fits, it stays under the bar — overlapping the panel it came from is the lesser evil there, since the panel yields its own taps when the column is that full.

The published bottom is the panel's real bottom (the list's when it is open), so clearing the head no longer just moves the banner onto the list instead.

Related issue

Closes #144

Why this approach?

A breakpoint cannot answer this question. Whether two boxes overlap depends on both widths and both anchors, and the panel's own height varies with the objective text and whether its list is open — so the collision is computed from measured edges, the same contract --bf-top-bar-bottom (#104) and --bf-right-cluster-top (#143) already use. The two shared variables and the px parser move to layout.ts, where those edges live; objectives.ts loses its private copy of the parser.

Sideways-first is deliberate. Dropping the banner is the more obvious fix and is what the old narrow path did, but on a landscape phone it costs vertical space that does not exist, and it moves the text away from where the player is already looking. The horizontal strip is free real estate in exactly the band where the collision happens.

No simulation code is touched; this is all DOM HUD in packages/game.

Verification

  • npm run typecheck
  • npm test — 1385 passed, 11 skipped
  • npm run build (via npm run check, bundle budget included)
  • I added or updated tests where behavior changed
  • I included screenshots or a recording for visible changes

Driven in a real browser on wallace-1 with a message showing, at 844×390, 390×844 and 1280×800, each with and without a selection card up — six states, rects measured directly:

viewport banner result
844×390 6..530, top 48 steps beside the panel (538) and the cluster (574); no vertical move
390×844 16..374, top 156 drops below the panel (bottom 142); clear of the cluster (571)
1280×800 360..920, top 48 unchanged — no collision to resolve

overlapsPanel and overlapsCluster are false in all six, the banner stays inside the root, and document.elementFromPoint at the objective head returns the head rather than the banner.

A review of the first cut caught two things, both fixed here: the drop was unbounded, so on a landscape phone it landed on the command card (the same bug moved); and position() read offsetWidth every frame a message was up, forcing a synchronous reflow — the published edges already cover every case that changes the banner's width.

Provenance and AI assistance

Claude Code (Anthropic) wrote the implementation, tests and this description, driven and reviewed by the repository owner. No generated assets.

Contributor checklist

  • I searched issues and active pull requests before implementation and coordinated ownership in the linked issue
  • This pull request closes or references exactly one primary coordination issue
  • I read CONTRIBUTING.md and followed the deterministic simulation rules
  • I reviewed and understand every submitted change
  • I have the right to submit this code and any included assets
  • My commits are signed off under the Developer Certificate of Origin (git commit -s)
  • This PR contains no credentials, private player data, or unlicensed third-party material

Generated by Claude Code

The banner is centred at min(560px,92%) and the objectives panel is
right-anchored at min(300px,60vw), and both hang from the top bar — so
their vertical ranges always meet and whether they collide is decided
horizontally. Solving w/2 + 280 > w - 306 puts the overlap at every
viewport up to ~1172px wide, but the only clearance was a media query at
the 720px narrow breakpoint. From there up to a windowed desktop the
banner painted over the objective head, and the current goal and its
progress read as ghost text under it.

The panel now publishes its own footprint the way the HUD publishes the
top bar's and the command cluster's edges: the first clear y below
everything it occupies, and its left edge. The banner places itself from
those measurements. Two ways out, tried in order: sideways into the strip
left of the panel, which is 524px on an 844px landscape phone and needs no
vertical movement at all on a screen where every row below the bar is
already spoken for; failing that, down below the panel, bounded by the
command cluster so dodging one HUD does not simply land this one — z-index
28 and pointer-events:auto — on the command card and eat its taps.

The published bottom is the panel's real bottom, the list's when it is
open, so clearing the head no longer just moves the banner onto the list.

The two shared CSS variables and the px parser move to layout.ts, where the
other cross-overlay edges already live; objectives.ts loses its private
copy of the parser.

Verified in a browser, message showing, at 844x390, 390x844 and 1280x800,
with and without a selection card up: no overlap with the panel or the
cluster in any of the six, the banner stays on screen, and the desktop
layout is unchanged.

Closes #144

Signed-off-by: Claude <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bannerfall Ready Ready Preview Aug 23, 2026 9:01am

Request Review

@Knorcedger
Knorcedger merged commit 54760da into main Aug 23, 2026
3 checks passed
@Knorcedger
Knorcedger deleted the claude/mobile-hud-overlap-objectives-4hj5pv branch August 23, 2026 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scenario message banner covers the objectives head on every viewport narrower than ~1170px

2 participants