fix(search): keep the phone results toolbar inside the screen #159

Merged
tudor merged 1 commits from fix/phone-toolbar-width into main 2026-09-30 22:21:17 +00:00
Owner

On phones, the results toolbar's search summary ("SW196AR · within 1 mile Edit") ran about 40px past the right edge of the screen and cut "Edit" in half. The filter row overflowed with it. It was reported on an iPhone 17 (402px), but it happens at every phone width. On staging:

Width Summary right edge Filter row right edge
360px 426px 442px
402px 425px 441px

Cause

The phone toolbar is a column flex container, but it kept flex-wrap: wrap from the desktop rule. In a wrapping flex container, each line is as wide as its widest item's content rather than the container. The summary's ~410px of text therefore widened the line past the 370px toolbar, and align-items: stretch widened the filter row to match.

Fix

Add flex-wrap: nowrap to the phone rule. With a single line, stretch means the container's width.

Verified on staging by injecting that rule into the live page. At both 360px and 402px, nothing in the toolbar, folded or unfolded, passes the right edge afterwards; "Edit" is fully visible, and the filter row ends exactly at the screen edge.

Why the E2E check missed it

.main has overflow-x: clip, so document.scrollWidth stayed equal to the viewport. The phone journey now also measures the right edges of the toolbar's own elements. The filter row's children are exempt because that row scrolls by design. The journey also runs at 402px now.

Run against staging, which doesn't have the fix yet, the new check fails at 360, 390 and 402px on exactly these elements (see above).

Two fixes to the test itself, both found by running it against staging:

  • It measured the bottom sheet partway through its 0.3s slide-up. It now waits for the sheet to settle.
  • It compared the sheet against a Map/List button position taken before the sheet opened. The sheet pushes the button up, so the button is now measured again.

Unit tests: 513/513 pass.

🤖 Generated with Claude Code

On phones, the results toolbar's search summary ("SW196AR · within 1 mile Edit") ran about 40px past the right edge of the screen and cut "Edit" in half. The filter row overflowed with it. It was reported on an iPhone 17 (402px), but it happens at every phone width. On staging: | Width | Summary right edge | Filter row right edge | |---|---|---| | 360px | 426px | 442px | | 402px | 425px | 441px | ## Cause The phone toolbar is a column flex container, but it kept `flex-wrap: wrap` from the desktop rule. In a wrapping flex container, each line is as wide as its widest item's content rather than the container. The summary's ~410px of text therefore widened the line past the 370px toolbar, and `align-items: stretch` widened the filter row to match. ## Fix Add `flex-wrap: nowrap` to the phone rule. With a single line, stretch means the container's width. Verified on staging by injecting that rule into the live page. At both 360px and 402px, nothing in the toolbar, folded or unfolded, passes the right edge afterwards; "Edit" is fully visible, and the filter row ends exactly at the screen edge. ## Why the E2E check missed it `.main` has `overflow-x: clip`, so `document.scrollWidth` stayed equal to the viewport. The phone journey now also measures the right edges of the toolbar's own elements. The filter row's children are exempt because that row scrolls by design. The journey also runs at 402px now. Run against staging, which doesn't have the fix yet, the new check fails at 360, 390 and 402px on exactly these elements (see above). Two fixes to the test itself, both found by running it against staging: - It measured the bottom sheet partway through its 0.3s slide-up. It now waits for the sheet to settle. - It compared the sheet against a Map/List button position taken before the sheet opened. The sheet pushes the button up, so the button is now measured again. Unit tests: 513/513 pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
tudor added 1 commit 2026-09-30 21:09:08 +00:00
fix(search): keep the phone results toolbar inside the screen
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m12s
PR Checks / Backend Smoke (pull_request) Successful in 9s
PR Checks / Build Backend (no push) (pull_request) Successful in 18s
PR Checks / Build Frontend (no push) (pull_request) Successful in 1m19s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 11s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 15s
a37da15008
The search summary ("SW196AR · within 1 mile  Edit") ran about 40px off
the right edge on every phone, cutting "Edit" in half, and the filter row
bled past the screen with it (reported on an iPhone 17, 402px).

The phone toolbar is a column flex container, but it kept flex-wrap:
wrap from the desktop rule. In a wrapping flex container each line is as
wide as its widest item's content, not the container, so the summary's
~410px of text stretched the line past a 370px toolbar. nowrap makes
stretch mean the container's width. Verified on staging by injecting the
rule: nothing in the toolbar passes the right edge at 360 or 402px.

The E2E overflow check could not see this: .main clips on x, so
scrollWidth stayed equal to the viewport. The phone journey now measures
the toolbar's own right edges, and runs at 402px as well. It also waits
for the bottom sheet's slide-up to finish before measuring, and measures
the Map/List button again after the sheet pushes it up; both assertions
read a mid-animation or stale box before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

🤖 AI Code Review (Claude Code)

Fixes a phone toolbar overflow on 402px screens (iPhone 17) by adding flex-wrap: nowrap to the mobile filter bar. The e2e test adds a 402px width case, waits for the bottom-sheet animation to settle, re-measures the FAB after the sheet opens, and adds a per-element right-edge check on the toolbar. The change is small, test and CSS only, and looks healthy.

🟡 Minor

  • e2e/tests/journeys.spec.ts: The bottom-sheet check uses expect.poll without an explicit timeout or intervals, so it relies on the default poll timing. It also only waits for the sheet's bottom edge to be at or above the tab bar, so a sheet that is still mid-animation could pass early and then fail the following FAB comparison intermittently. Consider polling on the final position, or on the fab and sheet relationship itself.
  • e2e/tests/journeys.spec.ts: The offscreen check filters on offsetParent, which is null for position: fixed elements. Fixed toolbar children are therefore silently skipped, which could hide an overflow. It also compares right edges only, so left-edge overflow is not covered.
## 🤖 AI Code Review (Claude Code) Fixes a phone toolbar overflow on 402px screens (iPhone 17) by adding flex-wrap: nowrap to the mobile filter bar. The e2e test adds a 402px width case, waits for the bottom-sheet animation to settle, re-measures the FAB after the sheet opens, and adds a per-element right-edge check on the toolbar. The change is small, test and CSS only, and looks healthy. ### 🟡 Minor - **e2e/tests/journeys.spec.ts**: The bottom-sheet check uses expect.poll without an explicit timeout or intervals, so it relies on the default poll timing. It also only waits for the sheet's bottom edge to be at or above the tab bar, so a sheet that is still mid-animation could pass early and then fail the following FAB comparison intermittently. Consider polling on the final position, or on the fab and sheet relationship itself. - **e2e/tests/journeys.spec.ts**: The offscreen check filters on offsetParent, which is null for position: fixed elements. Fixed toolbar children are therefore silently skipped, which could hide an overflow. It also compares right edges only, so left-edge overflow is not covered.
tudor merged commit 37bbda1da1 into main 2026-09-30 22:21:17 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: tudor/school_compare#159