Skip to content

fix(lab): MobilePowerSearch announces empty and unavailable states only from the open step - #8769

Merged
imdreamrunner merged 1 commit into
mainfrom
fix/lab-mobile-powersearch-stale-announcements
Oct 28, 2026
Merged

imdreamrunner merged 1 commit into
mainfrom
fix/lab-mobile-powersearch-stale-announcements

Conversation

@imdreamrunner

Copy link
Copy Markdown
Contributor

fix(lab): MobilePowerSearch speaks a sheet's empty-result and unavailable messages only while that step is open

Lab only: packages/lab/src/MobilePowerSearch/MobilePowerSearch.tsx and its test. Follow-up to #8740. One commit on main.

User impact

Screen-reader users of Lab MobilePowerSearch after #8740, in two states. (1) In Add filter with a content search, typing a query that lists suggestions and then leaving the sheet — Back, Escape, the scrim — hears "No results found", though results were listed and nothing was searched for: on the page after Escape, or inside the Filters dialog after Back. (2) After editing a filter and closing the value step, a controlled config update that drops that filter's field or operator writes "This filter is no longer available" with no filter open; the words surface in the next step that opens (editing a different filter speaks the stale message), and reopening the same stale filter speaks nothing, because its occasion is unchanged. Restoring it makes each message speak only while its step is the open one, and again whenever the step reopens on the same occasion.

Problem and solution fit

Why does it occur? BottomSheet keeps a closed sheet's body mounted, and #8740's SheetEmptyMessage spoke whenever its occasion changed, with no notion of whether anyone was in the sheet. contentResults is emptied whenever step !== 'fields', so the step change itself produced an "empty result"; and the draft outlives its step, so a later config update changed the unavailable message's occasion inside a closed dialog — where useAnnounce holds the words until that dialog's channel is exposed, which is when the next step opens.

Why does it harm the task? An announcement that describes a state the person is not in misreports what happened — a search that found nothing, a filter that vanished — and interrupts whatever they moved on to.

Why does that harm matter? component:PowerSearch FR18 limits the empty-result message to a query whose result set is empty, and FR14 ties the unavailable message to the filter being edited, inside the sheet; AR6 says every announcement a sheet makes is about that sheet's content while it is open. A message spoken from a closed sheet breaks the promise the flow's in-sheet announcement route exists to keep.

The narrow fix: SheetEmptyMessage takes isShown — its step being the open one. Hidden, it speaks nothing and forgets its spoken occasion; shown, it speaks a new occasion once. The three call sites pass step === 'fields' (both Add filter messages) and step === 'value' (the unavailable state). Nothing else about the messages, the results list or the aria-controls target changes.

Expected behavior and authority

Smallest restoration

MobilePowerSearch.tsx: one prop (isShown) on the internal SheetEmptyMessage, one early return in its effect that also resets spokenOccasionRef, three call sites gated on the current step. No prop, visual, default or interaction change; the message's element, id and text are as before.

Evidence

  • Reproduction before the change (this test file on main's component, checked by stashing the source): "does not announce 'No results found' when Add filter is left after a query that listed suggestions" fails — expected 'No results found' to be '' in the page region after Back; "announces the unavailable state only while its step is open, and again when the same stale filter reopens" fails — the words surface in the live region of the next step opened (editing "Author is Ada").
  • Result after the change: both pass. Nothing is spoken on Back or Escape after a query that listed suggestions; a config update after the value step closed speaks nothing, now or in the next step; reopening the stale filter speaks "This filter is no longer available" in its own dialog.
  • Representative unchanged path: the existing tests — "speaks 'No filters match your search' from its rendered element once per query", the content-search aria-controls target, "moves focus to Remove … and announces it in the sheet" — pass unchanged, so a message in the open step still speaks once per occasion.
  • Regression test or other mutation-sensitive proof: the two tests above; removing the isShown gate fails the first, removing the occasion reset (keeping the gate) fails the second's reopen assertion.

Scope

  • One defect is restored (two symptoms of the one missing step gate).
  • Separable contradictory or unsettled tagalongs were removed or split: none; Core untouched.
  • No new public API, visual representation, default, or interaction model is hidden under the bug-fix label.
  • Public text and artifacts contain no internal Meta context.

Testing

  • pnpm exec vitest run packages/lab/src/MobilePowerSearch — 116 tests pass (114 + the two regressions); on main's component with this test file, the two regressions fail as described.
  • Strict lint on packages/lab/src/MobilePowerSearch/ — 0 findings; prettier and git diff --check clean.
  • No real-browser state depends on this change: the live regions are DOM text, asserted directly by the tests.

…able messages only while that step is open

A closed step's body stays mounted, so its SheetEmptyMessage could change
occasion with no one in the sheet: leaving Add filter after a query that listed
suggestions spoke "No results found" (the results are emptied once the step is
not 'fields'), and a config update that dropped the last edited field or
operator after the value step closed wrote "This filter is no longer available"
into the closed dialog, where the words surfaced in the next step that opened,
while reopening the same stale filter spoke nothing (same occasion). The
message now takes isShown — its step being the open one — speaks only then,
and forgets its occasion while hidden, so the same one is spoken again when the
step reopens on it.
@vercel

vercel Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Oct 28, 2026 1:04am UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🔄 In progress (for maintainers only) Oct 28, 2026, 1:12 AM UTC

@github-actions

Copy link
Copy Markdown
Contributor

PR Analysis Report

Previews ready: Storybook and Sandbox were built with this PR's docsite. CI evidence will be added when available.

View Storybook for this PR · View Sandbox for this PR

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 28, 2026
@imdreamrunner
imdreamrunner merged commit 075fb3b into main Oct 28, 2026
65 checks passed
@github-actions
github-actions Bot deleted the fix/lab-mobile-powersearch-stale-announcements branch October 28, 2026 06:17

This branch was successfully deployed

1 active deployment
Preview — c835c370 Deployed Oct 28, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant