From 0a88797ff4a5db778b1669dd8c6470a16c2c570b Mon Sep 17 00:00:00 2001 From: Senrokai Date: Wed, 30 Sep 2026 19:44:59 +0200 Subject: [PATCH] Keep the dock's tabs in sight around the date strip, on phones and narrow desktop windows 67a21b4 let the dock's tabs give way to the date and range strips and scroll, and measured phones only after Go. Reviewers found four things it did not measure: - At the present, the state the map opens in, the Range strip, now 121 px and unshrinkable, took the tabs' width on a portrait phone: Display showed 0 of 79 px at 360, 390 and 412 wide, and Bookmarks 0, 27 and 49 of 95. Before, the strip sat off screen at x 406-502. It is now hidden below sm. - After Go on a phone, focus went back to the Display tab while the list was still wide; the strip then narrowed it and its scroll stayed, so the focused tab was 0 of 79 px in sight (a focus ring off screen), and on Saturn's page the Clock tab 28 of 63. The focused tab, else the selected one, is now scrolled into view after each render in which the strip comes or goes (afterRenderEffect on whether a date is shown). - On desktop windows 600 to 770 px wide the tab list drew the browser's classic scrollbar, light and 15 px tall, in the dark dock, and at 640 the open Display panel's tab was scrolled out of sight. The list now asks for a thin dark one (scheme-dark, scrollbar-width: thin); the tab is brought back as above. - The range strip's shrink-0 had no test: without it '417 AU' wraps and the row grows from 38 to 58 px. Measured on :4301 in the Sun's system, keyboard only (Tab to Display, Enter, Tab to the date, 2020-12-21T18:00, Enter), visible px of each tab: - 360x640 phone, at the present: Bookmarks 95/95, Display 24/79 (was 0), range hidden. After Go: the focused Display 78/79 (was 0), the date on screen, no page scroll. 390x844: 54/79 then 78/79. 412x915: 76/79 then 78/79. - Saturn's page at 360x640, after Go: the focused Clock tab 63/63. - 600x800 desktop: every tab in full before and after Go, no scrollbar. - 640x900, 700x900, 768x1024 desktop, after Go: the open Display tab 87/87, a dark scrollbar 10 px tall (row 43 px, was 48 with a light one). - 1400x900: unchanged, row 38 px. With no strip at all, a phone's row is now 33 px tall at the present and 38 once a date is set; the off-screen range strip used to hold it at 38. Tests: 'keeps the date strip on screen on a phone' now also sets a range and expects it shrink-0 and max-sm:hidden, and the list scheme-dark and a thin scrollbar; 'brings the tab that matters back into view once the date strip has narrowed the tabs' checks the focused tab on a phone and the selected tab on a wide screen. Guarded mutants, each failing its named test alone: the range's shrink-0 dropped, the range shown on a phone, the default scrollbar, no tab scrolled into view, the selected tab only, and the effect not keyed on the strip. Unit suite 870 passed. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../features/hud/hud-dock.component.spec.ts | 41 +++++++++++++++++++ src/app/features/hud/hud-dock.component.ts | 32 +++++++++++++-- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/app/features/hud/hud-dock.component.spec.ts b/src/app/features/hud/hud-dock.component.spec.ts index 4598890..a0ce7ee 100644 --- a/src/app/features/hud/hud-dock.component.spec.ts +++ b/src/app/features/hud/hud-dock.component.spec.ts @@ -485,10 +485,51 @@ describe('HudDockComponent', () => { // At 360 px the system view's five tabs take 397 px, and pushed the strip past the right // edge, where nothing scrolls: after Go on a phone the date was nowhere on screen. fixture.componentRef.setInput('date', '2020-12-21'); + fixture.componentRef.setInput('range', '417 AU'); fixture.detectChanges(); const tabs = host().querySelector('[role="tablist"]')!.classList; expect(tabs.contains('min-w-0') && tabs.contains('overflow-x-auto')).toBe(true); + // Its own scrollbar, where the browser draws one, thin and dark: a desktop's default was a + // light bar 15 px tall across the dock. + expect(tabs.contains('scheme-dark') && tabs.contains('[scrollbar-width:thin]')).toBe(true); expect(host().querySelector('[data-testid="hud-date"]')!.classList.contains('shrink-0')).toBe(true); + // The range keeps its width where it is shown, or '417 AU' wraps and the row grows 20 px; on a + // phone it is not shown, where at the present it took the Display tab out of sight. + const range = [...host().querySelectorAll('p')].find((p) => p.textContent?.includes('Range'))!.classList; + expect(range.contains('shrink-0') && range.contains('max-sm:hidden')).toBe(true); + }); + + it('brings the tab that matters back into view once the date strip has narrowed the tabs', () => { + // jsdom lays nothing out; what is checked is which tab is asked to be in view, and when. + const scrolled: string[] = []; + HTMLElement.prototype.scrollIntoView = function (this: HTMLElement) { + scrolled.push(this.id); + }; + try { + // On a phone: the tab focus went back to, which after Go sat wholly out of sight. + viewport.wide = false; + host().querySelector('#clock-date')!.value = '2020-12-21T18:00'; + button('Go').click(); + fixture.detectChanges(); + scrolled.length = 0; + fixture.componentRef.setInput('date', '2020-12-21'); + fixture.detectChanges(); + expect(scrolled).toEqual(['dock-tab-display']); + // On a wider window, where the panel stays open: its tab, focus being in the panel. + viewport.wide = true; + fixture.componentRef.setInput('date', ''); + fixture.detectChanges(); + tab('Display').click(); + fixture.detectChanges(); + host().querySelector('#clock-date')!.focus(); + scrolled.length = 0; + fixture.componentRef.setInput('date', '2020-12-21'); + fixture.detectChanges(); + expect(scrolled).toEqual(['dock-tab-display']); + } finally { + viewport.wide = true; + delete (HTMLElement.prototype as Partial).scrollIntoView; + } }); it('keeps the panel open on a wide screen, where it covers little of the scene', () => { diff --git a/src/app/features/hud/hud-dock.component.ts b/src/app/features/hud/hud-dock.component.ts index c9b6759..a7ce49c 100644 --- a/src/app/features/hud/hud-dock.component.ts +++ b/src/app/features/hud/hud-dock.component.ts @@ -1,4 +1,5 @@ import { + afterRenderEffect, ChangeDetectionStrategy, Component, computed, @@ -416,8 +417,14 @@ function isWideViewport(): boolean {
-
+ take 397 px, and on a portrait phone they pushed the date off the right edge. Where + the browser draws a scrollbar of its own, it is a thin dark one: on a desktop window + under 770 px wide its default was a light bar 15 px tall across the dark dock. --> +
@for (tab of tabs(); track tab) {