Make server-rendered Pajamas::ButtonComponent accessible when disabled
What does this MR do and why?
Adds an accessible_disabled option to Pajamas::ButtonComponent, defaulting to false. Set it to true and the button renders aria-disabled="true" without the native disabled attribute, so it stays focusable and gets announced by assistive technology. Every existing call site is unaffected.
This replaces the earlier approach in this MR, which dropped native disabled from all server-rendered buttons and added a document-level click guard to no-op the resulting clicks. Review surfaced the problem with that: server-rendered markup and behaviour aren't coupled. Rapid Diffs renders a disabled button that JS re-enables at runtime, with clicks routed through a <diff-file> web component, so the markup alone doesn't tell you what activating the button will do. Making the accessible variant opt-in puts that judgment at the call site, where someone can answer the question.
The click guard is gone.
That means opting in produces a focusable button with nothing stopping it from activating, and the call site owns preventing that. GlButton handles the same problem internally because it owns its own markup, which is exactly the coupling server-rendered buttons don't have.
loading keeps the native attribute regardless of this option, since a transient inert state has no discoverability argument.
No call sites opt in yet. The option is the seam that lets @gitlab/ui flip GlButton's accessibleDisabled default to true without stranding server-rendered buttons on inconsistent behaviour.
References
- #612142
- Proposal: !250688 (merged)#note_3704785153
- Dropping the JS: !250688 (merged)#note_3715147425
@gitlab/uihalf (separate MR): gitlab-org/gitlab-services/design.gitlab.com!5912 (merged)
Screenshots or screen recordings
No visual change. Default rendering is identical to master, and no call site opts in.
How to set up and validate locally
- Render
Pajamas::ButtonComponent.new(disabled: true)and confirm the markup still carries bothdisabledandaria-disabled="true", unchanged from master. - Render
Pajamas::ButtonComponent.new(disabled: true, accessible_disabled: true)and confirm the nativedisabledattribute is absent,aria-disabled="true"is present, and the button takes keyboard focus. - Render
Pajamas::ButtonComponent.new(loading: true, accessible_disabled: true)and confirm the nativedisabledattribute is still present.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.