Skip to content

Fix duplicate clear (x) icons in search inputs - #4380

Open
builder-io-integration[bot] wants to merge 2 commits into
mainfrom
ai_main_dc3a06e5f4744b4692a3
Open

Fix duplicate clear (x) icons in search inputs#4380
builder-io-integration[bot] wants to merge 2 commits into
mainfrom
ai_main_dc3a06e5f4744b4692a3

Conversation

@builder-io-integration

@builder-io-integration builder-io-integration Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

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

  • Added search-field-owns-clear CSS rule in agent-native.css that disables -webkit-search-cancel-button, -webkit-search-decoration, -webkit-search-results-button, and -webkit-search-results-decoration via appearance: none.
  • Applied the search-field-owns-clear class to the search inputs in SettingsTabsPage.tsx, AgentTabsPage.tsx, and AdminShell (dispatch's admin-navigation.tsx), since each already renders its own clear button.
  • Added agent-native.spec.ts test asserting the CSS rule exists and stays scoped to the opt-in class (not a blanket input[type="search"] rule).
  • Added scripts/guard-single-search-clear.mjs, a new guard that scans .tsx/.jsx source for type="search" inputs and verifies each field with a custom clear button has the search-field-owns-clear class, and vice versa, flagging mismatches.
  • Registered the new guard as guard:single-search-clear in package.json and scripts/run-guards.ts.
  • Added a changeset documenting the fix for @agent-native/core and @agent-native/dispatch.

Edit in Builder  Preview


To clone this PR locally use the Github CLI with command gh pr checkout 4380

You can tag me at @BuilderIO for anything you want me to fix or change

@builder-io-integration builder-io-integration Bot changed the title fix: prevent duplicate search field clear controls Fix duplicate clear (x) icons in search inputs Sep 4, 2026

@builder-io-integration builder-io-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Comment on lines +43 to +46
// 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;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🟡 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.

Fix in Builder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant