Phone layout: stop the radio controls running off the side #46

Merged
sjg merged 3 commits from fix/mobile-layout into main 2026-08-06 20:15:21 +02:00
Owner

On a 390px screen the transmit controls were laid out at x=400, off the side of a tray 354px wide — present, invisible, and reachable only by a horizontal scroll with nothing to say it was there. The page scrolled sideways by a dozen pixels too.

Three causes, three places

1. A container query, at the end of the stylesheet, re-imposes flex-wrap: wrap on a narrow tray's rows. That is right while a row runs left to right. Below the phone breakpoint the row is a column, and wrapping a column starts a second column — which is exactly where the transmit controls went. The rule outranks the phone one (two classes to its one) and sits later in the file, so it now excludes itself below that breakpoint rather than being overridden.

2. The tray is a grid, and a grid column sizes to its content. One row wider than the screen — the mode picker, six buttons across — dragged the whole tray out with it. minmax(0, 1fr) lets the column be as narrow as the phone and the rows wrap inside it.

3. The wavelength and signal-strength readouts are given the width of their column on narrow screens, but with padding on a content box that is the column's width plus the padding. Those were the dozen pixels of page scroll. Border-box now.

Also

  • The rig picker was taking 139px of a 338px bar, pushing the rest of the top bar into the overflow menu. Capped and ellipsised on phones; the full name is still in the menu it opens.
  • The map's collapsed filter bar keeps both anchors and shrinks inside them, instead of dropping left and being sized by shrink-to-fit, and no longer asks for a compositing layer it does not need (will-change: backdrop-filter).

About the Edge bug

Reported: "Hide Filters hides the whole panel in MS Edge." I could not reproduce it — this machine has no Edge. What I changed are the two constructs in that panel most likely to explain it: an absolutely positioned, backdrop-filtered, composited box sizing itself from its content is the shape of thing that renders as nothing on an engine other than the one it was written against. Both changes are behaviour-neutral in Chromium, verified: the collapsed bar still hugs the right edge with Fullscreen and Show Filters on it.

Please confirm in Edge before trusting this one. If it still happens, the next things I'd want are whether the bar is gone or merely invisible, and whether Show Filters is still clickable where it used to be.

Testing

New tests/mobile-layout.mjs, at 430, 390 and 360px: no sideways scroll, nothing laid out past the right edge, the transmit controls inside the screen, the rig picker within its cap — plus the collapsed filter bar still on screen with a working button to bring the filters back. Added to npm run test:browser.

One unrelated fix rides along: the SSTV panel test stamped its picture with a fixed date, which the panel's own 24-hour retention dropped once that date was a day old. It started failing overnight. It uses a recent stamp now.

Typecheck, lint, 47 unit tests, all five browser suites, verify-generated and cargo fmt --check all pass.

On a 390px screen the transmit controls were laid out at **x=400**, off the side of a tray 354px wide — present, invisible, and reachable only by a horizontal scroll with nothing to say it was there. The page scrolled sideways by a dozen pixels too. ## Three causes, three places **1. A container query, at the end of the stylesheet**, re-imposes `flex-wrap: wrap` on a narrow tray's rows. That is right while a row runs left to right. Below the phone breakpoint the row is a *column*, and wrapping a column starts a **second column** — which is exactly where the transmit controls went. The rule outranks the phone one (two classes to its one) and sits later in the file, so it now excludes itself below that breakpoint rather than being overridden. **2. The tray is a grid, and a grid column sizes to its content.** One row wider than the screen — the mode picker, six buttons across — dragged the whole tray out with it. `minmax(0, 1fr)` lets the column be as narrow as the phone and the rows wrap inside it. **3. The wavelength and signal-strength readouts** are given the width of their column on narrow screens, but with padding on a content box that is the column's width *plus* the padding. Those were the dozen pixels of page scroll. Border-box now. ## Also - **The rig picker** was taking 139px of a 338px bar, pushing the rest of the top bar into the overflow menu. Capped and ellipsised on phones; the full name is still in the menu it opens. - **The map's collapsed filter bar** keeps both anchors and shrinks inside them, instead of dropping `left` and being sized by shrink-to-fit, and no longer asks for a compositing layer it does not need (`will-change: backdrop-filter`). ## About the Edge bug Reported: "Hide Filters hides the whole panel in MS Edge." **I could not reproduce it — this machine has no Edge.** What I changed are the two constructs in that panel most likely to explain it: an absolutely positioned, backdrop-filtered, composited box sizing itself from its content is the shape of thing that renders as nothing on an engine other than the one it was written against. Both changes are behaviour-neutral in Chromium, verified: the collapsed bar still hugs the right edge with Fullscreen and Show Filters on it. **Please confirm in Edge before trusting this one.** If it still happens, the next things I'd want are whether the bar is gone or merely invisible, and whether Show Filters is still clickable where it used to be. ## Testing New `tests/mobile-layout.mjs`, at 430, 390 and 360px: no sideways scroll, nothing laid out past the right edge, the transmit controls inside the screen, the rig picker within its cap — plus the collapsed filter bar still on screen with a working button to bring the filters back. Added to `npm run test:browser`. One unrelated fix rides along: the SSTV panel test stamped its picture with a fixed date, which the panel's own 24-hour retention dropped once that date was a day old. It started failing overnight. It uses a recent stamp now. Typecheck, lint, 47 unit tests, all five browser suites, `verify-generated` and `cargo fmt --check` all pass.
sjg added 1 commit 2026-08-06 19:06:39 +02:00
[fix](trx-frontend-http): stop the radio controls running off the side of a phone
CI / lint (pull_request) Successful in 2m19s
CI / test (pull_request) Successful in 8m23s
CI / frontend (pull_request) Failing after 1m28s
CI / reuse (pull_request) Successful in 2s
14ad6e241b
On a 390 px screen the transmit controls were laid out at x=400, off the
side of a tray 354 px wide: present, invisible, and reachable only by a
horizontal scroll with nothing to say it was there.  The page scrolled
sideways by a dozen pixels as well.

