diff --git a/docs/search-chrome-behaviour.md b/docs/search-chrome-behaviour.md index 4702b419df..f3a013677f 100644 --- a/docs/search-chrome-behaviour.md +++ b/docs/search-chrome-behaviour.md @@ -118,9 +118,17 @@ chrome and changes to it land on every mode at once. Keep these rules: it appears. The `role="status"` / `aria-live="polite"` announcement stays either way — except while faulted, when the spine goes `aria-live="off"` and the fault panel's `role="alert"` makes the single announcement instead of both speaking. -3. **Sort is a segmented control, not a select.** Two values do not justify a menu you must open - to read. `ResultSortControl` renders `sortOptions` as `aria-pressed` buttons inside a - `role="group"` named "Sort results"; add a third order only if it still fits the rail. +3. **Sort is a segmented control, not a select — and it is `sm`-and-up.** Two values do not + justify a menu you must open to read. `ResultSortControl` renders `sortOptions` as + `aria-pressed` buttons inside a `role="group"` named "Sort results"; add a third order only if + it still fits the rail. Below 640px it is `hidden`: the two segments cost roughly half the + band's one line, and the query truncated to pay for a control set about once a session. Only + the affordance is `sm`-and-up — `?sort=` still carries an alpha order onto a phone and the + results honour it. The display class belongs in the component's own base string, because `cn` + is a plain join with no Tailwind conflict resolution. A page whose only utility is sort hides + the whole utilities group below `sm` (`hasPhoneUtilities`) rather than leaving an empty flex + child — in `inline` placement under 414px that child is `w-full basis-full`, i.e. a blank + second line. 4. **Native selects are pinned to 16px below `sm`.** The unlayered iOS anti-zoom rule in `globals.css` ("Interactive element defaults") deliberately beats Tailwind's `text-*` utilities on `input`/`select`/`textarea`. Do not fight it with `!important` or a per-call-site diff --git a/lighthouse-budget.json b/lighthouse-budget.json index ef2d06ca3f..112dedb74e 100644 --- a/lighthouse-budget.json +++ b/lighthouse-budget.json @@ -20,75 +20,75 @@ }, "baseline": { "desktop-documents-search": { - "lcpMs": 912.6572000000001, - "cls": 0.09676386467668462, - "tbtMs": 77.5, + "lcpMs": 887, + "cls": 0.119, + "tbtMs": 1, "fcpMs": 404.55240000000003, - "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/150.0.0.0 Safari/537.36" + "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.0.0 Safari/537.36" }, "desktop-dsm": { - "lcpMs": 938.4955500000002, - "cls": 0.01330779747882682, + "lcpMs": 936, + "cls": 0.013, "tbtMs": 0, "fcpMs": 399.6637, - "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/150.0.0.0 Safari/537.36" + "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.0.0 Safari/537.36" }, "desktop-forms": { - "lcpMs": 1567.6434999999997, - "cls": 0.05555523904347394, + "lcpMs": 870, + "cls": 0.06, "tbtMs": 0, "fcpMs": 393.5287, - "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/150.0.0.0 Safari/537.36" + "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.0.0 Safari/537.36" }, "desktop-root": { - "lcpMs": 935.5017499999998, - "cls": 0, - "tbtMs": 64.99999999999989, + "lcpMs": 822, + "cls": 0.007, + "tbtMs": 3, "fcpMs": 358.3345, - "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/150.0.0.0 Safari/537.36" + "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.0.0 Safari/537.36" }, "desktop-therapy-compass": { - "lcpMs": 1024.6195499999997, + "lcpMs": 822, "cls": 0, - "tbtMs": 42, + "tbtMs": 0, "fcpMs": 397.3599, - "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/150.0.0.0 Safari/537.36" + "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.0.0 Safari/537.36" }, "mobile-documents-search": { - "lcpMs": 2357.43, + "lcpMs": 2311, "cls": 0, - "tbtMs": 398.87499999999864, + "tbtMs": 399, "fcpMs": 2329.335, - "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/150.0.0.0 Safari/537.36" + "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.0.0 Safari/537.36" }, "mobile-dsm": { - "lcpMs": 2744.673, + "lcpMs": 2319, "cls": 0, - "tbtMs": 367.6859999999997, + "tbtMs": 322, "fcpMs": 2325.841, - "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/150.0.0.0 Safari/537.36" + "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.0.0 Safari/537.36" }, "mobile-forms": { - "lcpMs": 2359.54, - "cls": 0.08045469317717091, - "tbtMs": 362.06400000000167, + "lcpMs": 2304, + "cls": 0.08, + "tbtMs": 324, "fcpMs": 2291.215, - "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/150.0.0.0 Safari/537.36" + "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.0.0 Safari/537.36" }, "mobile-root": { - "lcpMs": 3325.742, + "lcpMs": 3274, "cls": 0, - "tbtMs": 638.9019999999982, - "fcpMs": 3325.742, - "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/150.0.0.0 Safari/537.36" + "tbtMs": 763, + "fcpMs": 3274, + "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.0.0 Safari/537.36" }, "mobile-therapy-compass": { - "lcpMs": 2791.386, + "lcpMs": 2338, "cls": 0, - "tbtMs": 341.201, + "tbtMs": 302, "fcpMs": 2327.357, - "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/150.0.0.0 Safari/537.36" + "chromeVersion": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/151.0.0.0 Safari/537.36" } }, - "updatedAt": "2026-08-05T08:26:50.745Z" + "updatedAt": "2026-08-07T13:42:17.043Z" } diff --git a/src/components/clinical-dashboard/search-results-header-band.tsx b/src/components/clinical-dashboard/search-results-header-band.tsx index 94e168b75f..b86520a55d 100644 --- a/src/components/clinical-dashboard/search-results-header-band.tsx +++ b/src/components/clinical-dashboard/search-results-header-band.tsx @@ -65,7 +65,9 @@ function singularNoun(plural: string) { } /** Sort is a two-state choice, so it reads as a segmented control rather than a - select: a dropdown over two values makes you open a menu to learn nothing. */ + select: a dropdown over two values makes you open a menu to learn nothing. + It is a `sm`-and-up control — see `ResultSortControl` for why the phone line + drops it. */ const sortOptions: ReadonlyArray<{ value: ResultSortValue; label: string }> = [ { value: "relevance", label: "Relevance" }, { value: "alpha", label: "A–Z" }, @@ -259,6 +261,14 @@ export function SearchResultsHeaderBand({ const hasUtilities = Boolean( onSortChange || onViewChange || onSaveSearch || utilityControls || pageMobileControls || (partial && onRetry), ); + // Sort is the one utility that does not render below `sm`. A page whose only + // utility is sort would otherwise keep this group mounted on a phone as an + // empty flex child — and in `inline` placement below 414px that child is + // `w-full basis-full`, so it would take a whole empty second line under the + // count. Hide the group itself there instead of leaving a ghost row. + const hasPhoneUtilities = Boolean( + onViewChange || onSaveSearch || utilityControls || pageMobileControls || (partial && onRetry), + ); // See `mobileControlsPlacement`: absent a declaration, a page control is // assumed to be a full-width select and keeps its own row, and a band with no // page control collapses to one line. @@ -428,7 +438,8 @@ export function SearchResultsHeaderBand({