From c143a7cf322b407e8091ca4e27a16e92a5178cef Mon Sep 17 00:00:00 2001 From: rcourtman Date: Sun, 2 Aug 2026 21:31:20 +0100 Subject: [PATCH] Bound search history popover width --- .../subsystems/frontend-primitives.md | 4 ++ frontend-modern/browser-verification.json | 53 ++++++++----------- .../shared/__tests__/SearchInput.test.tsx | 24 +++++++++ .../shared/searchInputEnhancementsModel.ts | 2 +- 4 files changed, 50 insertions(+), 33 deletions(-) diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md index e942a69c9..d0fe4fcec 100644 --- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md +++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md @@ -3938,6 +3938,10 @@ tips/history interaction runtime, and history-toggle copy plus history-menu button and row class policy. Future search-input-enhancement work should extend those owners instead of pushing history copy or menu presentation policy back into the shell. +Search-history menus must remain full-width on narrow search surfaces while +using a bounded desktop width aligned to the search field's leading edge; a +full-page or full-toolbar search field must not turn the history popover into a +screen-wide overlay that obscures unrelated controls. The shared search tips popover now follows that same owner split. `frontend-modern/src/components/shared/SearchTipsPopover.tsx` stays the render shell, `frontend-modern/src/components/shared/useSearchTipsPopoverState.ts` diff --git a/frontend-modern/browser-verification.json b/frontend-modern/browser-verification.json index 585a08563..fac590dae 100644 --- a/frontend-modern/browser-verification.json +++ b/frontend-modern/browser-verification.json @@ -1,17 +1,13 @@ { "version": 1, - "base_sha": "1ed7004d067f3bf451184da04754206b8ad3fe23", - "verified_at": "2026-08-02T20:11:54Z", + "base_sha": "b3dbc26d545b7526f62ed466884c4006f07cf8cb", + "verified_at": "2026-08-02T20:27:26Z", "result": "passed", "changed_paths": [ - "frontend-modern/src/components/shared/FilterBar/AddFilterMenu.tsx", - "frontend-modern/src/components/shared/FilterBar/FilterBar.tsx", - "frontend-modern/src/components/shared/FilterBar/filterCatalog.ts" + "frontend-modern/src/components/shared/searchInputEnhancementsModel.ts" ], "content_sha256": { - "frontend-modern/src/components/shared/FilterBar/AddFilterMenu.tsx": "f5fcfb1db804ea313d3cf2c885423b67de2c707ea1f3cba3ce65c16f4085fb1f", - "frontend-modern/src/components/shared/FilterBar/FilterBar.tsx": "438e37d0c1698584bb6dcb69ef01cd07c0d70b23a0f242e92ebff6771f1e98c9", - "frontend-modern/src/components/shared/FilterBar/filterCatalog.ts": "2991ee70854100a4fbdd8f0e7adb066e9a3c2d7654e32e52c261a61048a3727c" + "frontend-modern/src/components/shared/searchInputEnhancementsModel.ts": "cd34929cd632fcf6eda163b34def13df0666d91f279e5df9e329ee8b0b05ee33" }, "routes": [ "/proxmox/overview" @@ -21,38 +17,31 @@ "width": 1280, "height": 900 }, - { - "width": 1024, - "height": 768 - }, - { - "width": 768, - "height": 800 - }, { "width": 640, "height": 800 + }, + { + "width": 390, + "height": 844 } ], "states": [ "Desktop default filter toolbar", - "Desktop View preferences open", - "Desktop last available Node filter active", - "Tablet default filter toolbar", - "Tablet View preferences open", - "Tablet Columns disclosure open", - "Narrow filter controls collapsed", - "Narrow filter controls expanded", - "Narrow last available Node filter active", - "Narrow cleared filter state with Add filter restored" + "Desktop empty search-history menu", + "Desktop populated search-history menu", + "Desktop active search with history closed", + "Tablet-width empty search-history menu", + "Phone-width populated search-history menu", + "Restored empty search and cleared history" ], "interactions": [ - "Opened View preferences at desktop and tablet widths and confirmed the panel remained inside the viewport", - "Opened Columns at the 768px breakpoint and confirmed its content remained reachable above the bottom navigation", - "Expanded narrow filter controls and selected Node pve1", - "Confirmed the exhausted Add filter control disappeared while the active chip, Saved, Clear filters, and View controls remained usable", - "Cleared the active Node filter and confirmed Add filter and its Node option returned", - "Repeated the last-filter activation and clear-and-restore flow at 1280px", - "Checked browser console warnings and errors" + "Opened the empty search-history menu and confirmed it remained bounded to 512px on the 1280px desktop viewport", + "Confirmed the same menu used the full available search width at 640px and 390px", + "Measured zero document-level horizontal overflow at all three verified widths", + "Entered edge, committed it with Enter, and confirmed the search filtered the workload table", + "Reopened history and confirmed the populated entry and clear-history action rendered within the bounded menu", + "Closed history and confirmed the active-search filter toolbar remained usable", + "Cleared history and the active search, then confirmed the overview returned to its clean default state" ] } diff --git a/frontend-modern/src/components/shared/__tests__/SearchInput.test.tsx b/frontend-modern/src/components/shared/__tests__/SearchInput.test.tsx index f6ccfbf78..58032c8b9 100644 --- a/frontend-modern/src/components/shared/__tests__/SearchInput.test.tsx +++ b/frontend-modern/src/components/shared/__tests__/SearchInput.test.tsx @@ -79,10 +79,34 @@ describe('SearchInput', () => { expect(searchInputEnhancementsModelSource).toContain('getSearchHistoryToggleTitle'); expect(searchInputEnhancementsModelSource).toContain('SEARCH_HISTORY_CLEAR_LABEL'); expect(searchInputEnhancementsModelSource).toContain('SEARCH_HISTORY_MENU_CLASS'); + expect(searchInputEnhancementsModelSource).toContain('w-full max-w-lg'); + expect(searchInputEnhancementsModelSource).not.toContain('left-0 right-0 top-full'); expect(searchInputEnhancementsModelSource).toContain('h-10 w-10'); expect(searchInputEnhancementsModelSource).toContain('sm:h-7 sm:w-7'); }); + it('caps the history menu on wide search surfaces without narrowing mobile layouts', () => { + const HistoryHarness = () => { + const [value, setValue] = createSignal(''); + + return ( + + ); + }; + + render(() => ); + + fireEvent.click(screen.getByRole('button', { name: 'Show search history' })); + + const historyMenu = screen.getByRole('listbox'); + expect(historyMenu).toHaveClass('w-full', 'max-w-lg'); + expect(historyMenu).not.toHaveClass('right-0'); + }); + it('captures typed characters by default when focus is outside the input', async () => { render(() => ); diff --git a/frontend-modern/src/components/shared/searchInputEnhancementsModel.ts b/frontend-modern/src/components/shared/searchInputEnhancementsModel.ts index d4bc58531..51400170d 100644 --- a/frontend-modern/src/components/shared/searchInputEnhancementsModel.ts +++ b/frontend-modern/src/components/shared/searchInputEnhancementsModel.ts @@ -1,5 +1,5 @@ export const SEARCH_HISTORY_MENU_CLASS = - 'absolute left-0 right-0 top-full z-50 mt-2 w-full overflow-hidden rounded-md border border-border bg-surface text-sm shadow-sm'; + 'absolute left-0 top-full z-50 mt-2 w-full max-w-lg overflow-hidden rounded-md border border-border bg-surface text-sm shadow-sm'; export const SEARCH_HISTORY_EMPTY_STATE_CLASS = 'px-3 py-2 text-xs text-muted'; export const SEARCH_HISTORY_ROW_CLASS = 'flex items-center justify-between px-2 py-1.5 hover:bg-blue-50 dark:hover:bg-blue-900';