Various components: Let UserAttributes override generated ARIA attributes - #13642
Merged
danielchalmers merged 1 commit intoAug 18, 2026
Conversation
…tes override generated ARIA attributes Follows PR MudBlazor#13613, which moved `aria-describedby`, `aria-invalid` and `aria-required` above the `@attributes="UserAttributes"` splat on MudInput so a caller can override them. Blazor resolves duplicate attributes last-write-wins, so a literal after the splat silently discards the caller's value and one before it acts as a fallback. The same four components still write these annotations after their splat. MudMask is the reason this matters most. MudTextField renders a MudMask instead of a MudInput whenever `Mask` is set, and splats the same UserAttributes down, so after MudBlazor#13613: <MudTextField aria-required="true" /> honours the caller <MudTextField Mask="@Mask" aria-required="true" /> silently discards it One public component, two answers, keyed on an unrelated parameter. MudRadioGroup has the strongest standalone case: a `<div role="radiogroup">` cannot carry the native `required` attribute, and the child radios do not emit it either, so `aria-required` is the widget's only required-ness signal. An app that validates server-side currently has no way to state it. Both MudRangeInput inputs move together. They share one UserAttributes dictionary, so moving only one would leave the two halves of a single field announcing different required-ness — worse than the current uniform discard. Deliberately unchanged: - `required` stays below the splat everywhere. It is native browser behaviour rather than an annotation, and it drives validation, not just the DOM. - MudRangeInput's `aria-label` and `id` stay below. Their values differ per input ("Start"/"End", `-start`/`-end`), and one dictionary cannot express two values for one key. `StartInputAriaLabel`/`EndInputAriaLabel` remain the supported override path. - MudFileUpload's `id` stays below. The splat sits inside a `@for`, so a single caller id would land on every active input and break the file-picker interop. This is an ordering change only. No new code, nothing allocated per render, and default rendering is byte-identical.
20 tasks
This was referenced Aug 24, 2026
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.
Follows #13613, which moved
aria-describedby,aria-invalidandaria-requiredabove the@attributes="UserAttributes"splat onMudInputso a caller can override them. Blazor resolves duplicate attributes last-write-wins, so a literal written after the splat silently discards the caller's value, and one written before it acts as a fallback.Deliberately unchanged
requiredstays below the splat everywhere. It is native browser behaviour rather than an ARIA annotation, and it drivesMudFormComponentvalidation and the label asterisk, not just the DOM. Keeping the pair separable is the point of the original change.MudRangeInput'saria-labelandidstay below. Their values differ per input ("Start"/"End",-start/-end), and one dictionary cannot express two values for one key — a caller value would be duplicated onto both halves, breaking the distinct accessible names and producing a duplicate DOM id.StartInputAriaLabel/EndInputAriaLabelremain the supported override path.MudFileUpload'sidstays below. The splat sits inside a@for, so a single caller id would land on every active input and breakmudFileUpload.openFilePicker, which resolves bygetElementByIdand no-ops silently on a miss.Behaviour
aria-required/aria-invalid/aria-describedbyrequiredattributeRequiredChecklist: