Fit the tab labels on narrow phones
Five labels across a 320px viewport is tighter than it looks. The body's own 16px gutters, the bar's padding and four gaps leave about 45px of text per tab, and "Growth" — the widest label at roughly 3.2em — wants 46px at the default size. So on an iPhone SE and the smaller Androids it truncated to "Growt…", and on a 280px foldable cover screen it was 7px short. The same 370px breakpoint the day bar already uses for the same reason now trims the type to 0.75rem and the horizontal padding to 2px, which takes the widest label to about 39px against 43px of room even at 280px. Above the breakpoint nothing changes; there was never a problem there. Also fixes the sticky offset going stale. The tab bar sits directly under the day bar, so its `top` is that bar's measured height, published as --day-bar-h. That was measured on load and on resize — but the bar also grows the first time a sleep is logged, when the timer pill appears inside it, and that fires no resize, leaving the tab bar overlapping the day bar until something else happened to trigger one. A ResizeObserver on the bar covers that and every other cause, with the resize listener kept as the fallback. The label arithmetic is now checked rather than eyeballed, since no browser is available here: the layout numbers are read back out of the stylesheet so they cannot drift, text width is estimated from per-character advances, and the pass mark demands real headroom rather than a bare fit because the estimate is only good to a few percent. Removing the new rules makes it fail on exactly the two devices that were broken, which is the only way to know a check like that is doing anything.
This commit is contained in:
+12
-4
@@ -4781,12 +4781,20 @@
|
||||
// The tab bar sticks directly under the day bar, which means its `top` has to
|
||||
// be that bar's height — measured, because the bar's contents (and so its
|
||||
// height) differ between phones and orientations.
|
||||
//
|
||||
// A resize listener alone is not enough: the bar also grows the first time a
|
||||
// sleep is logged, when the timer pill appears inside it, and that fires no
|
||||
// resize. Watching the element covers both, and every other cause besides.
|
||||
const dayBarEl = document.querySelector(".day-bar");
|
||||
function measureDayBar() {
|
||||
const bar = document.querySelector(".day-bar");
|
||||
if (!bar) return;
|
||||
document.documentElement.style.setProperty("--day-bar-h", `${bar.offsetHeight}px`);
|
||||
if (!dayBarEl) return;
|
||||
document.documentElement.style.setProperty("--day-bar-h", `${dayBarEl.offsetHeight}px`);
|
||||
}
|
||||
if (dayBarEl && typeof ResizeObserver === "function") {
|
||||
new ResizeObserver(measureDayBar).observe(dayBarEl);
|
||||
} else {
|
||||
addEventListener("resize", measureDayBar);
|
||||
}
|
||||
addEventListener("resize", measureDayBar);
|
||||
measureDayBar();
|
||||
|
||||
showTab(loadTab(), { scroll: false });
|
||||
|
||||
@@ -198,6 +198,18 @@ main {
|
||||
}
|
||||
.tabs .tab:hover { filter: none; }
|
||||
|
||||
/* Five labels have to fit without truncating on the narrow phones, and the
|
||||
budget is tight: at a 320px viewport (iPhone SE, smaller Androids) the body's
|
||||
own 16px gutters, the bar's padding and four gaps leave about 45px of text
|
||||
per tab, while "Growth" — the widest label, roughly 3.3em — wants 46px at the
|
||||
default size. So the same breakpoint the day bar already uses trims the type
|
||||
and the padding, which takes the widest label to about 40px against 43px of
|
||||
room even on a 280px foldable cover screen. */
|
||||
@media (max-width: 370px) {
|
||||
.tabs { gap: 2px; padding-left: 2px; padding-right: 2px; }
|
||||
.tabs .tab { font-size: 0.75rem; padding-left: 2px; padding-right: 2px; }
|
||||
}
|
||||
|
||||
/* main's own gap sits between the pinned blocks and the tab area; each tab
|
||||
then spaces its own panels the same way. */
|
||||
.tab-panel {
|
||||
|
||||
Reference in New Issue
Block a user