From 8aa9725feb5a71622ccff026861cc42990bcec6f Mon Sep 17 00:00:00 2001 From: Roland Date: Sun, 2 Aug 2026 14:45:49 -0600 Subject: [PATCH] ui: the corner triggers, the More button, and the search modal Four faults, each measured in the running app before and after. The search glyph carried Semantic's `item` class, which has had no rules at all since Semantic was removed: no pointer cursor, no hover, and an 18.6px hit area against a 54.4px bar. It is the same kind of thing as Help and Admin and now takes the same class. The share glyph did compute `cursor: pointer` -- it is an `` -- but its target was the 24px box the icon occupies, so the pointer appeared only if you found it exactly. Corner anchors now stretch and pad like a link. The More button rendered with NO class at all: a bare grey UA button while the rest of the bar took the user's colour. Menu.Target clones its child and hands it a className of its own, and the trigger spread those cloned props after its own `className` attribute, so the clone replaced ours. It is merged now. This was mine, from extracting NavDropdownTrigger last commit -- and it also made the previous commit's "measured and drawn are the same component" claim only half true, because the hidden placeholder is not cloned and so kept its class. The bar still wrapped, for a reason the padding fix could not reach: the corner does not keep a constant width. The Cmd-K hint renders only once useKeyboardDetected has seen a keypress, so it appears at an arbitrary later moment and widens the corner by ~30px; the load, memory, temperature and drive warnings come and go with the machine's state. None of that resizes the container, which was the only thing observed -- so nothing recalculated. That is the other half of "at certain widths": the same viewport wrapped or not depending on whether the user had touched a key. The corner and the home link are observed too now. The search modal showed an input and the first line of the first group. The suggestion list is absolutely positioned, which is right everywhere else -- a list that reflows the page while you type is unusable -- but in a modal it fails twice: an absolute list adds no height, so the panel sized itself to the search box alone at 114px, and the panel's own `overflow: auto` then clipped the list at that edge. In the modal the list sits in flow; the inverse is asserted so the rule cannot leak to the pages where overlaying is correct. Two of the new tests were wrong first and reverting the fix left them green: they asserted hand-written markup carrying the classes I expected the components to have, rather than the real SearchIconButton and ShareButton. They use the real components now. Every fix was then planted against: 5 red for the More class, 2 for the search class, 2 for the corner hit area, 1 for the observer, 2 for the modal. 1115 jest / 62 suites, 196 in ui-layout.cy.js, clean npm run build. Confirmed live: share and search both pointer at 54.4px, More white on the bar colour with a transparent face, and the modal's list in flow and unclipped. --- app/src/App.css | 24 ++ .../components/KeyboardShortcutsProvider.js | 11 + app/src/components/Nav.js | 14 +- app/src/components/Search.js | 11 +- app/src/components/ThemeSamplePage.js | 2 +- app/src/components/ui/ui-layout.cy.js | 329 ++++++++++++++++++ app/src/components/ui/ui.css | 16 + app/src/hooks/useOverflowNav.js | 31 +- 8 files changed, 431 insertions(+), 7 deletions(-) diff --git a/app/src/App.css b/app/src/App.css index 6f5a98df..5f68e862 100644 --- a/app/src/App.css +++ b/app/src/App.css @@ -79,6 +79,30 @@ html .wrolpi-navbar .mantine-ActionIcon-root:hover { display: flex; align-items: center; margin-left: 1.5em; + /* Full bar height, so the anchor inside has somewhere to stretch to. */ + align-self: stretch; +} + +/* + * An icon-only trigger in the corner gets a link's hit area, not its glyph's. + * + * The share glyph already computed `cursor: pointer` -- it is an `` -- but the + * target was the 24px box the icon occupies, so the pointer appeared only if you found it + * exactly, and there was no hover highlight to aim at. Stretched and padded, it behaves + * like Help and Admin beside it. + * + * `align-self` rather than `align-items: stretch` on the wrapper: the IconButtons in the + * corner have an explicit height, and a stretch container places an item it cannot stretch + * at the start -- which would push the hotspot and theme glyphs back off centre. + */ +.wrolpi-navbar-icon > a { + align-self: stretch; + padding: 0 0.5em; + cursor: pointer; +} + +.wrolpi-navbar-icon > a:hover { + background: rgba(0, 0, 0, 0.12); } /* diff --git a/app/src/components/KeyboardShortcutsProvider.js b/app/src/components/KeyboardShortcutsProvider.js index b79764ee..7fa6d729 100644 --- a/app/src/components/KeyboardShortcutsProvider.js +++ b/app/src/components/KeyboardShortcutsProvider.js @@ -83,6 +83,16 @@ function SearchModal({open, onClose}) { return ( + {/* + * `wrolpi-search-modal` makes the suggestion list part of the panel rather + * than an overlay on the page; see ui.css. Everywhere else the list floats + * over the page, which is right -- results that reflow the page while you + * type are unusable. Inside a modal it is wrong twice over: an absolutely + * positioned list adds no height, so the panel stayed 114px tall, and the + * panel's own `overflow: auto` then clipped the list at the panel's edge. + * The modal showed a search box and the first word of the first result. + */} +
+
); diff --git a/app/src/components/Nav.js b/app/src/components/Nav.js index 9baba2da..bc537cbc 100644 --- a/app/src/components/Nav.js +++ b/app/src/components/Nav.js @@ -111,8 +111,18 @@ function DropdownMenuItem({link}) { * button that eventually rendered -- the row overflowed by that much and the bar wrapped. * Measuring one thing and drawing another is only ever right by coincidence. */ -const NavDropdownTrigger = React.forwardRef(({text, ...props}, ref) => -