Skip to content

fix(a11y): announce workspace status and progress steps to screen readers#1562

Open
olexii4 wants to merge 2 commits into
mainfrom
CRW-10313
Open

fix(a11y): announce workspace status and progress steps to screen readers#1562
olexii4 wants to merge 2 commits into
mainfrom
CRW-10313

Conversation

@olexii4
Copy link
Copy Markdown
Contributor

@olexii4 olexii4 commented May 12, 2026

What does this PR do?

Fixes WCAG 4.1.3 (Status Messages, Level AA): dynamic status changes in the dashboard are now announced by assistive technologies without requiring the user to move focus.

Two scenarios were failing:

1. Workspaces list — "Start workspace" kebab action

When a user starts a workspace from the kebab menu, the status indicator updates visually from Stopped to Starting, but screen readers remained completely silent. A visually-impaired user had no way to know the workspace was loading unless they guessed and tabbed around to find the indicator.

2. Create Workspace / Starting Workspace progress wizard

When the workspace creation or starting wizard advances from step to step (e.g. "Initializing" → "Starting workspace" → "Waiting for workspace to start"), none of the step transitions were announced. The screen reader only read the initial "Loading" screen.

Changes

WorkspaceStatusIndicator (src/components/Workspace/Status/Indicator/index.tsx)

Adds a visually-hidden <span role="status" aria-atomic="true"> inside the indicator element. Its text content mirrors the status label (e.g. "Workspace status is Starting"). Whenever the workspace status prop changes, the live region text updates and the screen reader announces the change — without the user having to Tab to the element.

ProgressStepTitle (src/components/WorkspaceProgress/StepTitle/index.tsx)

Adds a persistent <span role="status" aria-live="polite" aria-atomic="true"> live region rendered alongside every step title. The region is populated only when the step is active (distance === 0), so the announcement fires exactly once per step transition. The live region text uses a "Step: " prefix (e.g. "Step: Waiting for workspace to start") to keep it distinct from the visible title text and prevent ambiguous matches in DOM queries.

Screenshot/screencast of this PR

Знімок екрана 2026-05-12 о 15 28 29

What issues does this PR fix or reference?

fixes https://redhat.atlassian.net/browse/CRW-10313

Is it tested? How?

  • Existing snapshot tests updated to include the new live region elements (25 snapshots updated).
  • Manually verified with macOS VoiceOver on Chrome (Command + F5) that status changes are announced without user focus movement.

Release Notes

Docs PR

@olexii4 olexii4 requested review from akurinnoy and ibuziuk as code owners May 12, 2026 12:07
@che-bot
Copy link
Copy Markdown
Contributor

che-bot commented May 12, 2026

Click here to review and test in web IDE: Contribute

…ders

WCAG 4.1.3 (Status Messages) requires dynamic status changes to be announced
by assistive technologies without requiring user focus.

WorkspaceStatusIndicator: add a visually-hidden role="status" live region inside
the indicator span. When the workspace status prop changes (e.g. Stopped →
Starting), the live region text updates and screen readers announce the change
without the user having to Tab to the element.

ProgressStepTitle: add a persistent aria-live="polite" live region that is
populated only when a step is active (distance === 0). As each step in the
workspace creation or starting wizard becomes active, its name is announced
automatically. The "Step: " prefix keeps the live region text distinct from
the visible step title, preventing ambiguous DOM query matches.

Also restore aria-label="Restore from backup" on the BackupsView Toolbar
restore button to satisfy the existing accessibility test expectation.

Assisted-by: Claude Sonnet 4.6
Signed-off-by: Oleksii Orel <oorel@redhat.com>
@svor svor requested a review from olkornii May 12, 2026 12:39
@github-actions
Copy link
Copy Markdown

Docker image build succeeded: quay.io/eclipse/che-dashboard:pr-1562 (linux/amd64, linux/arm64)

kubectl patch command
kubectl patch -n eclipse-che "checluster/eclipse-che" --type=json -p="[{"op": "replace", "path": "/spec/components/dashboard/deployment", "value": {containers: [{image: "quay.io/eclipse/che-dashboard:pr-1562", name: che-dashboard}]}}]"

Copy link
Copy Markdown

@olkornii olkornii left a comment

Choose a reason for hiding this comment

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

Works for me with 3.27.1 and quay.io/eclipse/che-dashboard:pr-1562 .

Workspace creation process is fast, so screen reader cannot announce all of the steps. It is the only not a perfect thing I noticed.
@svor @olexii4 what do you think? Not sure we can do something with that. The only idea I have how we can improve it is to force screen reader to announce something like "Workspace created" even if it didnt finish announcing the rest of the steps.

But IMHO it is not necessary as once workspace is created screen reader announces "Workspace empty-blabla is running".

@olexii4
Copy link
Copy Markdown
Contributor Author

olexii4 commented May 12, 2026

Works for me with 3.27.1 and quay.io/eclipse/che-dashboard:pr-1562 .

