From ef5a3a1dbc69facaacab5a614f843c2b61ca03e1 Mon Sep 17 00:00:00 2001 From: Roland Date: Wed, 5 Aug 2026 17:10:31 -0600 Subject: [PATCH] ui: a progress bar's track is its own edge, not a border Take the 1px outline off the bar without changing its size. `box-sizing: border-box` is global and the declared 1.375rem / 7.5rem were always the outer box, so nothing moves. What the border was quietly doing was giving the empty half of the track an edge, so the track now has to carry that itself: `--head` rather than `--bg`. A bar sits on a Panel as often as on the page -- Status and Downloads put them in Panels and table rows, uploads in modals -- and `--bg` is invisible against one of those two by definition, which is also why light mode needed its own `--panel` override. `--head` is off both surfaces in all four themes, and keeps the label's contrast against the empty track above 4.5:1 everywhere, which a lighter track (`--border`, 3.4:1 in night) would not. Asserted per theme in the component spec: no border on any edge, the height and min-width measured against `rem` rather than px, and the track distinct from the Panel beneath it. Putting the border back fails all four. --- app/src/components/ui/ui-layout.cy.js | 39 +++++++++++++++++++++++++++ app/src/components/ui/ui.css | 13 ++++----- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/app/src/components/ui/ui-layout.cy.js b/app/src/components/ui/ui-layout.cy.js index e1496b80..e391befc 100644 --- a/app/src/components/ui/ui-layout.cy.js +++ b/app/src/components/ui/ui-layout.cy.js @@ -955,6 +955,45 @@ describe('a progress bar has room for the label inside it', () => { }); }); + themeNames.forEach((theme) => { + it(`draws no outline of its own in ${theme}, and is the size it was with one`, () => { + /* + * The border came off. Both halves matter: the bar must not be the 1px smaller + * inside that removing an outline usually makes it -- it is not, because + * `box-sizing: border-box` is global and the declared height was always the outer + * box -- and the empty part of the track has to keep an edge of its own now that + * no line is drawing one, which is why the track paints `--head` rather than the + * `--bg` / `--panel` pair that a bar sits on. + * + * Measured against `rem`, not px: 1.375rem and 7.5rem move with `--ui-scale`. + */ + cy.mountUI(bar({percent: 40, label: 'CPU Usage'}), {theme}); + + cy.get('.wrolpi-progress').should(($bar) => { + const style = getComputedStyle($bar[0]); + ['Top', 'Right', 'Bottom', 'Left'].forEach(side => + expect(style[`border${side}Width`], `no border on the ${side} edge`) + .to.equal('0px')); + + const rem = 16 * uiScale(); + expect($bar[0].getBoundingClientRect().height, 'the bar is the height it was') + .to.be.closeTo(1.375 * rem, 0.5); + expect(parseFloat(style.minWidth), 'and the width it was') + .to.be.closeTo(7.5 * rem, 0.5); + }); + + // The Panel the bar sits on, which is what the track has to stay off. + cy.get('.wrolpi-progress').should(($bar) => { + const track = getComputedStyle($bar[0]).backgroundColor; + const panel = getComputedStyle($bar[0].closest('.wrolpi-panel')).backgroundColor; + expect(track, 'the track paints a surface of its own') + .to.not.match(/^rgba\(.*,\s*0(\.0+)?\)$/); + expect(contrast(toRgb(track), toRgb(panel)), 'track against the panel under it') + .to.be.greaterThan(1.05); + }); + }); + }); + it('keeps a long label on one line', () => { /* * `white-space: nowrap` on the label. The first version of this asserted the bar did diff --git a/app/src/components/ui/ui.css b/app/src/components/ui/ui.css index 0ab395bc..a3289aa2 100644 --- a/app/src/components/ui/ui.css +++ b/app/src/components/ui/ui.css @@ -1160,14 +1160,19 @@ html .mantine-Notification-closeButton:hover { * `overflow: hidden` is what keeps the indeterminate band inside the bar. Without it the * band slides from `margin-left: -35%` to `100%` in full view, so the animation ran from * outside the left edge to outside the right one, painting over whatever sat beside it. + * + * No border: the track is drawn by its own fill instead, so `--head` rather than `--bg`. + * A bar sits on a Panel as often as on the page, and `--bg` is invisible against one of + * those two by definition -- `--head` is off both in every theme. Height and min-width + * are the outer box (`box-sizing: border-box` is global), so dropping the 1px border left + * the bar exactly the size it was. */ .wrolpi-progress { position: relative; height: 1.375rem; min-width: 7.5rem; overflow: hidden; - background: var(--bg); - border: 1px solid var(--border); + background: var(--head); } /* @@ -1260,10 +1265,6 @@ html .mantine-Notification-closeButton:hover { * is lighter than black by definition. Left as it is, deliberately, rather than * asserted at a threshold chosen to pass. */ -html[data-theme="light"] .wrolpi-progress { - background: var(--panel); -} - html[data-theme="light"] .wrolpi-progress-fill { filter: brightness(1.75) saturate(0.55); }