fix(a11y): announce loading state in LoadingSpinner for screen readers#506
Conversation
📝 WalkthroughWalkthroughLoadingSpinner component now declares ARIA accessibility attributes (role="status", aria-live="polite", and an i18n-translated aria-label) to properly announce loading state to assistive technologies. Corresponding test updates verify the ARIA properties and localized visible text across locale changes, with a full mock of svelte-i18n. ChangesLoadingSpinner Accessibility
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related issues
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/LoadingSpinner.svelte (1)
2-2:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUse the project i18n wrapper instead of importing
svelte-i18ndirectly.Please import translations from
src/lib/i18n.jsso this component stays on the repo’s centralized i18n initialization/fallback contract.As per coding guidelines, "Use i18n via
src/lib/i18n.jswith English as synchronous fallback and other 24 locales lazy-loaded".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/LoadingSpinner.svelte` at line 2, Replace the direct import of t from 'svelte-i18n' with the project's i18n wrapper by importing t from 'src/lib/i18n.js' so LoadingSpinner.svelte uses the centralized i18n initialization/fallback; update the import statement that currently references "t" to use the wrapper export and ensure the component continues to call t(...) unchanged so English remains the synchronous fallback and other locales stay lazy-loaded per the repo convention.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/components/LoadingSpinner.svelte`:
- Line 2: Replace the direct import of t from 'svelte-i18n' with the project's
i18n wrapper by importing t from 'src/lib/i18n.js' so LoadingSpinner.svelte uses
the centralized i18n initialization/fallback; update the import statement that
currently references "t" to use the wrapper export and ensure the component
continues to call t(...) unchanged so English remains the synchronous fallback
and other locales stay lazy-loaded per the repo convention.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: b28cf681-11c6-48b2-b2f3-e72a3d55a1a3
📒 Files selected for processing (2)
src/components/LoadingSpinner.sveltesrc/components/__tests__/LoadingSpinner.test.js
aaronbrethorst
left a comment
There was a problem hiding this comment.
Nice, focused fix, Tarun. This does exactly what issue #505 asks for and nothing more: the inline LoadingSpinner now carries role="status", aria-live="polite", and a localized aria-label, so screen reader users finally get told something is happening. It mirrors the pattern already established in FullPageLoadingSpinner.svelte to the letter, which is exactly what I want to see — consistency over cleverness.
The test rewrite is the real star here. Swapping in a local svelte-i18n mock that actually flips en→es turns what could have been a tautological "the mock returns the key" check into a genuine reactivity test: it proves both the aria-label and the visible text re-render on a locale change. That's a meaningfully better test than what it replaced.
Critical Issues (0 found)
None.
Important Issues (0 found)
None. Tests pass (npx vitest run — 4/4 green), npm run lint is clean, and the accessible-name assertions hold up under scrutiny: removing the aria-label from the component would actually fail the Spanish test, since aria-label wins over text content for the computed accessible name. The coverage is real, not decorative.
Suggestions (1 found)
- The inner
<svg>is purely decorative but isn't markedaria-hidden="true"[src/components/LoadingSpinner.svelte:12]. In practice the parentrole="status"already owns the accessible name viaaria-label, so the SVG contributes nothing to assistive tech and this is belt-and-suspenders. It also applies equally to the existingFullPageLoadingSpinner.svelte, so it's not a regression you introduced. Out of scope for this PR — tracked separately (see below) rather than gating the merge.
A note on the CodeRabbit comment
The automated suggestion to import t from a src/lib/i18n.js wrapper is a false alarm — i18n.js exports languages, getInitialLocale, and isRTL, but not t. Importing t directly from svelte-i18n is the established convention across the codebase (ArrivalDeparture, AlertsModal, SearchPane, and ~15 others). Your import is correct; no change needed.
Strengths
- Implementation is minimal and matches the sibling component exactly.
- Satisfies every acceptance-criteria checkbox in issue #505.
- Test mock is a legitimate, reusable fixture that makes locale reactivity genuinely testable.
beforeEach(() => locale.set('en'))properly isolates the mutable mock state between tests.waitForcorrectly handles the async reactivity flush afterlocale.set('es').
Recommended Action
Merge as-is. The single suggestion above is fit-and-finish and belongs in a follow-up, not this PR.
Fixes #505 #405
Summary by CodeRabbit
Accessibility
Tests