fix(a11y): announce dynamic status and errors via live regions (A11Y-… - #3005
fix(a11y): announce dynamic status and errors via live regions (A11Y-…#3005sunilsabatp wants to merge 3 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThe PR adds a reusable ChangesAccessibility announcements
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ 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.
Actionable comments posted: 4
🤖 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.
Inline comments:
In `@docs/accessibility/ACCESSIBILITY_FINDINGS.md`:
- Around line 1555-1563: Update the accessibility findings summary to include
A11Y-010 in the completed findings list and change the reported completion count
from 14 to 15, while preserving the existing completed-item formatting.
In `@src/features/common/ContentLoaders/Projects/GlobeLoader.tsx`:
- Around line 13-14: Move the LiveRegion component outside the root motion.div
marked aria-busy="true" in GlobeLoader, or limit aria-busy to only the visual
loader, while preserving the existing loading announcement and globe rendering
behavior.
In `@src/features/common/LiveRegion/index.tsx`:
- Around line 48-49: Update the LiveRegion consumer in UploadWidget so its
live-region nodes remain mounted rather than being remounted via key={status}.
Maintain persistent regions for each politeness level and update their content
as status changes, preserving the documented accessibility contract.
In `@src/features/common/LiveRegion/LiveRegion.module.scss`:
- Line 12: In the visually hidden styling for LiveRegion, replace the deprecated
clip declaration with clip-path using an inset(50%) value, preserving the
existing hidden-element behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 2d2388f1-4fb4-4568-9f32-44531cdcd559
⛔ Files ignored due to path filters (3)
public/static/locales/en/common.jsonis excluded by!**/*.jsonpublic/static/locales/en/donationReceipt.jsonis excluded by!**/*.jsonpublic/static/locales/en/me.jsonis excluded by!**/*.json
📒 Files selected for processing (14)
docs/accessibility/ACCESSIBILITY_FINDINGS.mdsrc/features/common/ContentLoaders/Projects/GlobeLoader.tsxsrc/features/common/Layout/ErrorPopup/index.tsxsrc/features/common/LiveRegion/LiveRegion.module.scsssrc/features/common/LiveRegion/index.tsxsrc/features/common/RedeemCode/RedeemFailed.tsxsrc/features/projectsV2/ProjectList/index.tsxsrc/features/projectsV2/ProjectListControls/ProjectListControlForMobile.tsxsrc/features/projectsV2/ProjectListControls/index.tsxsrc/features/user/BulkCodes/components/UploadWidget.tsxsrc/features/user/BulkCodes/forms/IssueCodesForm.tsxsrc/features/user/CompleteSignup/components/SignupToggles.tsxsrc/features/user/DonationReceipt/microComponents/DonorContactForm.tsxsrc/features/user/PlanetCash/screens/Transactions.tsx
| * Keep the live region mounted and update its content instead of mounting a | ||
| * new one, as this is more reliably announced by assistive technologies. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Keep live-region nodes mounted in consumers.
The documented contract conflicts with src/features/user/BulkCodes/components/UploadWidget.tsx:118-152, which remounts LiveRegion with key={status}. Newly inserted role="status" nodes are not reliably announced across assistive technologies; keep persistent regions per politeness and update their content instead.
🤖 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/features/common/LiveRegion/index.tsx` around lines 48 - 49, Update the
LiveRegion consumer in UploadWidget so its live-region nodes remain mounted
rather than being remounted via key={status}. Maintain persistent regions for
each politeness level and update their content as status changes, preserving the
documented accessibility contract.
| padding: 0; | ||
| margin: -1px; | ||
| overflow: hidden; | ||
| clip: rect(0, 0, 0, 0); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== file =="
if [ -f src/features/common/LiveRegion/LiveRegion.module.scss ]; then
cat -n src/features/common/LiveRegion/LiveRegion.module.scss
else
fd -a 'LiveRegion\.module\.scss' .
fi
echo
echo "== stylelint/package configs =="
for f in .stylelintrc .stylelintrc.json .stylelintrc.js .stylelintrc.cjs package.json; do
if [ -f "$f" ]; then
echo "--- $f ---"
sed -n '1,220p' "$f"
fi
done
echo
echo "== searches for deprecated clip / clip-path / visually hidden =="
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' 'clip\s*:|clip-path|visually hidden|sr-only|sr-only' . | head -200
echo
echo "== browser support markers =="
for f in .browserslistrc brio .browserslist browserlistrc browserlistrc.json; do
if [ -f "$f" ]; then
echo "--- $f ---"
cat "$f"
fi
doneRepository: Plant-for-the-Planet-org/planet-webapp
Length of output: 8253
Replace deprecated clip with clip-path.
clip: rect(...) is legacy CSS; for this visually hidden pattern, use clip-path: inset(50%) so the project stops relying on deprecated CSS when browser support is already modern enough for the rest of the codebase.
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 12-12: Deprecated property "clip" (property-no-deprecated)
(property-no-deprecated)
🤖 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/features/common/LiveRegion/LiveRegion.module.scss` at line 12, In the
visually hidden styling for LiveRegion, replace the deprecated clip declaration
with clip-path using an inset(50%) value, preserving the existing hidden-element
behavior.
Source: Linters/SAST tools
…(A11Y-010) - Render each polite LiveRegion as a persistent, visually hidden region outside the branch it used to live in, and revert the visible message to plain markup. A role="status" region inserted together with its text is often not announced, while a text change inside an already-observed region is - Leave the visible elements conditional. They sit in flex containers with a gap, so always rendering them would add spacing. The hidden region is absolutely positioned and out of flow, so layout is unchanged
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/features/user/BulkCodes/forms/IssueCodesForm.tsx (1)
384-384: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winApply
aria-busyto the container that contains all workflow controls.This
<form>contains only the submit button; inputs, totals, and errors are outside it. Putaria-busy={isProcessing}onStyledFormContainer(or make it the actual form) so the complete issuing workflow is marked busy.🤖 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/features/user/BulkCodes/forms/IssueCodesForm.tsx` at line 384, Move aria-busy={isProcessing} from the form in IssueCodesForm to StyledFormContainer, which contains the inputs, totals, errors, and submit control; alternatively make StyledFormContainer the form while preserving the existing submission behavior.
🤖 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/features/user/BulkCodes/forms/IssueCodesForm.tsx`:
- Line 384: Move aria-busy={isProcessing} from the form in IssueCodesForm to
StyledFormContainer, which contains the inputs, totals, errors, and submit
control; alternatively make StyledFormContainer the form while preserving the
existing submission behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 035f244d-2cf5-4093-8bad-d8fa60955781
📒 Files selected for processing (11)
docs/accessibility/ACCESSIBILITY_FINDINGS.mddocs/accessibility/FOLLOW_UPS.mdsrc/features/common/ContentLoaders/Projects/GlobeLoader.tsxsrc/features/common/LiveRegion/index.tsxsrc/features/projectsV2/ProjectList/index.tsxsrc/features/projectsV2/ProjectListControls/ProjectListControlForMobile.tsxsrc/features/projectsV2/ProjectListControls/index.tsxsrc/features/user/BulkCodes/components/UploadWidget.tsxsrc/features/user/BulkCodes/forms/IssueCodesForm.tsxsrc/features/user/DonationReceipt/microComponents/DonorContactForm.tsxsrc/features/user/PlanetCash/screens/Transactions.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
- src/features/user/PlanetCash/screens/Transactions.tsx
- src/features/projectsV2/ProjectListControls/ProjectListControlForMobile.tsx
- docs/accessibility/ACCESSIBILITY_FINDINGS.md
- src/features/user/DonationReceipt/microComponents/DonorContactForm.tsx
- src/features/common/ContentLoaders/Projects/GlobeLoader.tsx
- src/features/common/LiveRegion/index.tsx
- src/features/user/BulkCodes/components/UploadWidget.tsx
Summary
Addresses A11Y-010: Dynamic status, errors, and results not announced (missing live regions) by introducing a reusable
LiveRegioncomponent and applying it across the application.Previously, dynamic updates such as errors, validation messages, filter result counts, loading states, and success messages were rendered as ordinary content, so screen readers did not announce them automatically.
Changes
LiveRegioncomponent for announcing dynamic content.politeness="assertive"(role="alert") for validation errors, error popups, and failed actions.politeness="polite"(role="status") for filter result counts, empty states, upload progress, success messages, and other non-urgent updates.aria-busyto loading indicators where appropriate.asprop.ACCESSIBILITY_FINDINGS.md.Accessibility Impact
This change addresses:
Screen reader users will now receive announcements for:
without requiring focus to move.
Testing
Manual
Screen Reader
Regression