[select][combobox] Ignore hidden-input changes while readonly or disabled#4810
[select][combobox] Ignore hidden-input changes while readonly or disabled#4810lunaxislu wants to merge 3 commits into
Conversation
commit: |
Bundle size
PerformanceTotal duration: 1,100.96 ms -226.53 ms(-17.1%) | Renders: 50 (+0) | Paint: 1,669.77 ms -337.90 ms(-16.8%)
8 tests within noise — details Check out the code infra dashboard for more information about this PR. |
✅ Deploy Preview for base-ui ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
Code Review (GPT-5.5)Request changes 🔴 because the same readOnly hidden-input autofill path still exists in NumberField, and the new regression coverage can be much smaller. 1. Bugs / Issues1. 🔴 NumberField still accepts hidden-input autofill while readOnly (blocking)The PR fixes Select and AriaCombobox, but NumberField has the same supported hidden-input autofill path and still only guards
onChange(event) {
// Workaround for https://github.com/facebook/react/issues/9023
if (event.nativeEvent.defaultPrevented) {
return;
}
// Handle browser autofill.
const nextValue = event.currentTarget.valueAsNumber;
const parsedValue = Number.isNaN(nextValue) ? null : nextValue;
setDirty(parsedValue !== validityData.initialValue);
setValue(parsedValue, details);
}This leaves the same class of bug open in another public component that already has a hidden-input browser autofill test. Fix: Apply the same locked-state guard to 2. 🟡 The locked-state regression tests can be table-driven (non-blocking)The new tests repeat the same matrix several times:
it('ignores hidden-input autofill when readOnly', async () => { ... });
it('ignores hidden-input autofill when disabled', async () => { ... });
it('ignores hidden-input autofill when readOnly outside Field', async () => { ... });
it('ignores hidden-input autofill when disabled outside Field', async () => { ... });Recommendation: Extract small render/assert helpers per component and drive the lock state with 2. Simplification OpportunitiesThe production change is already close to minimal for Select and AriaCombobox. If NumberField is included too, a tiny shared predicate may be worth it, for example “ignore this hidden input change when the native event was already prevented or the root is locked, and prevent the Field validation handler when possible.” I would only add that helper if it removes duplication across Select, AriaCombobox, and NumberField; otherwise the source-level inline guard is fine. |
Fixes #4809.
Follow-up to #4806.
SelectRootandAriaComboboxuse the same hidden-input autofill pattern thatOTPFieldRootused before #4806, but their hidden-inputonChangehandlersstill only guard
defaultPrevented, notdisabled || readOnly.This PR applies the same locked-state guard to those remaining handlers.
AriaComboboxis the shared root used by:Combobox.Root(selectionMode='single' | 'multiple')Autocomplete.Root(selectionMode='none')What changed
SelectRoot.tsx: hidden-inputonChangeguard now matches OTP'sAriaCombobox.tsx: same one-line guard updateSelectCombobox(selectionMode='single')Autocomplete(selectionMode='none')Each regression test fires
changeon the hidden input and verifies that no public state change happens whilereadOnlyordisabled.No public API change.