Skip to content
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

feat(ui5-menu-item): add accessibility attributes #9333

Merged
merged 6 commits into from
Jul 8, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/base/src/types.ts
Original file line number Diff line number Diff line change
@@ -57,8 +57,9 @@ type AccessibilityAttributes = {
controls?: LowercaseString<string>
expanded?: "true" | "false" | boolean,
hasPopup?: ARIAHasPopup,
name?: string
name?: string,
role?: ARIARoles,
ariaKeyShortcuts?: string,
}

export type {
1 change: 1 addition & 0 deletions packages/main/src/ListItem.hbs
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
aria-selected="{{_accInfo.ariaSelected}}"
aria-checked="{{_accInfo.ariaChecked}}"
aria-owns="{{_accInfo.ariaOwns}}"
aria-keyshortcuts="{{_accInfo.ariaKeyShortcuts}}"
>
{{> listItemPreContent}}

1 change: 1 addition & 0 deletions packages/main/src/ListItem.ts
Original file line number Diff line number Diff line change
@@ -65,6 +65,7 @@ type AccInfo = {
listItemAriaLabel?: string;
ariaOwns?: string;
tooltip?: string;
ariaKeyShortcuts?: string;
}

type ListItemAccessibilityAttributes = Pick<AccessibilityAttributes, "hasPopup" | "ariaSetsize" | "ariaPosinset">;
6 changes: 5 additions & 1 deletion packages/main/src/MenuItem.hbs
Original file line number Diff line number Diff line change
@@ -23,7 +23,11 @@
{{else if hasEndContent}}
<slot name="endContent"></slot>
{{else if additionalText}}
<span part="additional-text" class="ui5-li-additional-text">{{additionalText}}</span>
<span
part="additional-text"
class="ui5-li-additional-text"
aria-hidden="{{_accInfo.ariaHidden}}"
>{{additionalText}}</span>
{{/if}}

{{/inline}}
24 changes: 23 additions & 1 deletion packages/main/src/MenuItem.ts
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@ import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
import { isPhone } from "@ui5/webcomponents-base/dist/Device.js";
import AriaHasPopup from "@ui5/webcomponents-base/dist/types/AriaHasPopup.js";
import type { AccessibilityAttributes } from "@ui5/webcomponents-base/dist/types.js";
import type { ListItemAccessibilityAttributes } from "./ListItem.js";
import ListItem from "./ListItem.js";
import ResponsivePopover from "./ResponsivePopover.js";
import type PopoverPlacement from "./types/PopoverPlacement.js";
@@ -24,6 +26,8 @@ import menuItemCss from "./generated/themes/MenuItem.css.js";
type MenuBeforeOpenEventDetail = { item?: MenuItem };
type MenuBeforeCloseEventDetail = { escPressed: boolean };

type MenuItemAccessibilityAttributes = Pick<AccessibilityAttributes, "ariaKeyShortcuts" | "role"> & ListItemAccessibilityAttributes;

/**
* @class
*
@@ -142,6 +146,21 @@ class MenuItem extends ListItem implements IMenuItem {
@property()
tooltip?: string;

/**
* Defines the additional accessibility attributes that will be applied to the component.
* The following fields are supported:
*
* - **ariaKeyShortcuts**: Indicated the availability of a keyboard shortcuts defined for the menu item.
*
* - **role**: Defines the role of the menu item. If not set, menu item will have default role="menuitem".
*
* @public
* @since 2.1.0
* @default {}
*/
@property({ type: Object })
accessibilityAttributes: MenuItemAccessibilityAttributes = {};

/**
* Indicates whether any of the element siblings have icon.
*/
@@ -242,8 +261,10 @@ class MenuItem extends ListItem implements IMenuItem {

get _accInfo() {
const accInfoSettings = {
role: "menuitem",
role: this.accessibilityAttributes.role || "menuitem",
ariaHaspopup: this.hasSubmenu ? AriaHasPopup.Menu.toLowerCase() as Lowercase<AriaHasPopup> : undefined,
ariaKeyShortcuts: this.accessibilityAttributes.ariaKeyShortcuts,
ariaHidden: !!this.additionalText && !!this.accessibilityAttributes.ariaKeyShortcuts ? true : undefined,
};

return { ...super._accInfo, ...accInfoSettings };
@@ -314,4 +335,5 @@ export default MenuItem;
export type {
MenuBeforeCloseEventDetail,
MenuBeforeOpenEventDetail,
MenuItemAccessibilityAttributes,
};
24 changes: 20 additions & 4 deletions packages/main/test/pages/Menu.html
Original file line number Diff line number Diff line change
@@ -15,15 +15,15 @@
<body class="bg">
<ui5-button id="btnOpen">Open Menu</ui5-button> <br/>
<ui5-menu id="menu" header-text="My ui5-menu">
<ui5-menu-item text="New File(selection prevented)" accessible-name="Opens a file explorer" additional-text="Ctrl+Alt+Shift+N" tooltip="Select a file - prevent default" icon="add-document"></ui5-menu-item>
<ui5-menu-item id="menuItemNewFile" text="New File (selection prevented)" accessible-name="Opens a file explorer" additional-text="Ctrl+Alt+Shift+N" tooltip="Select a file - prevent default" icon="add-document"></ui5-menu-item>
<ui5-menu-item text="New Folder with very long title for a menu item" additional-text="Ctrl+F" icon="add-folder" disabled>
<ui5-menu-item text="test.txt"></ui5-menu-item>
</ui5-menu-item>
<ui5-menu-separator></ui5-menu-separator>
<ui5-menu-item text="Open" icon="open-folder" accessible-name="Choose platform" loading-delay="100" loading>
<ui5-menu-item text="Open Locally" icon="open-folder" additional-text="Ctrl+K">
<ui5-menu-item text="Open from C"></ui5-menu-item>
<ui5-menu-item text="Open from D"></ui5-menu-item>
<ui5-menu-item id="menuItemFromC" text="Open from C"></ui5-menu-item>
<ui5-menu-item id="menuItemFromD" text="Open from D"></ui5-menu-item>
<ui5-menu-separator></ui5-menu-separator>
<ui5-menu-item text="Open from E" disabled></ui5-menu-item>
</ui5-menu-item>
@@ -40,7 +40,7 @@
<ui5-menu-item text="Close" additional-text="Ctrl+W" loading-delay="100" loading></ui5-menu-item>
<ui5-menu-separator></ui5-menu-separator>
<ui5-menu-item text="Preferences" icon="action-settings" disabled></ui5-menu-item>
<ui5-menu-item text="Exit" icon="journey-arrive"></ui5-menu-item>
<ui5-menu-item id="menuItemExit" text="Exit" icon="journey-arrive"></ui5-menu-item>
</ui5-menu>

<ui5-title level="H5" class="header-title">Clicked menu item text</ui5-title>
@@ -243,6 +243,22 @@
console.warn("Item clicked: " + event.detail.item.text);
});

menuItemNewFile.accessibilityAttributes = {
ariaKeyShortcuts: "Ctrl+Alt+Shift+N",
}

menuItemExit.accessibilityAttributes = {
ariaKeyShortcuts: "Ctrl+X",
}

menuItemFromC.accessibilityAttributes = {
role: "menuitemcheckbox",
};

menuItemFromD.accessibilityAttributes = {
role: "menuitemcheckbox",
};

</script>
</body>
</html>
25 changes: 24 additions & 1 deletion packages/main/test/specs/Menu.cy.js
Original file line number Diff line number Diff line change
@@ -60,7 +60,7 @@ describe("Menu interaction", () => {
cy.get("[ui5-menu]")
.ui5MenuOpened();


cy.get("[ui5-menu-item][text='Item 1.0']")
.as("item")
.ui5MenuItemClick();
@@ -309,6 +309,7 @@ describe("Menu interaction", () => {
<ui5-menu-item text="Item 1.1"></ui5-menu-item>
</ui5-menu-item>
<ui5-menu-item text="Item 2.0" accessible-name="test accessible name"></ui5-menu-item>
<ui5-menu-item text="Item 3.0" additional-text="Ctrl+A"></ui5-menu-item>
</ui5-menu>`)

cy.get("[ui5-menu]")
@@ -334,6 +335,28 @@ describe("Menu interaction", () => {
cy.get("@items")
.eq(1)
.should("have.attr", "accessible-name", "test accessible name")

cy.get("@items")
.eq(2)
.then($el => {
$el.get(0).accessibilityAttributes = {
ariaKeyShortcuts: "Ctrl+A",
role: "menuitemcheckbox",
}
})

cy.get("@items")
.eq(2)
.shadow()
.find("li")
.should("have.attr", "aria-keyshortcuts", "Ctrl+A", "aria-keyshortcuts attribute is reflected")
.and("have.attr", "role", "menuitemcheckbox", "role attribute is reflected")

cy.get("@items")
.eq(2)
.shadow()
.find("li .ui5-li-additional-text")
.should("have.attr", "aria-hidden", "true", "aria-hidden attribute is set to true")
});
})
})