-
Notifications
You must be signed in to change notification settings - Fork 232
fix(button): update aria-label when label changes #5691
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: 7ff7359 The changes in this PR will be included in the next version bump. This PR includes changesets to release 84 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📚 Branch Preview🔍 Visual Regression Test ResultsWhen a visual regression test fails (or has previously failed while working on this branch), its results can be found in the following URLs:
Deployed to Azure Blob Storage: If the changes are expected, update the |
Tachometer resultsChromebutton permalinktest-basic
Firefoxbutton permalinktest-basic
|
|
|
||
| private updateAriaLabel(): void { | ||
| if (this.label) { | ||
| this.setAttribute('aria-label', this.label); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a user sets aria-label directly after the component has set it via the label property, the component might override the user's intent here. I would be checking if aria-label is set by the user or not before we trigger component logic.
private _userSetAriaLabel = false;
connectedCallback() {
super.connectedCallback();
// Detect if aria-label was set by the user before component logic runs
this._userSetAriaLabel = this.hasAttribute('aria-label');
}
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {
if (name === 'aria-label' && oldValue !== newValue) {
this._userSetAriaLabel = true;
}
super.attributeChangedCallback(name, oldValue, newValue);
}
private updateAriaLabel(): void {
if (this._userSetAriaLabel) return; // Don't override user intent
if (this.label) {
this.setAttribute('aria-label', this.label);
} else {
this.removeAttribute('aria-label');
}
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we want to allow both label and aria-label on the component at the same time? Isn't label used just for aria-label purposes, as per docs and code?
If the consumer doesn't set a label but sets an aria-label, the component will have the desired aria-label.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Theoretically we generally don’t want both to apply at the same time. The implementation should respect a consumer’s explicit aria-label and only use label as a fallback for accessibility. This will avoid race conditions and user confusion.
I think we should document that aria-label always takes priority over label.
- If both are set, use
aria-label. - If only label is set, set
aria-labelto label. - If neither is set, no
aria-labelis present.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that this might be a good improvement, even though there is no need for a consumer to provide both label and aria-label. Currently, on main, if label and aria-label are set, the label will override the aria-label. That being said, I feel like adding more is out of scope and we're looking forward to see this fix merged. Can we keep this in mind and act on it in another PR if it truly is something we want?
| @@ -243,6 +251,11 @@ export class ButtonBase extends ObserveSlotText(LikeAnchor(Focusable), '', [ | |||
| this.manageAnchor(); | |||
| } | |||
|
|
|||
| // Don't override PendingStateController's aria-label changes | |||
| if (changed.has('label') && !this.isPendingState()) { | |||
| this.updateAriaLabel(); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both update and updated might call updateAriaLabel for the same change. Can you call updateAriaLabel in only one lifecycle or just make sure it runs once per change.
Do you have any specific reason to call this in update method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This surfaces multiple conflicts since the Button component has label and the PendingStateController that modify the aria-label. Maybe a long term major change would be to get rid of the label prop altogether 🤔 or if we keep it we need a library level way to determine if it's only for aria-label purposes or not, in order to update the PendingStateController accordingly.
For now I gated the updates according to the pending state to happen either in update or updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool thats something we would like to do in future. Do you mind validating this in screen readers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I added a screen recording, validating the manual test cases with a screen reader. Let me know if I should add anything else.
Description
This PR modifies the aria-label update logic of the
ButtonBasein order to correctly update when thelabelproperty changes during its lifetime, gating the buttons that use thePendingStateControllerto not override their aria-label manipulation.Unit tests were added to validate these usecases in the future. All existing tests pass.
Implementation based on #5674
Motivation and context
Currently when the
labelproperty changes, thearia-labelof the button components do not reflect this change.Related issue(s)
Screenshots (if appropriate)
labelSWCdemo.mp4
Author's checklist
Reviewer's checklist
patch,minor, ormajorfeaturesManual review test cases
Validate
aria-labelupdates whenlabelupdatesValidate
aria-labelvalues when element's content changesDevice review