Keep the date on screen on a phone after Go, and hand focus back to the tab that folded

09eaf95 folded the Display sheet away on a narrow viewport once a date was set, and said the
strip then read the date. It did only in its text: the dock's tab list could not shrink, the
system view's five tabs take 397 px, and at 360 by 640 and 390 by 844 they pushed the date strip
to x 406-511, past the right edge of a page that does not scroll. With the sheet folded, the set
date was nowhere on screen; before the fold, the open field had at least shown it. And the fold
removed the form that held focus, so focus fell to the page and the next Tab started again at
Search, with nothing announcing the date.

The tab list now gives way (min-w-0) and scrolls (overflow-x-auto), and the date and range strips
keep their width (shrink-0). After a date is set on a phone, focus goes to the tab whose panel
folded, so Enter opens it again.

Live on :4301 in the Sun's system, Display, 2020-12-21T18:00, Enter: at 360x640 the panel folds,
the strip "Date 2020-12-21" sits at x 82-230 and the tabs scroll in 73 px (397 of content); at
390x844 the strip is at 112-260 and the tabs scroll in 103; page scrollWidth equals the viewport
at both, and the tab row stays 36 px high. Focus is on #dock-tab-display at both, and Enter
reopens the panel. At 1400x900 nothing changes: the panel stays open, focus stays in the field,
the tabs take their 437 px. Screenshots dock-go-360x640.png and dock-go-390x844.png, in the
review's scratchpad (wave1/solar/fixr2).

Tests: the tab list carries min-w-0 and overflow-x-auto and the date strip shrink-0 (jsdom lays
nothing out, so the classes are what can be checked there; the positions above are the app's),
and after Go on a phone the focused element is #dock-tab-display. Guarded mutants (full suite),
each failing only its named test: min-w-0 and overflow-x-auto removed, shrink-0 removed from the
date strip ('keeps the date strip on screen on a phone'), and the focus call removed ('hands
focus to the tab that folded').

Unit suite 864/864, tsc -p tsconfig.app.json and etl:typecheck clean.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-30 17:42:29 +02:00
co-authored by Claude Opus 5.5
parent 7080a5a817
commit 67a21b4a10
2 changed files with 32 additions and 3 deletions
@@ -467,6 +467,30 @@ describe('HudDockComponent', () => {
} }
}); });
it('hands focus to the tab that folded, not to the page, so Enter opens the panel again', () => {
viewport.wide = false;
try {
const field = host().querySelector<HTMLInputElement>('#clock-date')!;
field.focus();
field.value = '2020-12-21T18:00';
button('Go').click();
fixture.detectChanges();
expect(document.activeElement?.id).toBe('dock-tab-display');
} finally {
viewport.wide = true;
}
});
it('keeps the date strip on screen on a phone: the tabs give way to it, and scroll', () => {
// 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.detectChanges();
const tabs = host().querySelector('[role="tablist"]')!.classList;
expect(tabs.contains('min-w-0') && tabs.contains('overflow-x-auto')).toBe(true);
expect(host().querySelector('[data-testid="hud-date"]')!.classList.contains('shrink-0')).toBe(true);
});
it('keeps the panel open on a wide screen, where it covers little of the scene', () => { it('keeps the panel open on a wide screen, where it covers little of the scene', () => {
host().querySelector<HTMLInputElement>('#clock-date')!.value = '2020-12-21T18:00'; host().querySelector<HTMLInputElement>('#clock-date')!.value = '2020-12-21T18:00';
button('Go').click(); button('Go').click();
+8 -3
View File
@@ -415,7 +415,9 @@ function isWideViewport(): boolean {
} }
<div class="hud-brackets hud-surface pointer-events-auto flex w-full items-stretch"> <div class="hud-brackets hud-surface pointer-events-auto flex w-full items-stretch">
<div role="tablist" aria-label="Dock" class="flex items-stretch divide-x divide-border/40"> <!-- The tabs give way to the date and the range, and scroll: the five of the system view
take 397 px, and on a portrait phone they pushed the date off the right edge. -->
<div role="tablist" aria-label="Dock" class="flex min-w-0 items-stretch divide-x divide-border/40 overflow-x-auto">
@for (tab of tabs(); track tab) { @for (tab of tabs(); track tab) {
<button <button
type="button" type="button"
@@ -439,7 +441,7 @@ function isWideViewport(): boolean {
today's, which the reader's own machine already says. --> today's, which the reader's own machine already says. -->
@if (date()) { @if (date()) {
<p <p
class="ml-auto flex items-baseline gap-2 border-l border-border/40 px-3 py-2 sm:px-4" class="ml-auto flex shrink-0 items-baseline gap-2 border-l border-border/40 px-3 py-2 sm:px-4"
data-testid="hud-date" data-testid="hud-date"
> >
<span class="type-label text-muted">Date</span> <span class="type-label text-muted">Date</span>
@@ -448,7 +450,7 @@ function isWideViewport(): boolean {
} }
@if (range()) { @if (range()) {
<p <p
class="flex items-baseline gap-2 border-l border-border/40 px-3 py-2 sm:px-4" class="flex shrink-0 items-baseline gap-2 border-l border-border/40 px-3 py-2 sm:px-4"
[class.ml-auto]="!date()" [class.ml-auto]="!date()"
> >
<span class="type-label text-muted">Range</span> <span class="type-label text-muted">Range</span>
@@ -553,8 +555,11 @@ export class HudDockComponent implements OnInit {
this.dateField.set(field.value); this.dateField.set(field.value);
// On a phone the sheet covers the system it has just set the date of: at 360 by 640 every // On a phone the sheet covers the system it has just set the date of: at 360 by 640 every
// orbit lies behind it. The thing to look at is now the scene, as after a search. // orbit lies behind it. The thing to look at is now the scene, as after a search.
// Focus goes back to the tab that folded, not to the page: the form it was in is gone.
if (!isWideViewport()) { if (!isWideViewport()) {
const tab = this.activeTab();
this.activeTab.set(null); this.activeTab.set(null);
this.host.nativeElement.querySelector<HTMLElement>(`#dock-tab-${tab}`)?.focus();
} }
} }
} }