diff --git a/.changeset/button-aria-label-fix.md b/.changeset/button-aria-label-fix.md new file mode 100644 index 00000000000..ec50c17ac95 --- /dev/null +++ b/.changeset/button-aria-label-fix.md @@ -0,0 +1,12 @@ +--- +'@spectrum-web-components/button': patch +--- + +**Fixed** aria-label handling in `` component. + +- **Fixed**: Moved aria-label updates to occur after slot content changes are processed to prevent timing issues +- **Added**: Enhanced `label` property support for programmatic aria-label control +- **Added**: Comprehensive tests for aria-label behavior during content and pending state changes +- **Fixed**: Removed duplicate aria-label update logic in `update()` method + +These changes ensure that aria-labels are properly managed and preserved across component state changes, improving accessibility for screen reader users. diff --git a/.changeset/combobox-pending-state-fix.md b/.changeset/combobox-pending-state-fix.md new file mode 100644 index 00000000000..f0a9611faee --- /dev/null +++ b/.changeset/combobox-pending-state-fix.md @@ -0,0 +1,12 @@ +--- +'@spectrum-web-components/combobox': patch +--- + +**Fixed** pending state handling and accessibility in `` component. + +- **Changed**: Removed dependency on `PendingStateController` and implemented inline pending state handling +- **Fixed**: Updated aria-labelledby attribute ordering to improve screen reader experience (`label applied-label pending-label`) +- **Fixed**: Updated progress circle implementation to use `role="presentation"` instead of `aria-valuetext` +- **Added**: Direct pending state visual rendering with improved accessibility + +These changes improve accessibility for pending states while reducing unnecessary component dependencies. diff --git a/.changeset/picker-pending-state-fix.md b/.changeset/picker-pending-state-fix.md new file mode 100644 index 00000000000..43b0451472c --- /dev/null +++ b/.changeset/picker-pending-state-fix.md @@ -0,0 +1,12 @@ +--- +'@spectrum-web-components/picker': patch +--- + +**Fixed** pending state handling and accessibility in `` component. + +- **Changed**: Removed dependency on `PendingStateController` and implemented inline pending state handling +- **Fixed**: Updated aria-labelledby attribute ordering to improve screen reader experience (`icon label applied-label pending-label`) +- **Fixed**: Updated progress circle implementation to use `role="presentation"` instead of `aria-valuetext` +- **Added**: Direct pending state visual rendering with improved accessibility + +These changes improve accessibility for pending states while reducing unnecessary component dependencies. diff --git a/.changeset/progress-circle-accessibility-fix.md b/.changeset/progress-circle-accessibility-fix.md new file mode 100644 index 00000000000..f9803eeae21 --- /dev/null +++ b/.changeset/progress-circle-accessibility-fix.md @@ -0,0 +1,10 @@ +--- +'@spectrum-web-components/progress-circle': patch +--- + +**Fixed** accessibility warning logic in `` component. + +- **Fixed**: Updated accessibility warning logic to only apply when `role="progressbar"` is explicitly set +- **Fixed**: Improved label validation for better accessibility compliance + +These changes ensure accessibility warnings are only shown when appropriate and improve overall accessibility compliance. diff --git a/.changeset/reactive-controllers-pending-state-fix.md b/.changeset/reactive-controllers-pending-state-fix.md new file mode 100644 index 00000000000..57e21e5b031 --- /dev/null +++ b/.changeset/reactive-controllers-pending-state-fix.md @@ -0,0 +1,12 @@ +--- +'@spectrum-web-components/reactive-controllers': patch +--- + +**Fixed** accessibility and caching in `PendingStateController`. + +- **Fixed**: Updated progress circle to use `role="presentation"` for better accessibility compliance +- **Fixed**: Improved aria-label caching logic to better handle dynamic label changes +- **Added**: Documentation noting the controller is primarily used by `` component +- **Fixed**: Enhanced caching mechanism to preserve user-set aria-labels during pending states + +These changes improve accessibility compliance and aria-label management for components using the pending state controller. diff --git a/packages/button/src/ButtonBase.ts b/packages/button/src/ButtonBase.ts index 196394b91c6..9fbae9d6a79 100644 --- a/packages/button/src/ButtonBase.ts +++ b/packages/button/src/ButtonBase.ts @@ -225,13 +225,7 @@ export class ButtonBase extends ObserveSlotText(LikeAnchor(Focusable), '', [ if (!this.hasAttribute('tabindex')) { this.setAttribute('tabindex', '0'); } - if (changed.has('label')) { - if (this.label) { - this.setAttribute('aria-label', this.label); - } else { - this.removeAttribute('aria-label'); - } - } + this.manageAnchor(); this.addEventListener('keydown', this.handleKeydown); this.addEventListener('keypress', this.handleKeypress); @@ -243,6 +237,14 @@ export class ButtonBase extends ObserveSlotText(LikeAnchor(Focusable), '', [ this.manageAnchor(); } + if (changed.has('label')) { + if (this.label) { + this.setAttribute('aria-label', this.label); + } else { + this.removeAttribute('aria-label'); + } + } + if (this.anchorElement) { // Ensure the anchor element is not focusable directly via tab this.anchorElement.tabIndex = -1; @@ -256,14 +258,4 @@ export class ButtonBase extends ObserveSlotText(LikeAnchor(Focusable), '', [ this.anchorElement.addEventListener('focus', this.proxyFocus); } } - protected override update(changes: PropertyValues): void { - super.update(changes); - if (changes.has('label')) { - if (this.label) { - this.setAttribute('aria-label', this.label); - } else { - this.removeAttribute('aria-label'); - } - } - } } diff --git a/packages/button/stories/index.ts b/packages/button/stories/index.ts index 5d5a4e8b2cb..86aa382e9c6 100644 --- a/packages/button/stories/index.ts +++ b/packages/button/stories/index.ts @@ -86,6 +86,17 @@ export const argTypes = { type: 'boolean', }, }, + label: { + name: 'label', + type: { name: 'string', required: false }, + description: 'The label to apply to the aria-label of the button.', + table: { + type: { summary: 'string' }, + }, + control: { + type: 'text', + }, + }, }; export const makeOverBackground = @@ -122,6 +133,7 @@ export function renderButton(properties: Properties): TemplateResult { treatment=${ifDefined(properties.treatment)} variant=${ifDefined(properties.variant)} static-color=${ifDefined(properties.staticColor)} + label=${ifDefined(properties.label)} > ${properties.content || 'Click Me'} diff --git a/packages/button/stories/template.ts b/packages/button/stories/template.ts index 0ea6cf6352d..2f2f3f21fea 100644 --- a/packages/button/stories/template.ts +++ b/packages/button/stories/template.ts @@ -9,7 +9,6 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ - import { html, TemplateResult } from '@spectrum-web-components/base'; import { ifDefined } from '@spectrum-web-components/base/src/directives.js'; import { @@ -30,6 +29,7 @@ export interface Properties { target?: '_blank' | '_parent' | '_self' | '_top'; noWrap?: boolean; iconOnly?: boolean; + label?: string; } export const Template = ({ diff --git a/packages/button/test/button.test.ts b/packages/button/test/button.test.ts index 90e253f8636..c923084f622 100644 --- a/packages/button/test/button.test.ts +++ b/packages/button/test/button.test.ts @@ -384,32 +384,62 @@ describe('Button', () => { it('manages aria-label from pending state', async () => { const el = await fixture