Three causes, each in a different place.

A container query at the end of the stylesheet re-imposes `flex-wrap:
wrap` on a narrow tray's rows.  That is right while a row runs left to
right; below the phone breakpoint the row is a column, and wrapping a
column starts a *second column* — which is what put the transmit
controls beside the tray rather than under it.  The rule outranks the
phone one, two classes to its one, and sits later in the file, so it now
excludes itself below that breakpoint rather than being overridden.

The tray is a grid, and a grid column sizes to its content.  One row
wider than the screen — the mode picker, six buttons across — dragged
the whole tray out with it.  `minmax(0, 1fr)` lets the column be as
narrow as the phone and the rows wrap inside it.

The wavelength and signal-strength readouts are given the width of their
column on narrow screens, but with padding on a content box that is the
column's width plus the padding.  Those dozen pixels were the page's
sideways scroll.  They are border-box now.

Also: the rig picker was taking 139 px of a 338 px bar, pushing the rest
of the top bar into the overflow menu.  It is capped and ellipsised on
phones, with the full name still in the menu it opens.

The map's filter bar, collapsed, keeps both its anchors and shrinks
inside them rather than dropping `left` to be sized by shrink-to-fit,
and no longer asks for a compositing layer it does not need.  An
absolutely positioned, backdrop-filtered, composited box sizing itself
from its content is the shape of thing that renders as nothing on an
engine other than the one it was written against — which is what Edge
does with it.  Unverified there: this machine has no Edge to test with.

tests/mobile-layout.mjs holds the page to it at 430, 390 and 360 px: no
sideways scroll, nothing laid out past the right edge, the transmit
controls inside the screen, the rig picker within its cap — and the
collapsed filter bar still on screen with a button to bring the filters
back.

The SSTV panel test stamped its picture with a fixed date, which the
panel's own retention window dropped once that date was a day old.  It
uses a recent stamp now.

Signed-off-by: Stan Grams <sjg@haxx.space>
sjg added 1 commit 2026-08-06 19:14:34 +02:00
[fix](trx-frontend-http): let the bottom nav's labels fit inside its tabs
CI / lint (pull_request) Successful in 2m17s
CI / test (pull_request) Successful in 8m22s
CI / frontend (pull_request) Failing after 1m46s
CI / reuse (pull_request) Successful in 2s
6284747339
The bottom nav keeps its labels under the icons -- that is what makes it
navigation rather than five glyphs -- but the labels did not fit the
tabs.  On a 360 px screen "Bookmarks" and "Digital modes" were cut off
mid-word and ran into each other: "Bookmarks igital mode".

The stylesheet already meant to handle it.  Three rules shrink the long
labels, and a rule twenty lines further down sets the size for all of
them; identical specificity, later in the file, so the blanket rule won
and nothing was ever shortened.  Those rules now come after it.

Beyond that, tabs sized themselves to their own labels, so "Map" and
"Digital modes" were given the same room.  They divide the bar evenly
now, which is the shape of every bottom nav, and a label that still runs
long ellipsises rather than being cut through a letter.

"Digital modes" does not fit at any size worth reading, so the nav shows
"Digital" and the button carries the full name as its accessible label;
the short form is hidden from assistive tech, which reads the button's
name instead.

The phone layout test now checks that no label in the nav is cut off at
430, 390 or 360 px, and that the shortened tab still says what it is to
something that reads the page rather than looks at it.

Signed-off-by: Stan Grams <sjg@haxx.space>
sjg added 1 commit 2026-08-06 19:41:48 +02:00
[fix](trx-frontend-http): size the nav's labels against the screen, not the font
CI / lint (pull_request) Successful in 2m17s
CI / test (pull_request) Successful in 8m23s
CI / frontend (pull_request) Successful in 4m20s
CI / reuse (pull_request) Successful in 3s
CI / lint (push) Successful in 2m17s
CI / test (push) Successful in 7m35s
CI / frontend (push) Successful in 3m29s
CI / reuse (push) Successful in 2s
77b283cb78
CI cut "Bookmarks" off at 360 px where this machine had ten pixels to
spare.  How wide a platform draws a word varies by more than ten per
cent, so a fixed 0.6rem label is a bet on the machine it was measured
on -- the same bet ui-core's own comment warns about where it explains
why the tab strip reflows by measurement rather than at a width.

The long labels are sized with `clamp(0.46rem, 2.2vw, 0.62rem)` now.  A
tab is a fifth of the viewport, so what fits in it follows the viewport;
tying the label to the same thing leaves better than a fifth of the tab
spare at every phone width, and holds with the text drawn 30% wider than
it is here.

The test asked the wrong question too.  "Does the label fit" is a
question about font metrics, and it will keep answering differently on
different machines.  It now asserts what actually matters: a label stays
inside its own tab, and if it is too long for it, it ends in an ellipsis
rather than being cut through a letter.  Both hold whatever width the
platform draws the words at.

Signed-off-by: Stan Grams <sjg@haxx.space>
sjg merged commit 77b283cb78 into main 2026-08-06 20:15:21 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sjg/trx-rs#46