[feat](trx-frontend-http): box the selected tab instead of underlining it
CI / lint (push) Successful in 2m23s
CI / test (push) Successful in 8m19s
CI / frontend (push) Successful in 3m10s
CI / reuse (push) Successful in 3s

The desktop strip marked the current page with a 2px underline while the
mobile bottom nav already boxed it, so one navigation model looked like
two.  The box now sits on both: a transparent 1px border on the base
reserves it, so switching pages moves no neighbours, and hover fills a
fainter version of the same shape.  Tools carries it too — that button
is marked active for the destinations the strip hides.

Dropping the mobile rule's border-bottom:none, which only existed to
cancel the old desktop underline, closes the bottom edge its active box
had been missing.  The smoke test checks all four edges.

Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
sjg
2026-08-03 20:37:31 +02:00
parent 6f53592041
commit 889d00007d
2 changed files with 37 additions and 8 deletions
@@ -10,7 +10,7 @@ import { fileURLToPath } from "node:url";
import { chromium } from "playwright-core";
// page.evaluate callbacks run in the browser, not in this Node process.
/* global document */
/* global document, getComputedStyle */
const frontendDir = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
const webDir = path.resolve(frontendDir, "../assets/web");
@@ -213,6 +213,21 @@ try {
await page.locator("#aprs-map .leaflet-pane").first().waitFor({ state: "attached" });
assert.equal(new URL(page.url()).pathname, "/map");
// The selected destination is marked by a box on all four sides, so a rule
// that drops one edge (the mobile nav used to lose its bottom border) is a
// regression even though the tab still reads as "active".
const activeTab = await page.evaluate(() => {
const style = getComputedStyle(document.querySelector(".tab-bar-nav .tab.active"));
return ["Top", "Right", "Bottom", "Left"].map((side) => ({
width: style.getPropertyValue(`border-${side.toLowerCase()}-width`),
color: style.getPropertyValue(`border-${side.toLowerCase()}-color`),
}));
});
for (const edge of activeTab) {
assert.notEqual(edge.width, "0px", `active tab border: ${JSON.stringify(activeTab)}`);
assert.ok(!/rgba\(0, 0, 0, 0\)|transparent/.test(edge.color), `active tab border: ${JSON.stringify(activeTab)}`);
}
// The map is full-bleed: it breaks out of the centred .card column and
// reaches both viewport edges, without pushing the page sideways.
const stage = await page.evaluate(() => {