Skip to content

feat(ui5-list): add live region announcement for item selection#13440

Open
NakataCode wants to merge 3 commits intomainfrom
feat/list-live-region-selection-announcement
Open

feat(ui5-list): add live region announcement for item selection#13440
NakataCode wants to merge 3 commits intomainfrom
feat/list-live-region-selection-announcement

Conversation

@NakataCode
Copy link
Copy Markdown
Contributor

@NakataCode NakataCode commented Apr 28, 2026

Problem:

  • When a user selects or deselects a list item with a mouse click, screen readers get no immediate feedback. They only discover the selection state when navigating back to the item, because the AT reads aria-selected on focus.

Solution:

  • Call announce() (InvisibleMessage) with a polite live region announcement immediately after a selection change succeeds. The text is "Selected" or "Not Selected" using the existing i18n strings LIST_ITEM_SELECTED / LIST_ITEM_NOT_SELECTED.

What's covered:

  • All selectable modes: Single, SingleStart, SingleEnd, SingleAuto, Multiple
  • Mouse clicks and keyboard (Space/Enter)
  • SingleAuto arrow-key navigation (goes through the same onSelectionRequested path)
  • No announcement when selectionMode="None"
  • No announcement when the consumer prevents the selection-change event
  • Delete mode is naturally excluded — it never toggles selected

Announces "Selected" or "Not Selected" via InvisibleMessage when a list
item's selection state changes in any selectionMode other than "None".
Covers Single, SingleStart, SingleEnd, SingleAuto, and Multiple modes.
@ui5-webcomponents-bot
Copy link
Copy Markdown
Collaborator

ui5-webcomponents-bot commented Apr 28, 2026

@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview April 28, 2026 13:46 Inactive
@NakataCode
Copy link
Copy Markdown
Contributor Author

Code review

Found 2 issues:

  1. InvisibleMessageMode is imported as a value instead of import type + string literal (packages/base/AGENTS.md says: "BAD - imports the enum object (runtime overhead) / GOOD - import type only (no runtime overhead)" and "BAD - runtime enum access / GOOD - string comparison")

} from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js";
import getNormalizedTarget from "@ui5/webcomponents-base/dist/util/getNormalizedTarget.js";
import announce from "@ui5/webcomponents-base/dist/util/InvisibleMessage.js";
import InvisibleMessageMode from "@ui5/webcomponents-base/dist/types/InvisibleMessageMode.js";

The fix: import type InvisibleMessageMode from "..." and replace InvisibleMessageMode.Polite with "Polite".

  1. The announce() call fires in Delete selectionMode, producing a misleading "Selected" or "Not Selected" announcement when the user presses the delete button. handleDelete returns true, which sets selectionChange = true, which triggers the else branch — but the @event("selection-change") JSDoc explicitly lists only Single, SingleStart, SingleEnd, and Multiple modes, not Delete. In Delete mode, item.selected is irrelevant to the user action.

});
if (changePrevented) {
this._revertSelection(previouslySelectedItems);
} else {
const item = e.detail.item;
const selectedText = item.selected
? List.i18nBundle.getText(LIST_ITEM_SELECTED)
: List.i18nBundle.getText(LIST_ITEM_NOT_SELECTED);
announce(selectedText, InvisibleMessageMode.Polite);
}
}
}

The fix: guard the announce() call to exclude Delete mode (e.g. check this.selectionMode !== ListSelectionMode.Delete).

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@NakataCode NakataCode changed the title feat(ui5-list): add live region announcement for item selection (POC) feat(ui5-list): add live region announcement for item selection May 5, 2026
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview May 5, 2026 09:06 Inactive
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview May 5, 2026 10:20 Inactive
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.

2 participants