Skip to content

docs(a11y): a11y migration docs for button#6177

Merged
nikkimk merged 8 commits intomainfrom
nikkimk/button-migration
Apr 23, 2026
Merged

docs(a11y): a11y migration docs for button#6177
nikkimk merged 8 commits intomainfrom
nikkimk/button-migration

Conversation

@nikkimk
Copy link
Copy Markdown
Contributor

@nikkimk nikkimk commented Apr 14, 2026

Description

In spectrum-web-components/CONTRIBUTOR-DOCS/03_project-planning/03_components/button/accessibility-migration-analysis.md:

  • Documented recommendations for ARIA roles, states, and properties for the 2nd-gen tabs
  • Shadow DOM and cross-root ARIA considerations documented, including any limitations or required workarounds (e.g., ElementInternals, cross-root ARIA delegation)
  • Accessibility tree expectations documented, including expected node roles, names, states, and hierarchy
  • Keyboard interaction model fully specified, covering focus management, key bindings, roving tabindex or active-descendant patterns, and focus trapping where applicable
  • Testing requirements defined, including unit tests, integration tests, and manual screen reader testing matrix (JAWS, NVDA, VoiceOver)
  • Known 1st-gen accessibility issues cataloged with disposition (fix in 2nd-gen, defer, or won't fix) and linked to any open GitHub issues or bugs
  • Applicable WAI-ARIA design pattern identified with relevant ARIA roles documented
  • 1st-gen component analysis completed, covering current ARIA implementation, keyboard handling, existing test coverage, and known issues with dispositions

Motivation and context

The ticket requests accessibility recommendations for tabs as part of its migration from 1st-gen to 2nd-gen. The recommendations should produce a comprehensive set of accessibility requirements that the engineering team will use as the specification for the 2nd-gen implementation.

The 2nd-gen migration is an opportunity to address known accessibility gaps, align with the latest WAI-ARIA Authoring Practices, and ensure the component meets WCAG 2.2 AA compliance.

Related issue(s)

  • fixes SWC-1874

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

Review the Button accessibility migration analysis

  • ARIA roles, states, and properties covered
  • Shadow DOM and cross-root ARIA considerations covered
  • Accessibility tree documented
  • Keyboard interaction fully specified
  • Testing requirements defined
  • Known 1st-gen issues cataloged with dispositions

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 14, 2026

⚠️ No Changeset found

Latest commit: 8d4c658

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@nikkimk nikkimk self-assigned this Apr 14, 2026
@nikkimk nikkimk marked this pull request as ready for review April 14, 2026 22:02
@nikkimk nikkimk requested a review from a team as a code owner April 14, 2026 22:02
@nikkimk nikkimk requested a review from 5t3ph April 14, 2026 22:02
Copy link
Copy Markdown
Contributor

@5t3ph 5t3ph left a comment

Choose a reason for hiding this comment

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

Overall, excellent as usual!

Please review in tandem to the a11y callouts in my PR, which I have updated slightly based on your document here.


## Overview

This doc describes how **`swc-button`** and a dedicated **`swc-link-button`** (or equivalent) should behave for **accessibility** in 2nd-gen, targeting **WCAG 2.2 Level AA**. It separates **actions** (`<button>` semantics) from **navigation** (`<a href>` semantics), avoids the 1st-gen **proxy-click** pattern on a synthetic link, and aligns **pending / loading** treatment with Spectrum loading guidance ([Figma — Loading animation discovery](https://www.figma.com/design/42VzvpW262EAUbYsadO4e8/Loading-animation-discovery)) and internal **general / accessibility guidance** for loading indicators (delay before show, determinate vs indeterminate, placement, status announcements, and motion).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are we ready to make a call to only use the class-based, semantic <a>, or are you still proposing creating swc-link-button?

It feels a little bit like this doc is emphasizing that distinction more than we need to since link semantics are already deprecated as of S1, so in reading this, it is a little hard to distinguish the purely button recommendations. Could we instead simply note that the decision to deprecate link semantics is firm?

We should continue to have documentation in Storybook to inform consumers that the button is not capable/suited to being a link, but as far as migrating the component, I think the intertwined concerns make it a bit difficult to understand this plan is for swc-button only.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Are we ready to make a call to only use the class-based, semantic , or are you still proposing creating swc-link-button?

Let's table the swc-link-button. I removed it and all references to it from the scope of this doc. If we need it later, we can always make an epic and a doc for it.


**`swc-button`** and **`swc-link-button`** hosts should **not** expose **`role="button"`** / **`role="link"`** while the real control is **`aria-hidden`** or unfocusable—1st-gen hid the anchor and set **`role="link"`** on the host, which breaks native link behavior; avoid the same for **`<button>`**.

### Form-associated buttons (`submit` / `reset`)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we defer handling these button types for the button migration MVP to avoid bringing over the current S1 stop-gap proxy behavior?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes. I updated this doc accordingly.


**Pending state**

- Tree shows **button** or **link** still (unless replaced by different control); pending is **visual** + **name** / **live region**, not a nested **progressbar** masquerading as the control.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should pending use aria-disabled="true" while still remaining focusable? That was some of the guidance from SWC-459 and also matches React's behavior

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes.

| **`aria-disabled` on `<button>`** | Only when intentionally using **disabled semantics** that still allow **focus** (rare); prefer native **`disabled`** when the control should not be in tab order. Document differences in Storybook. |
| **Links and “disabled”** | Do **not** document **`aria-disabled`** on links as “disabled link”—**links are not semantically disabled**. Use a **button**, remove **`href`**, or change copy. |
| **Pending / loading (visual)** | Use an **animated progress icon** (e.g. looping SVG) **without** **`role="progressbar"`** on that graphic unless it truly represents **measurable** progress. **Do not** embed **`swc-progress-circle`** for button pending—that component is for **progressbar** semantics ([progress circle a11y doc](../progress-circle/accessibility-migration-analysis.md)). |
| **Pending / loading (name)** | Keep the control **named**: update **visible** label (“Saving…”), **`aria-label`**, or **`aria-labelledby`** so the **accessible name** reflects **in-progress** when helpful. Prefer **specific** strings (“Uploading document…”) over generic “Loading” when context allows (per loading a11y guidance). |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should aria-labelledby be removed from this guidance due to cross-root issues?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes. It should be removed now.


**`swc-button`**

- Role: **button**; name from subtree, **`aria-label`**, or **`aria-labelledby`**.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Remove aria-labelledby here too?

- [ ] **No proxy** `anchorElement.click()` from a **custom element** that is not the focused **link**; **hosts** do **not** use **`role="button"`** / **`role="link"`**; **focus** targets **native** `<button>` / `<a>` (delegation).
- [ ] **Link** docs state **no semantic disabled**; patterns for “unavailable navigation” documented without **`aria-disabled`** on `<a>`.
- [ ] **Pending** uses **animated icon**, not **`swc-progress-circle`**; announcements follow **polite** / **status** guidance; **no assertive** live region for default loading.
- [ ] **Initiating button** guidance: pending UX does **not** rely on **`aria-disabled="true"`** on the trigger if that would **block** understanding of in-flight work (align with design guidance).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looking at the design guidance, I think there's a typo and this should be in reference to not using disabled as you have noted as well for "Initiating control during load"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed.

@caseyisonit caseyisonit added Status:Ready for review PR ready for review or re-review. 2nd gen These issues or PRs map to our 2nd generation work to modernizing infrastructure. High priority PR review PR is a high priority and should be reviewed ASAP labels Apr 20, 2026
@nikkimk nikkimk requested a review from 5t3ph April 20, 2026 19:34
…web-components into nikkimk/button-migration
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 20, 2026

📚 Branch Preview Links

🔍 First Generation 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-6177

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
Copy Markdown
Contributor

@5t3ph 5t3ph left a comment

Choose a reason for hiding this comment

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

LGTM! I'll work on updating the migration plan 👍

@nikkimk nikkimk requested a review from cdransf April 22, 2026 21:01
Copy link
Copy Markdown
Member

@cdransf cdransf left a comment

Choose a reason for hiding this comment

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

A few comments and notes, but looks great! ✨


---

## 1st-gen implementation notes (avoid in 2nd-gen)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should this be a subsection inside of recommendations? ✨

## Related rules and skills

- **contributor-doc-update.md** — when to run `update-nav.js` after heading or structure changes.
- **contributor-doc-update.mdc** — when to run `update-nav.js` after heading or structure changes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
- **contributor-doc-update.mdc** — when to run `update-nav.js` after heading or structure changes.
- **contributor-doc-update.md** — when to run `update-nav.js` after heading or structure changes.

- **contributor-doc-update.mdc** — when to run `update-nav.js` after heading or structure changes.
- **component-migration-analysis** skill — for `rendering-and-styling-migration-analysis.md`, not this file.
- **stories-documentation.md** / **stories-format.md** — Storybook docs, separate from this contributor planning doc.
- **stories-documentation.mdc** / **stories-format.mdc** — Storybook docs, separate from this contributor planning doc.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
- **stories-documentation.mdc** / **stories-format.mdc** — Storybook docs, separate from this contributor planning doc.
- **stories-documentation.md** / **stories-format.mdc** — Storybook docs, separate from this contributor planning doc.

Comment on lines +128 to +129
- **Never** recommend **`aria-live="assertive"`** for loading or routine progress.
- Treat **`aria-live="polite"`** as **rare**: polite regions still **queue** speech, and **several** components or regions updating together becomes **noisy** (bursts, backlog). Prefer **native role semantics** (e.g. **`progressbar`**) and **one** primary message for related loaders when possible.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we can remove these since we have comparable recommendations under Live regions and announcements. ✨


- Verify behavior and ARIA in **2nd-gen source** before stating what the component exposes — do not document ARIA the code does not set
- Ask clarifying questions for uncertain mappings instead of guessing
- When the doc covers **progress**, **loading**, **busy**, or **spinner** UX, align guidance with Adobe’s Figma file **Loading animation discovery** ([Loading animation discovery](https://www.figma.com/design/42VzvpW262EAUbYsadO4e8/Loading-animation-discovery)); if you cite or rely on it in the doc body, **also** list that link under **`## References`**
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The Figma docs'll be behind SSO, so we may want to move this guidance into the related ticket (I'm not sure how we'd best surface them to the assigned dev or distill it down for the agent?). ✨

@nikkimk nikkimk enabled auto-merge (squash) April 23, 2026 13:41
@nikkimk nikkimk added Status:Ready for re-review PR has had its feedback addressed and is once again ready for review. and removed Status:Ready for re-review PR has had its feedback addressed and is once again ready for review. labels Apr 23, 2026
@nikkimk nikkimk merged commit 608aa71 into main Apr 23, 2026
30 of 32 checks passed
@nikkimk nikkimk deleted the nikkimk/button-migration branch April 23, 2026 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2nd gen These issues or PRs map to our 2nd generation work to modernizing infrastructure. High priority PR review PR is a high priority and should be reviewed ASAP Status:Ready for review PR ready for review or re-review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants