Opens in a new tabSkip to content
Agent LighthouseAgent Lighthouse

    Searches the text of every published page. The evidence sources themselves are not in this index — search all of them on the trusted sources page.

    GitHub ↗
    Browse checks and page contents
    operability-safety/native-control-substitution

    Native Control Substitution Index

    What it checks

    Finds choice, date and file controls built as custom widgets instead of the native HTML elements. A native element is <select> or an <input> of type date, month, week, time, datetime-local, file, color or range.

    A custom widget is counted in three cases:

    • an element with role="combobox", "listbox" or "menu" that is not a <select> or <input>;
    • a div, span, button or a whose class reads as a picker (select, dropdown, picker, calendar, datepicker, chooser, combobox), with a hidden or readonly input in the same region holding its value;
    • a drop zone with no <input type="file"> inside it or beside it.

    The region is the enclosing <form>, or the parent element when there is none. A native control in the region means the widget decorates a real element, so it is not counted.

    Each custom choice widget is then checked for the ARIA combobox contract: a widget role, aria-expanded, an aria-controls that resolves to a popup role holding options, and an aria-activedescendant that resolves when present.

    The result reports a weighted index, not an action count. A substitution counts 2 when the page URL or form action reads as checkout, cart, signup, register, book, order or search, and 1 elsewhere.

    • No choice, date or file control at all is not applicable.
    • Only native controls passes.
    • A custom widget with a complete contract warns. It works, but costs more steps than the native element.
    • A custom widget with a broken or missing contract, or a drop zone with no file input, fails.

    Why it matters

    Falsifiable claim: native <select>, <input type="date">, and <input type="file"> are single-call primitives in every mainstream agent toolkit (selectOption, fill, setInputFiles) and are keyboard-operable, so they succeed in one action with no actionability risk. A custom equivalent requires five steps: open the control, wait for the popup, scroll the option list into view, locate the option, then click. Each step is independently subject to Playwright’s visible, stable and receives-events gates. Anthropic documents dropdowns specifically as ‘tricky for Claude to manipulate using mouse movements’. Test: instrument the same form with native vs custom controls and count tool calls and retries to reach an identical value.

    Evidence

    • Playwright — locator.selectOption() and locator.setInputFiles() — Microsoft (vendor-doc, verified 2026-10-17)
    • selectOption “Selects option or options in <select>”, and “If the target element is not a <select> element, this method throws an error.” setInputFiles “expects Locator to point to an input element.” The one-call primitives exist only for the native elements.
    • microsoft/playwright-mcp README — Microsoft (vendor-doc, verified 2026-10-17)
    • The agent-facing tools mirror those primitives. browser_select_option will “Select an option in a dropdown” by snapshot ref, and browser_file_upload will “Upload one or multiple files”. A custom widget has to be driven with clicks instead.
    • Computer use tool — Anthropic (vendor-doc, verified 2026-10-17)
    • “Some UI elements (such as dropdowns and scrollbars) might be tricky for Claude to manipulate using mouse movements. If you experience this, try prompting the model to use keyboard shortcuts.”
    • Playwright: Auto-waiting / Actionability checks — Microsoft (vendor-doc, URL verified 2026-08-20)
    • Each click on a custom widget passes the visible, stable and receives-events checks. Opening a popup, scrolling it and clicking an option is several such actions where the native element needs one.
    • WebSuite: Systematically Evaluating Why Web Agents Fail — arXiv (study, URL verified 2026-10-17)
    • Counter-evidence. In WebSuite’s per-interaction table a custom dropdown menu succeeded 100% for both agents tested, and a native select 100% for one and 0% for the other, over 8 trials each. The study does not show custom widgets failing more often than native ones. The grade rests on the documented tool behaviour above, not on this study.

    How it scores

    Tier per evidence policy: scored — grade A meets the A/B bar required for scored audits.

    Grade: A — the consumer behaviour is first-party documented. Playwright documents that its one-call primitives work only on the native elements and throw on anything else. Playwright MCP exposes those primitives to agents as tools. Anthropic documents dropdowns as hard for Claude to operate with the mouse.

    Example finding

    A checkout ships a styled country picker: <div class="dropdown" tabindex="0"> plus a virtualised <ul> that only renders 20 of 195 countries at a time, and a hidden input carrying the value. Playwright’s selectOption is unusable; the agent opens the list, sees 20 entries, does not find ‘Netherlands’, and has no scroll target inside the popup — the same ‘difficulty locating correct scrollable areas’ failure WebVoyager names as a driver of navigation-stuck.

    Sources

    Browser view

    Playwright’s selectOption states: “If the target element is not a <select> element, this method throws an error” (verified 2026-10-20). Playwright MCP exposes it as browser_select_option, which will “Select an option in a dropdown” (verified 2026-10-20). A custom widget has to be driven click by click instead. A supplied browser snapshot is the rendered DOM those tools read, so the browser view runs this audit on it.

    The browser view runs on each complete, unredacted, non-loading capture that carries readable text. It reads the parsed capture DOM only. The finding is informative with weight 0. It does not prove HTTP delivery, computed appearance, a complete accessibility tree, live form state, or action success. A truncated, redacted or still-loading capture records missing evidence. Existing implementation limits still apply.

    The review appears in Browser-rendered snapshot assessment. The eligibility record lives in packages/core/src/snapshot-eligibility.ts. The crawler grade, tier and weight stay unchanged.