Workspace creation process is fast, so screen reader cannot announce all of the steps. It is the only not a perfect thing I noticed. @svor @olexii4 what do you think? Not sure we can do something with that. The only idea I have how we can improve it is to force screen reader to announce something like "Workspace created" even if it didnt finish announcing the rest of the steps.

But IMHO it is not necessary as once workspace is created screen reader announces "Workspace empty-blabla is running".

@olkornii Try one of these:

@olexii4 olexii4 requested a review from svor May 12, 2026 14:56
@svor
Copy link
Copy Markdown
Contributor

svor commented May 12, 2026

I’d say that if the Level AA criteria for 2.1 and 2.2 are met, we should be good

@svor
Copy link
Copy Markdown
Contributor

svor commented May 12, 2026

/retest

@olkornii
Copy link
Copy Markdown

olkornii commented May 12, 2026

@olexii4 tried with workspaces u mentioned. Noticed one more thing: "Waiting for workspace to start" is the last announced step. All of sub-steps for this step are not announced. I'll try to figure out if its enough or no.

Copy link
Copy Markdown

@olkornii olkornii left a comment

Choose a reason for hiding this comment

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

@olexii4 seems like all of sub-steps must be announced as well:
The Verdict: If the sub-steps appear visually as progress text on the screen, the screen reader must announce them as well as they change.

@openshift-ci openshift-ci Bot removed the lgtm label May 12, 2026
@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 12, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: olexii4

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@github-actions
Copy link
Copy Markdown

Docker image build succeeded: quay.io/eclipse/che-dashboard:pr-1562 (linux/amd64, linux/arm64)

kubectl patch command
kubectl patch -n eclipse-che "checluster/eclipse-che" --type=json -p="[{"op": "replace", "path": "/spec/components/dashboard/deployment", "value": {containers: [{image: "quay.io/eclipse/che-dashboard:pr-1562", name: che-dashboard}]}}]"

@olexii4
Copy link
Copy Markdown
Contributor Author

olexii4 commented May 13, 2026

@olexii4 seems like all of sub-steps must be announced as well: The Verdict: If the sub-steps appear visually as progress text on the screen, the screen reader must announce them as well as they change.

@olkornii I have fix it:
Знімок екрана 2026-05-13 о 17 03 23

@github-actions
Copy link
Copy Markdown

Docker image build succeeded: quay.io/eclipse/che-dashboard:pr-1562 (linux/amd64, linux/arm64)

kubectl patch command
kubectl patch -n eclipse-che "checluster/eclipse-che" --type=json -p="[{"op": "replace", "path": "/spec/components/dashboard/deployment", "value": {containers: [{image: "quay.io/eclipse/che-dashboard:pr-1562", name: che-dashboard}]}}]"

Follow-up to the workspace status live-region fix. Condition sub-steps
(StorageReady, RoutingReady, DeploymentReady, etc.) were not being announced
because ProgressStepTitle received mixed children [string, ReactElement] and
the previous typeof check only handled plain-string children.

Changes:

ProgressStepTitle:
- Add extractText() helper that recursively extracts plain text from any
  ReactNode (string, array, or React element with nested children).
- Replace typeof children === 'string' check with extractText(children) so
  the live region is populated regardless of whether children are plain strings
  or mixed string + JSX nodes.
- Add optional parentStepName prop. When set, the live-region announcement
  reads "Step: {parentStepName} / {stepText}" so screen readers hear the full
  context for sub-steps (e.g. "Step: Waiting for workspace to start / StorageReady").

StartingStepWorkspaceConditions:
- Pass parentStepName="Waiting for workspace to start" to ProgressStepTitle so
  each condition sub-step is announced with the parent step context.

Assisted-by: Claude Sonnet 4.6
Signed-off-by: Oleksii Orel <oorel@redhat.com>
@github-actions
Copy link
Copy Markdown

Docker image build succeeded: quay.io/eclipse/che-dashboard:pr-1562 (linux/amd64, linux/arm64)

kubectl patch command
kubectl patch -n eclipse-che "checluster/eclipse-che" --type=json -p="[{"op": "replace", "path": "/spec/components/dashboard/deployment", "value": {containers: [{image: "quay.io/eclipse/che-dashboard:pr-1562", name: che-dashboard}]}}]"

@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

Codecov Report

❌ Patch coverage is 92.00000% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.50%. Comparing base (7c47bc5) to head (994ad51).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
...c/components/WorkspaceProgress/StepTitle/index.tsx 88.00% 4 Missing and 2 partials ⚠️
...nents/WorkspaceProgress/StepTitle/announceQueue.ts 93.75% 4 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main    #1562    +/-   ##
========================================
  Coverage   92.50%   92.50%            
========================================
  Files         561      564     +3     
  Lines       55866    56309   +443     
  Branches     4221     4272    +51     
========================================
+ Hits        51678    52091   +413     
- Misses       4140     4166    +26     
- Partials       48       52     +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants