Skip to content

fix(Switch): persistently mount busy live region and localize loading announcement (#6114) - #6125

Open
Geervan wants to merge 3 commits into
facebook:mainfrom
Geervan:fix/switch-busy-live-region-announcement
Open

fix(Switch): persistently mount busy live region and localize loading announcement (#6114)#6125
Geervan wants to merge 3 commits into
facebook:mainfrom
Geervan:fix/switch-busy-live-region-announcement

Conversation

@Geervan

@Geervan Geervan commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #6114.

Previously, Switch rendered its busy announcement live region dynamically only while isBusy was true ({isBusy && <VisuallyHidden role="status">Loading</VisuallyHidden>}). This caused two defects:

  1. Born with content: The live region was mounted at the same moment its text appeared. Because screen readers observe text mutations within pre-existing live regions rather than newly inserted nodes with existing content, the loading announcement was typically silent.
  2. Hardcoded English: The string "Loading" was hardcoded in English instead of going through the useTranslator i18n system.

This PR aligns Switch with the persistent live-region pattern used by Button:

  • Unconditionally renders <VisuallyHidden role="status" aria-live="polite"> so the container is always mounted.
  • Sets its text to empty string "" when idle and dynamically updates it to t('@astryx.switch.loading') when isBusy is true.
  • Adds the @astryx.switch.loading key to packages/core/locales/en.json.

Changes

  • packages/core/src/Switch/Switch.tsx: Hooked useTranslator and converted the live region to be persistently mounted with dynamic translated text.
  • packages/core/locales/en.json: Added @astryx.switch.loading translation entry.
  • packages/core/src/Switch/Switch.test.tsx: Added regression unit tests for:
    • Empty persistent live region present when idle.
    • Live region updating to "Loading" when isLoading is enabled.
    • Localization of the loading announcement through InternationalizationProvider overrides.
    • Live region announcing "Loading" during async changeAction transitions and clearing on resolution.
  • .changeset/switch-busy-announcement.md: Added changeset entry for patch release.

Verification

  • npx vitest run packages/core/src/Switch/Switch.test.tsx (58/58 passed)
  • node scripts/check-i18n-catalog.mjs (passed with 0 errors)
  • npx vitest run packages/core/src/Button/Button.test.tsx packages/core/src/i18n/useTranslator.test.tsx (52/52 passed)
  • node scripts/check-changesets.mjs (passed)

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Sep 7, 2026
@vercel

vercel Bot commented Sep 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Sep 8, 2026 11:19am UTC

Request Review

@github-actions github-actions Bot added community Authored by a community contributor (not on the eng/design team) needs:code-review High-risk change (new package/component/API) — needs human code review before merge labels Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

PR Analysis Report

📚 Storybook Preview

View Storybook for this PR
GitHub Pages may take up to a minute to hydrate after deploy.

🧪 Sandbox Preview

View Sandbox for this PR
GitHub Pages may take up to a minute to hydrate after deploy.

Modified Components

Switch (@astryxdesign/core) · View in Storybook
Metric Before After Delta
Bundle Size (ESM) N/A N/A N/A
Lines of Code N/A 497 -
Complexity N/A Very High (46) -

Bundle Size Summary

Package Size (ESM) Size (CJS) Gzipped
@astryxdesign/core N/A 4.8KB 1.2KB

Accessibility Audit

Status: No accessibility violations detected.

Visual Regression

Status: No visual change across 2 compared shot(s).


Generated by PR Enrichment workflow | Storybook | Sandbox | View full report

@cixzhang cixzhang left a comment

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.

Thanks for this fix! This is very close. We'll likely want to use the useAnnounce pattern here over visually hidden.

Comment thread packages/core/src/Switch/Switch.tsx Outdated
Comment on lines +620 to +622
<VisuallyHidden role="status" aria-live="polite">
{isBusy ? t('@astryx.switch.loading') : ''}
</VisuallyHidden>

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.

We likely want to be using useAnnounce instead of VisuallyHidden which is the older pattern. The useAnnounce hook will include a stable live region and bypass the issue without introducing a permanent DOM element per switch.

@github-actions
github-actions Bot requested a review from cixzhang September 8, 2026 11:16
@Geervan

Geervan commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Updated to use the useAnnounce hook instead of VisuallyHidden as suggested!

Announcements now route through the shared singleton live region without introducing per-switch DOM nodes, let me know if I still missed any corners

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot. community Authored by a community contributor (not on the eng/design team) needs:code-review High-risk change (new package/component/API) — needs human code review before merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Switch: the busy status is announced in English, if it is announced at all

2 participants