Skip to content

Conversation

caseyisonit
Copy link
Contributor

@caseyisonit caseyisonit commented Sep 15, 2025

Description

This PR fixes aria-label handling issues in button components and improves accessibility for pending state controllers. The changes ensure that aria-labels are properly managed and preserved across component state changes, providing better screen reader support.

Key Changes:

Button Component (@spectrum-web-components/button):

  • Fixed timing of aria-label updates to occur after slot content changes are processed, preventing race conditions
  • Added label property support for programmatic aria-label control in Storybook
  • Added comprehensive tests for aria-label behavior during content changes
  • Moved aria-label management logic to execute after slot content processing

PendingState Controller (@spectrum-web-components/reactive-controllers):

  • Improved aria-label caching logic to better handle dynamic label changes
  • Changed progress circle from aria-valuetext to aria-label for better accessibility compliance
  • Enhanced caching mechanism to preserve user-set aria-labels during pending states
  • Added more robust logic for determining when to cache aria-labels

Motivation and context

The previous implementation had timing issues, allowing aria-label updates to occur before slot content changes were fully processed, leading to inconsistent accessibility behavior. Additionally, the pending state controller was using aria-valuetext instead of aria-label for progress indicators, which is not the recommended approach for accessibility.

These changes ensure that:

  • Screen readers receive consistent and accurate aria-label information
  • User-set aria-labels are properly preserved during component state changes
  • Progress indicators follow accessibility best practices
  • Dynamic content changes don't interfere with aria-label management

Related issue(s)

  • fixes [5620]
  • resolves SWC-1039

Screenshots (if appropriate)


Author's checklist

  • I have read the CONTRIBUTING and PULL_REQUESTS documents.
  • I have reviewed at the Accessibility Practices for this feature, see: Aria Practices
  • I have added automated tests to cover my changes.
  • I have included a well-written changeset if my change needs to be published.
  • I have included updated documentation if my change required it.

Reviewer's checklist

  • Includes a Github Issue with appropriate flag or Jira ticket number without a link
  • Includes thoughtfully written changeset if changes suggested include patch, minor, or major features
  • Automated tests cover all use cases and follow best practices for writing
  • Validated on all supported browsers
  • All VRTs are approved before the author can update Golden Hash

Manual review test cases

  • Button aria-label timing test
  1. Go to the button Storybook stories
  2. Set a label property on a button with slot content
  3. Change the slot content dynamically
  4. Verify that the aria-label remains consistent and doesn't get overridden
  • Pending state aria-label preservation test
  1. Go to any component that uses the PendingState controller (like buttons with pending states)
  2. Set a custom aria-label on the component
  3. Trigger the pending state
  4. Verify that the custom aria-label is cached and restored when pending state ends
  • Progress circle accessibility test
  1. Go to components with pending states
  2. Use a screen reader to navigate to the progress indicator
  3. Verify that the progress circle announces properly with aria-label instead of aria-valuetext
  • Dynamic content changes test
  1. Create a button with both slot content and a label property
  2. Dynamically change the slot content multiple times
  3. Verify that the aria-label from the label property is preserved throughout

Device review

  • Did it pass in Desktop?
  • Did it pass in (emulated) Mobile?
  • Did it pass in (emulated) iPad?

Copy link

changeset-bot bot commented Sep 15, 2025

🦋 Changeset detected

Latest commit: e327b6e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 84 packages
Name Type
@spectrum-web-components/button Patch
@spectrum-web-components/reactive-controllers Patch
@spectrum-web-components/action-bar Patch
@spectrum-web-components/action-button Patch
@spectrum-web-components/alert-banner Patch
@spectrum-web-components/alert-dialog Patch
@spectrum-web-components/button-group Patch
@spectrum-web-components/coachmark Patch
@spectrum-web-components/dialog Patch
@spectrum-web-components/infield-button Patch
@spectrum-web-components/picker-button Patch
@spectrum-web-components/picker Patch
@spectrum-web-components/search Patch
@spectrum-web-components/tags Patch
@spectrum-web-components/toast Patch
example-project-rollup Patch
example-project-webpack Patch
@spectrum-web-components/bundle Patch
@spectrum-web-components/accordion Patch
@spectrum-web-components/action-group Patch
@spectrum-web-components/color-area Patch
@spectrum-web-components/color-slider Patch
@spectrum-web-components/color-wheel Patch
@spectrum-web-components/combobox Patch
@spectrum-web-components/contextual-help Patch
@spectrum-web-components/field-label Patch
@spectrum-web-components/icon Patch
@spectrum-web-components/menu Patch
@spectrum-web-components/meter Patch
@spectrum-web-components/number-field Patch
@spectrum-web-components/overlay Patch
@spectrum-web-components/progress-bar Patch
@spectrum-web-components/radio Patch
@spectrum-web-components/sidenav Patch
@spectrum-web-components/slider Patch
@spectrum-web-components/swatch Patch
@spectrum-web-components/tabs Patch
@spectrum-web-components/tooltip Patch
@spectrum-web-components/tray Patch
@spectrum-web-components/story-decorator Patch
@spectrum-web-components/grid Patch
@spectrum-web-components/vrt-compare Patch
@spectrum-web-components/action-menu Patch
@spectrum-web-components/custom-vars-viewer Patch
documentation Patch
@spectrum-web-components/checkbox Patch
@spectrum-web-components/icons-ui Patch
@spectrum-web-components/icons-workflow Patch
@spectrum-web-components/table Patch
@spectrum-web-components/textfield Patch
@spectrum-web-components/breadcrumbs Patch
@spectrum-web-components/popover Patch
@spectrum-web-components/truncated Patch
@spectrum-web-components/top-nav Patch
@spectrum-web-components/card Patch
@spectrum-web-components/switch Patch
@spectrum-web-components/help-text Patch
@spectrum-web-components/color-field Patch
@spectrum-web-components/field-group Patch
@spectrum-web-components/eslint-plugin Patch
@spectrum-web-components/asset Patch
@spectrum-web-components/avatar Patch
@spectrum-web-components/badge Patch
@spectrum-web-components/clear-button Patch
@spectrum-web-components/close-button Patch
@spectrum-web-components/color-handle Patch
@spectrum-web-components/color-loupe Patch
@spectrum-web-components/divider Patch
@spectrum-web-components/dropzone Patch
@spectrum-web-components/icons Patch
@spectrum-web-components/iconset Patch
@spectrum-web-components/illustrated-message Patch
@spectrum-web-components/link Patch
@spectrum-web-components/modal Patch
@spectrum-web-components/progress-circle Patch
@spectrum-web-components/split-view Patch
@spectrum-web-components/status-light Patch
@spectrum-web-components/thumbnail Patch
@spectrum-web-components/underlay Patch
@spectrum-web-components/base Patch
@spectrum-web-components/opacity-checkerboard Patch
@spectrum-web-components/shared Patch
@spectrum-web-components/styles Patch
@spectrum-web-components/theme Patch

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

Copy link
Contributor

github-actions bot commented Sep 15, 2025

📚 Branch Preview

🔍 Visual Regression Test Results

When 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: pr-5730

If the changes are expected, update the current_golden_images_cache hash in the circleci config to accept the new images. Instructions are included in that file.
If the changes are unexpected, you can investigate the cause of the differences and update the code accordingly.

Copy link
Contributor

Tachometer results

Currently, no packages are changed by this PR...

@caseyisonit caseyisonit marked this pull request as ready for review September 19, 2025 19:46
@caseyisonit caseyisonit requested a review from a team as a code owner September 19, 2025 19:46
Comment on lines +2 to +3
'@spectrum-web-components/button': patch
'@spectrum-web-components/reactive-controllers': patch
Copy link
Contributor

@Rajdeepc Rajdeepc Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Will this be read with our current changelog script? Would you prefer adding separate changeset for each package instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are other changesets with mulitple packages, i dont think it should be an issue

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what Rajdeep means is, even though this works, our change log script does not pick up multiple packages (only the first one).

Copy link
Contributor

@Rajdeepc Rajdeepc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like how this has come together.
One suggestion: Would you like to add a quick screen reader test video to the PR. This would help the original reporter (and future contributors) to verify the behavior.

Copy link
Contributor

@rubencarvalho rubencarvalho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! I left one blocking comment: could we confirm the double label behavior?

cached: string | null,
current: string | null,
pending: string | undefined
): string | boolean | null {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the possible return values accurate? string | boolean | null?

pending: string | undefined
): string | boolean | null {
return (
(!cached && current && current !== pending) ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current && ... treats "" as false. Is an empty string invalid? Or do we need to treat null/undefined differently from an empty string?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If an empty string, maybe we can add a test to cover that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current !== "" && ...

* Renders the pending state UI. The aria-valuetext is needed for Firefox
* @returns A TemplateResult representing the pending state UI.
*
* @TODO: [SWC-1255] This should now be using the progress-circle component. It should be using an animated SVG icon with correct role and aria.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
* @TODO: [SWC-1255] This should now be using the progress-circle component. It should be using an animated SVG icon with correct role and aria.
* @TODO: [SWC-1255] This should not be using the progress-circle component. It should be using an animated SVG icon with correct role and aria.

(also, this todo is very prescriptive of the solution, even though I don't think we have complete clarity on the path forward her)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i can change the language

public cachedAriaLabel: string | null = null;
/**
* Renders the pending state UI.
* Renders the pending state UI. The aria-valuetext is needed for Firefox
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The aria-valuetext is needed for Firefox

I'm curious, why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because firefox reads indeterminate as 50 and value text will override that for screen readers, again this is part of the accessibility issue with using pending-circle

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

role = ""
aria-hidden="true"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants