Skip to content

fix(MobilePowerSearch): refine touch filter flow - #8749

Merged
rubyycheung merged 2 commits into
mainfrom
ruby/mobile-powersearch-feedback
Oct 28, 2026
Merged

rubyycheung merged 2 commits into
mainfrom
ruby/mobile-powersearch-feedback

Conversation

@rubyycheung

@rubyycheung rubyycheung commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • keep mobile PowerSearch headers, search, and footers fixed while only result rows scroll
  • retain prior sheets during drill-down so Escape, scrim, and swipe reveal the previous step without a redundant Add filter Back button
  • use trailing remove actions for every removable filter, including one-tap boolean filters
  • leave Add filter search unfocused until the user selects it, avoiding an automatic software keyboard
  • place single-section value editors directly on the sheet surface; reserve muted containers for multi-section editors
  • simplify the empty Filters state to one centered Add filter action, without duplicate header Add or footer Done controls
  • keep Clear all in place behind confirmation and preserve read-only filters
  • preserve filter identity, stale-filter handling, disabled-flow behavior, focus recovery, and modal announcements from feat(lab): MobilePowerSearch gains the Core PowerSearch sheet's behavior #8740
  • retain fix(lab): MobilePowerSearch announces empty and unavailable states only from the open step #8769's rule that empty and unavailable states announce only from the open step while keeping the approved H4 groups and visual empty states

Test plan

  • pnpm exec vitest run packages/lab/src/MobilePowerSearch/MobilePowerSearch.test.tsx (115 tests)
  • targeted ESLint for MobilePowerSearch.tsx and MobilePowerSearch.test.tsx
  • repository pre-commit checks, including sync, knowledge, changesets, package boundaries, i18n, fixtures, and setup contract
  • Storybook production build
  • verified the updated touch flow in the iOS Simulator
  • Lab typecheck rerun currently reaches three unrelated existing errors in packages/lab/src/Comments/icons.test.tsx; no changed MobilePowerSearch file reports a type error

@vercel

vercel Bot commented Oct 27, 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 10:51pm UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🔄 In progress (for maintainers only) Oct 28, 2026, 10:54 PM UTC

@rubyycheung
rubyycheung force-pushed the ruby/mobile-powersearch-feedback branch from 3c3be1b to 8d684a5 Compare October 27, 2026 21:18
@rubyycheung
rubyycheung changed the base branch from ruby/mobile-tokenizer-search-border to main October 27, 2026 21:18
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 27, 2026
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

📚 Storybook Preview

View Storybook for this PR

🧪 Sandbox Preview

View Sandbox for this PR

Modified Components

MobilePowerSearch (@astryxdesign/lab) · View in Storybook
Metric Before After Delta
Entry File (ESM) 336B 336B 0B
Lines of Code 2748 3224 -
Complexity Very High Very High (463) -

Component Size

Component Import before Import after Delta CSS before CSS after Delta
lab/MobilePowerSearch 148.4KB 154.5KB +6.1KB ⚠️ 1.4KB 1.2KB -177B

Sizes are gzip. Import counts the JavaScript the import loads eagerly; CSS counts the package stylesheet rules referenced by the modules it can load from its own package, lazily loaded ones included.

⚠️ Touch-only size budget

These components grew past the touch-only budget (2 KB gzip JavaScript or 1 KB gzip CSS per component). If the growth runs only on a coarse pointer, load its JavaScript lazily so the import does not carry it, or justify the cost in the pull request description; CSS stays in the package stylesheet, so justify it.

Component JavaScript CSS
lab/MobilePowerSearch +6.1KB ⚠️ -177B

Bundle Size Summary

Gzip figures measure each package's entry file, not the code an import pulls in.

Package Entry (ESM) Entry gzip before Entry gzip after Delta
@astryxdesign/lab 4.6KB 1.9KB 1.9KB 0B
Package stylesheet Gzip before Gzip after Delta
@astryxdesign/lab 11.1KB 11.2KB +54B

Accessibility Audit

Status: No accessibility violations detected.


Generated by PR Enrichment workflow | Storybook | Sandbox | View full report

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval of this pull request needs an engineering owner's spec decision first: the Lab touch flow's new direction (a retained sheet stack, removal from the Filters rows, one-tap empty filters, a Clear all that keeps read-only filters, inline list and calendar editors, and timezoneID-based dates) has no current spec for the Lab component, and component:PowerSearch DEC-3 currently describes this flow and rejects two of those choices. An engineering owner settles it by amending that spec or recording governing spec for the Lab prototype and commenting /approve-spec <full head SHA> on this pull request; the author may do so if they are an engineering owner. Separately, please split this 2,045-line change and fix:

  • Date-only filters now show a time of day on tokens and Filters rows (MobilePowerSearch.tsx:679).
  • Typing in Search filters after scrolling the list keeps only the first letter (MobilePowerSearch.tsx:2160).
  • A filter such as Status is empty on a field with other operators is removed by one tap on its row and exposes no checked state (MobilePowerSearch.tsx:1998).

[Automated review]

) {
return formatDateDay(filter.value.unixSeconds, locale);
}
return formatFilterValue(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Date-only values now go through formatFilterValue, whose formatDateAbsolute always adds hour and minute, so a date-only filter's token and Filters row read like Mar 9, 2024, 7:00 PM (and a day picked in the calendar reads 12:00 AM). Consider formatting date_absolute values whose operator is date-only as a day in timezoneID, keeping the time only for isDateOnly: false.

const fieldLabel =
config.getField(row.filter.field)?.label ??
row.filter.field;
const isImmediateToggle = operator?.value.type === 'empty';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes every empty-operator filter a one-tap removal, but handleFieldSelect only treats single-operator fields that way. For a field like Status with is / is not / is empty, a Status is empty row can no longer be edited and a tap removes it. The checked indicator is aria-hidden on a plain button, so assistive tech gets no checked state either. Suggest limiting this to single-operator fields and exposing the state (a checkbox with aria-checked) or naming the action.

<CheckboxIndicator state="checked" />
) : (
<IconButton
label={`Remove ${fieldLabel} filter`}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two filters on the same field get identical names (Remove Author filter twice), so screen-reader and voice users can't tell which one a button removes. Naming it from the row's full description (for example Remove Author is Ada) would disambiguate.

}}
<div
{...scrollViewportProps}
onScroll={blurFieldPickerSearch}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blurring on every scroll also fires when typing narrows the list: the browser clamps scrollTop, a scroll event follows, and the search loses focus mid-word. In Chromium, after scrolling Add filter and typing pri into Search filters, only p remains. Dismissing the keyboard only on a user drag (the onTouchMove path) avoids it.

[selectedItems],
);

useEffect(() => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

results starts as [] and is filled after a setTimeout, so the first render shows No results found before the search source answers. A pending state until the first search settles would avoid the flash; since this effect calls the caller's search source and sets state, a comment naming that external system would also help.

icon={<Icon icon="search" size="lg" color="secondary" />}
title={
allowsCreate && query.trim() === ''
? `Add ${label === 'ID' ? 'an ID' : 'a value'}`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This picks Add an ID only when the caller's field label is exactly ID and builds the sentence from English literals, so other labels and locales get Add a value. One translated message with the field label as a placeholder would cover every field.

@rubyycheung
rubyycheung force-pushed the ruby/mobile-powersearch-feedback branch from 9e83893 to 8a31f7e Compare October 28, 2026 18:09
@rubyycheung
rubyycheung marked this pull request as ready for review October 28, 2026 18:09
@rubyycheung
rubyycheung force-pushed the ruby/mobile-powersearch-feedback branch from 8a31f7e to f667979 Compare October 28, 2026 18:19
@rubyycheung rubyycheung reopened this Oct 28, 2026
@rubyycheung
rubyycheung force-pushed the ruby/mobile-powersearch-feedback branch from 153fc57 to c73efd0 Compare October 28, 2026 22:43
@rubyycheung
rubyycheung merged commit 0720bfa into main Oct 28, 2026
92 of 129 checks passed

This branch was successfully deployed

1 active deployment
Preview — c73efd0d 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.

2 participants