Fix duplicate clear (x) icons in search inputs - #4380
Fix duplicate clear (x) icons in search inputs#4380builder-io-integration[bot] wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Builder reviewed your changes and found 1 potential issue 🟡
Review Details
Code Review Summary
PR #4380 adds an opt-in search-field-owns-clear class to the three currently identified custom-clear search inputs, scopes WebKit search pseudo-element suppression to that class, and adds a repository guard plus focused stylesheet coverage. The CSS approach is sound: it avoids removing the native clear affordance from search fields that do not render their own control, and the current Settings, AgentTabs, and Dispatch admin fields are paired correctly. The changeset also covers both affected publishable packages.
Key Findings
🟡 MEDIUM — The new guard's semantic detector is too heuristic: it considers any nearby aria-label containing “clear” to be a custom clear control, even when attached to a non-interactive element, while missing valid buttons named through text or title. This can allow future duplicate-clear regressions to pass the guard or produce false failures.
Verification
Focused review agents found no CSS or current-component defects beyond the guard issue. The dev server is healthy. Browser verification was attempted across Settings and Dispatch admin search flows, but the browser executor had no Chrome automation tools available, so all planned visual test cases were environment-unverifiable and should be rerun when browser tooling is provisioned.
Risk level: Standard, because this changes shared CSS and a repository-wide guard used across core and dispatch.
| // A clear control belonging to this field: an icon button whose accessible | ||
| // name says "clear", rendered inside the same relative wrapper. | ||
| const CLEAR_CONTROL_RE = | ||
| /aria-label=(?:"[^"]*clear[^"]*"|\{[^}]*[Cc]lear[^}]*\})/i; |
There was a problem hiding this comment.
🟡 Guard does not actually identify custom clear controls
CLEAR_CONTROL_RE treats any nearby aria-label containing “clear” as a custom clear control, without verifying that it belongs to an interactive button, and it misses valid custom clear controls named via button text or title. This makes the invariant bypassable and can allow a future duplicate native widget to pass the guard; constrain detection to interactive controls and cover these cases with fixtures, or use a more explicit reviewed marker.
Additional Info
Found by 1 of 2 review agents; reproduced with fixtures where a div has aria-label="Clear filters" and where a button uses title="Clear search" without aria-label.
Summary
Fixes the recurring bug where search fields (e.g. Settings page search bar) showed two "x" clear controls instead of one, by suppressing WebKit's native cancel widget on fields that render their own themed clear button.
Problem
On
type="search"inputs, WebKit paints its own built-in cancel/clear widget (::-webkit-search-cancel-button) in addition to any custom clear button rendered by the consuming component. This resulted in two visible "x" affordances side by side in the Settings search bar (and other similarly built search inputs), a bug reported multiple times previously.Solution
Introduced an opt-in CSS class,
search-field-owns-clear, applied to inputs that already render their own clear button. This class suppresses WebKit's native search decoration/cancel/results widgets via CSS pseudo-elements, so only the custom clear button remains. The suppression is scoped per-field (not global) so fields without a custom clear button retain the native widget as their only way to clear. A new guard script enforces this pairing repo-wide so the duplicate can't silently reappear.Key Changes
search-field-owns-clearCSS rule inagent-native.cssthat disables-webkit-search-cancel-button,-webkit-search-decoration,-webkit-search-results-button, and-webkit-search-results-decorationviaappearance: none.search-field-owns-clearclass to the search inputs inSettingsTabsPage.tsx,AgentTabsPage.tsx, andAdminShell(dispatch'sadmin-navigation.tsx), since each already renders its own clear button.agent-native.spec.tstest asserting the CSS rule exists and stays scoped to the opt-in class (not a blanketinput[type="search"]rule).scripts/guard-single-search-clear.mjs, a new guard that scans.tsx/.jsxsource fortype="search"inputs and verifies each field with a custom clear button has thesearch-field-owns-clearclass, and vice versa, flagging mismatches.guard:single-search-clearinpackage.jsonandscripts/run-guards.ts.@agent-native/coreand@agent-native/dispatch.To clone this PR locally use the Github CLI with command
gh pr checkout 4380You can tag me at @BuilderIO for anything you want me to fix or change