Mark inputs with a required() validator as aria-required - #11336
Open
ousamabenyounes wants to merge 1 commit into
Open
Mark inputs with a required() validator as aria-required#11336ousamabenyounes wants to merge 1 commit into
ousamabenyounes wants to merge 1 commit into
Conversation
TextInput only displayed the "*" in its label but left the underlying input without any required semantics, so assistive technologies (and tests using toBeRequired()) did not see it as required. Add aria-required via the shared ResettableTextField renderer, deliberately using aria-required rather than the native required attribute so react-admin's JS validation is preserved and no native browser validation is triggered. Closes marmelab#9585
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When an input uses a
required()validator (e.g.<TextInput source="id" validate={required()} />), react-admin adds the*to the label but leaves the underlying<input>without any required semantics. As a result:expect(within(edit).getByLabelText('Id *')).toBeRequired()fails.This was reported in #9585. As discussed there, the fix should use
aria-required="true"rather than the nativerequiredattribute: react-admin relies on JS validation, and forms render withnoValidate=falseby default, so a nativerequiredattribute would trigger native browser validation. Addingaria-requiredwas the explicit direction given by the maintainer on the issue.Solution
Route an
aria-requiredflag through the sharedResettableTextFieldrenderer onto the native<input>element, and haveTextInputpassaria-required={isRequired || undefined}(whereisRequiredalready reflects the presence of arequired()validator or theisRequiredprop).inputProps) and MUI v6+ (slotProps.htmlInput, including the callback form).inputProps/slotProps.htmlInputare preserved (non-lossy merge).requiredattribute is intentionally not set, so JS validation and label behavior are unchanged.Scope: this PR fixes the reported
TextInputcase via the sharedResettableTextField. The same one-linearia-required={isRequired || undefined}wiring can be extended to the other inputs that exposeisRequired(SelectInput, NumberInput, DateInput, …) — happy to widen this PR or open a follow-up, whichever the maintainers prefer.How To Test
<TextInput source="id" validate={required()} />now renders<input ... aria-required="true">(and still no nativerequired). A non-required input is unchanged.Unit test added in
TextInput.spec.tsx:Test verification (RED → GREEN)
RED — on the unmodified
nextbranch (test kept, production change reverted):GREEN — with the fix:
No regression across the shared renderer's consumers (
TextInput,SelectInput,NumberInputsuites all green); ESLint, Prettier, and thera-core→ra-ui-materialuibuild all pass.Additional Checks
masterfor a bugfix or a documentation fix, ornextfor a feature — targetsnextas requested on the issue.aria-requiredis a non-visual accessibility attribute and existingrequiredstories (TextInput.stories.tsx,useInput.stories.tsx) already cover the required rendering. Happy to add one if preferred.aria-required={isRequired}pattern (docs_headless/.../Inputs.md,useInput.md); this makes the built-inTextInputconform, so no doc file drifts.