-
Notifications
You must be signed in to change notification settings - Fork 281
fix(ui5-select): fix acc finding #13559
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 12 commits
9a48ffa
fa01dc5
0be0532
33c5c37
f16945d
04a2ef0
317ba3a
310b4d3
1528770
4a41098
466d381
55e0544
a716162
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,6 +34,7 @@ import "@ui5/webcomponents-icons/dist/sys-enter-2.js"; | |
| import "@ui5/webcomponents-icons/dist/information.js"; | ||
| import { isPhone } from "@ui5/webcomponents-base/dist/Device.js"; | ||
| import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; | ||
| import type { I18nText } from "@ui5/webcomponents-base/dist/i18nBundle.js"; | ||
| import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js"; | ||
| import type { Timeout, AriaRole } from "@ui5/webcomponents-base/dist/types.js"; | ||
| import InvisibleMessageMode from "@ui5/webcomponents-base/dist/types/InvisibleMessageMode.js"; | ||
|
|
@@ -49,9 +50,10 @@ import { | |
| VALUE_STATE_TYPE_INFORMATION, | ||
| VALUE_STATE_TYPE_ERROR, | ||
| VALUE_STATE_TYPE_WARNING, | ||
| INPUT_SUGGESTIONS_TITLE, | ||
| LIST_ITEM_POSITION, | ||
| SELECT_ROLE_DESCRIPTION, | ||
| SELECT_POPOVER_ACCESSIBLE_NAME_PREFIX, | ||
| SELECT_LISTBOX_LABEL, | ||
| SELECT_DIALOG_CANCEL_BUTTON, | ||
| FORM_SELECTABLE_REQUIRED, | ||
| } from "./generated/i18n/i18n-defaults.js"; | ||
|
|
@@ -95,6 +97,13 @@ const isPrintableCharacter = (e: KeyboardEvent) => { | |
| return e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey; | ||
| }; | ||
|
|
||
| const isI18nText = (value: unknown): value is I18nText => { | ||
| return typeof value === "object" | ||
| && value !== null | ||
| && "key" in value | ||
| && "defaultText" in value; | ||
| }; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Generated i18n constants are always typed as return Select.i18nBundle.getText(SELECT_ROLE_DESCRIPTION);
return Select.i18nBundle.getText(FORM_SELECTABLE_REQUIRED);no guards needed. The TS error that prompted the workaround was almost certainly because Leaving the guard in is bad on two counts:
Please remove |
||
|
|
||
| /** | ||
| * @class | ||
| * | ||
|
|
@@ -1047,7 +1056,11 @@ class Select extends UI5Element implements IFormInputElement { | |
| } | ||
|
|
||
| get _headerTitleText() { | ||
| return Select.i18nBundle.getText(INPUT_SUGGESTIONS_TITLE); | ||
| if (typeof SELECT_LISTBOX_LABEL === "string" || isI18nText(SELECT_LISTBOX_LABEL)) { | ||
| return Select.i18nBundle.getText(SELECT_LISTBOX_LABEL); | ||
| } | ||
|
|
||
| return ""; | ||
| } | ||
|
|
||
| get _cancelButtonText() { | ||
|
|
@@ -1121,6 +1134,18 @@ class Select extends UI5Element implements IFormInputElement { | |
| return getEffectiveAriaLabelText(this) || getAssociatedLabelForTexts(this); | ||
| } | ||
|
|
||
| get _effectivePopoverAccessibleName() { | ||
| const fieldName = this.ariaLabelText || this._headerTitleText; | ||
| if (!fieldName) { | ||
| return undefined; | ||
| } | ||
| const prefix = (typeof SELECT_POPOVER_ACCESSIBLE_NAME_PREFIX === "string" | ||
| || isI18nText(SELECT_POPOVER_ACCESSIBLE_NAME_PREFIX)) | ||
| ? Select.i18nBundle.getText(SELECT_POPOVER_ACCESSIBLE_NAME_PREFIX) | ||
| : ""; | ||
| return `${prefix} ${fieldName}`; | ||
| } | ||
|
|
||
| get shouldDisplayDefaultValueStateMessage() { | ||
| return !this.valueStateMessage.length && this.hasValueStateText; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,7 +26,7 @@ export default function SelectPopoverTemplate(this: Select) { | |
| onBeforeOpen={this._beforeOpen} | ||
| onClose={this._afterClose} | ||
| onKeyDown={this._onkeydown} | ||
| accessibleName={this._isPhone ? this._headerTitleText : undefined} | ||
| accessibleName={this._isPhone ? this._effectivePopoverAccessibleName : undefined} | ||
| > | ||
| {this._isPhone && | ||
| <div slot="header" class="ui5-responsive-popover-header"> | ||
|
|
@@ -62,6 +62,7 @@ export default function SelectPopoverTemplate(this: Select) { | |
| onMouseDown={this._itemMousedown} | ||
| onItemClick={this._handleItemPress} | ||
| accessibleRole="ListBox" | ||
| accessibleName={this.ariaLabelText || this._headerTitleText} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicated expression (low).
get _effectivePopoverAccessibleName() {
return this.ariaLabelText || this._headerTitleText;
}and using it on both lines. Matches how
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Borrowed i18n key — please add a dedicated one (low).
Please introduce a Select-specific i18n key (e.g.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No test coverage added (medium). This PR changes ARIA wiring on two surfaces but adds no test. The branch history (two
Without these, the next refactor of
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: since |
||
| > | ||
| <slot></slot> | ||
| </List> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -321,6 +321,12 @@ SELECT_ROLE_DESCRIPTION=Listbox | |
| #XTXT: MultiComboBox and ComboBox icon accessible name | ||
| SELECT_OPTIONS=Select Options | ||
|
|
||
| #XACT: ARIA announcement prefix for Select dialog accessible name on mobile (without trailing space) | ||
| SELECT_POPOVER_ACCESSIBLE_NAME_PREFIX=Select: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cleaner than embedding the space in the translation — translators can't accidentally drop trailing whitespace, and the join is done explicitly in code. Good fix. (No action needed — leaving the comment here so the rationale is visible in review.) |
||
|
|
||
| #XACT: ARIA accessible name for Select's listbox when no explicit label is provided | ||
| SELECT_LISTBOX_LABEL=All Items | ||
|
|
||
| #XTXT: MultiComboBox show selected items button accessible name | ||
| SHOW_SELECTED_BUTTON=Show Selected Items Only | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assertion is now circular. It reads the value of
_effectivePopoverAccessibleNamefrom the element and then asserts the rendered attribute equals that same value — so if the getter is broken, both sides of the equality break the same way and the test still passes.The other new test (
Select.cy.tsx:325) hard-codes"Select: Countries"for the mobile case, so coverage isn't lost — but consider either deleting this case or changing it to assert a literal string. Either way, the property-readback pattern hides regressions.