[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
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
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>
This commit was merged in pull request #46.
This commit is contained in:
@@ -4061,12 +4061,18 @@ body[data-operator-layout="broadcast"] #cw-bar-overlay {
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
/* The long ones, smaller so they fit whole rather than ellipsised. These
|
/* The long ones, sized against the screen rather than at a fixed size.
|
||||||
used to sit above the rule that sets the size for all of them — same
|
A tab is a fifth of the viewport, so what fits in it is a function of the
|
||||||
specificity, so the later one won and nothing was ever shortened. */
|
viewport — and only roughly of the font size, since how wide a platform
|
||||||
|
renders a word varies by ten per cent or more between machines. A fixed
|
||||||
|
0.6rem fit here with ten pixels to spare and clipped in CI.
|
||||||
|
|
||||||
|
(These rules also used to sit above the one that sets the size for all
|
||||||
|
labels — identical specificity, later in the file, so nothing was ever
|
||||||
|
shortened.) */
|
||||||
.tab[data-tab="bookmarks"] .tab-label,
|
.tab[data-tab="bookmarks"] .tab-label,
|
||||||
.tab[data-tab="statistics"] .tab-label {
|
.tab[data-tab="statistics"] .tab-label {
|
||||||
font-size: 0.6rem;
|
font-size: clamp(0.46rem, 2.2vw, 0.62rem);
|
||||||
}
|
}
|
||||||
/* "Digital modes" does not fit at any size worth reading, so the nav shows
|
/* "Digital modes" does not fit at any size worth reading, so the nav shows
|
||||||
the short form and the button carries the full one as its label. */
|
the short form and the button carries the full one as its label. */
|
||||||
@@ -4077,7 +4083,7 @@ body[data-operator-layout="broadcast"] #cw-bar-overlay {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-size: 0.6rem;
|
font-size: clamp(0.46rem, 2.2vw, 0.62rem);
|
||||||
}
|
}
|
||||||
.decoder-tab-select {
|
.decoder-tab-select {
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@@ -61,8 +61,14 @@ try {
|
|||||||
`the rig picker is ${layout.rigSelect}px wide at ${width}px`);
|
`the rig picker is ${layout.rigSelect}px wide at ${width}px`);
|
||||||
|
|
||||||
// The bottom nav keeps its labels — that is what makes it navigation
|
// The bottom nav keeps its labels — that is what makes it navigation
|
||||||
// rather than five glyphs — so the labels have to fit inside a tab, which
|
// rather than five glyphs — and a label used to overflow its tab and run
|
||||||
// is a fifth of a phone. They were being cut off mid-word: "igital mode".
|
// into the next one: "Bookmarks igital mode".
|
||||||
|
//
|
||||||
|
// What is asserted is that a label stays inside its own tab and, if it is
|
||||||
|
// too long for it, ends in an ellipsis. Not that it fits: how wide a
|
||||||
|
// platform draws a word varies by more than ten per cent, so "it fits"
|
||||||
|
// passes on the machine it was written on and fails on the next one —
|
||||||
|
// which is what a fixed font size did here.
|
||||||
const nav = await page.evaluate(() => {
|
const nav = await page.evaluate(() => {
|
||||||
const bar = document.querySelector(".tab-bar-nav");
|
const bar = document.querySelector(".tab-bar-nav");
|
||||||
return [...bar.querySelectorAll(".tab")]
|
return [...bar.querySelectorAll(".tab")]
|
||||||
@@ -70,16 +76,28 @@ try {
|
|||||||
.map((tab) => {
|
.map((tab) => {
|
||||||
const label = [...tab.querySelectorAll(".tab-label, .tab-label-short")]
|
const label = [...tab.querySelectorAll(".tab-label, .tab-label-short")]
|
||||||
.find((span) => getComputedStyle(span).display !== "none");
|
.find((span) => getComputedStyle(span).display !== "none");
|
||||||
|
const style = label ? getComputedStyle(label) : null;
|
||||||
|
const labelBox = label?.getBoundingClientRect();
|
||||||
|
const tabBox = tab.getBoundingClientRect();
|
||||||
return {
|
return {
|
||||||
text: (label?.textContent ?? "").trim(),
|
text: (label?.textContent ?? "").trim(),
|
||||||
clipped: label ? label.scrollWidth > label.clientWidth + 1 : false,
|
escapes: labelBox
|
||||||
|
? labelBox.left < tabBox.left - 1 || labelBox.right > tabBox.right + 1
|
||||||
|
: false,
|
||||||
|
truncates: style?.textOverflow === "ellipsis" && style?.overflow !== "visible",
|
||||||
|
empty: !labelBox || labelBox.width < 1,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
assert.ok(nav.length >= 4, `the bottom nav has ${nav.length} destinations at ${width}px`);
|
assert.ok(nav.length >= 4, `the bottom nav has ${nav.length} destinations at ${width}px`);
|
||||||
const clipped = nav.filter((tab) => tab.clipped).map((tab) => tab.text);
|
const escaped = nav.filter((tab) => tab.escapes).map((tab) => tab.text);
|
||||||
assert.deepEqual(clipped, [],
|
assert.deepEqual(escaped, [],
|
||||||
`labels cut off at ${width}px: ${clipped.join(", ")}`);
|
`labels overflowing their tab at ${width}px: ${escaped.join(", ")}`);
|
||||||
|
const untruncatable = nav.filter((tab) => !tab.truncates).map((tab) => tab.text);
|
||||||
|
assert.deepEqual(untruncatable, [],
|
||||||
|
`labels that would be cut rather than ellipsised at ${width}px: ${untruncatable.join(", ")}`);
|
||||||
|
const blank = nav.filter((tab) => tab.empty).map((tab, index) => tab.text || `#${index}`);
|
||||||
|
assert.deepEqual(blank, [], `destinations with no label at ${width}px: ${blank.join(", ")}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A tab whose visible label is shortened for the nav still has to say what
|
// A tab whose visible label is shortened for the nav still has to say what
|
||||||
|
|||||||
Reference in New Issue
Block a user