[fix](trx-frontend-http): measure whether the tab bar fits, and watch for it
CI put the tab strip 9px into the controls at 1440px with no scaling at all, on a bar that had every degradation step available to it and used none of them. It used none because nothing thought anything was wrong: the fit test was an arithmetic estimate — identity + nav.scrollWidth + actions.scrollWidth + a 48px allowance for the gaps — and on a platform whose fonts run wider than the one it was written on, that allowance no longer covered what it stands for. An estimate that says "fits" stops the ladder before its first rung. It reads the geometry now: the controls have to stay inside the bar, and no tab may reach them. That is the same measurement the test makes, so the two cannot disagree about any platform's metrics. The tabs are the subject rather than the nav's box because the nav shrinks below its content — the box gets smaller while the tabs keep their width and slide underneath the controls. A second fault turned up while probing this: the strip only reflowed on window resize. The rig name arriving from the server, the style picker filling in, a font swapping in wider metrics — each changes what fits without touching the window, and the bar sat there as it was through all of them. A ResizeObserver on the bar and the controls covers those, and document.fonts.ready covers the swap. The guard sweeps text scales and adds a station name too long for the bar, but it should be said plainly: it passes against the old code too. Nothing here reproduces on this machine — a 4px viewport sweep from 1080 to 1500, three wide font stacks and scales from 1.0 to 3.0 all failed to make the old estimate lie. What is fixed is the mechanism that could. Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -810,12 +810,15 @@ function elementById(id) {
|
||||
});
|
||||
const barFits = () => {
|
||||
const bar = actions.closest(".tab-bar");
|
||||
if (!bar) return true;
|
||||
const identity = bar.querySelector(".header-main");
|
||||
const nav = bar.querySelector(".tab-bar-nav");
|
||||
const gutters = 48;
|
||||
const needed = (identity?.offsetWidth ?? 0) + (nav?.scrollWidth ?? 0) + actions.scrollWidth + gutters;
|
||||
return needed <= bar.clientWidth;
|
||||
const nav = bar?.querySelector(".tab-bar-nav");
|
||||
if (!bar || !nav) return true;
|
||||
const barRect = bar.getBoundingClientRect();
|
||||
const actionsRect = actions.getBoundingClientRect();
|
||||
if (actionsRect.right > barRect.right + 1) return false;
|
||||
const tabs = Array.from(nav.querySelectorAll(".tab")).filter((tab) => tab.offsetParent !== null);
|
||||
if (!tabs.length) return true;
|
||||
const tabsRight = Math.max(...tabs.map((tab) => tab.getBoundingClientRect().right));
|
||||
return tabsRight <= actionsRect.left - 1;
|
||||
};
|
||||
const reflowOverflow = () => {
|
||||
const nav = document.querySelector(".tab-bar-nav");
|
||||
@@ -841,6 +844,18 @@ function elementById(id) {
|
||||
};
|
||||
reflowOverflow();
|
||||
window.addEventListener("resize", reflowOverflow);
|
||||
if (typeof ResizeObserver !== "undefined") {
|
||||
const bar = actions.closest(".tab-bar");
|
||||
const observer = new ResizeObserver(() => {
|
||||
reflowOverflow();
|
||||
});
|
||||
if (bar) observer.observe(bar);
|
||||
observer.observe(actions);
|
||||
}
|
||||
document.fonts?.ready.then(() => {
|
||||
reflowOverflow();
|
||||
}).catch(() => {
|
||||
});
|
||||
}
|
||||
function installMobileMore() {
|
||||
const nav = document.querySelector(".tab-bar-nav");
|
||||
|
||||
Reference in New Issue
Block a user