mcpField
A
accessibility

accessibility

github.com/ui5Design & UI1.8k247 installsUpdated today
Repository

About accessibility

A reference skill for building accessible interfaces with UI5 Web Components. It helps UI developers apply component APIs for labels, descriptions, semantics, announcements, and themes beyond the accessibility support built into the components.

Key features

  1. 01Built-in ARIA roles and state mapping
  2. 02Keyboard navigation and focus handling
  3. 03Accessible labels and descriptions
  4. 04Semantic heading and icon settings
  5. 05Screen reader announcements
  6. 06High-contrast theme guidance

Use cases

  1. 01Labeling icon-only controls
  2. 02Associating visible labels with inputs
  3. 03Announcing search results or validation
  4. 04Adapting themes to contrast preferences

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/ui5/webcomponents --skill accessibility

After installing, type/accessibilityin Claude Code to confirm it loaded.

Details

From the project README

Accessibility in UI5 Web Components

UI5 Web Components have built-in accessibility: ARIA roles, keyboard navigation, screen reader support, and high contrast themes are handled automatically in the shadow DOM. Applications should use the accessibility APIs described here to provide additional context that only the app can know (labels, descriptions, relationships).

Built-in Accessibility (No App Code Needed)

Components automatically provide:

  • ARIA roles and attributes mapped in the shadow DOM (e.g., ui5-combobox renders role="combobox" internally)
  • Keyboard navigation within complex components (arrow keys in lists, tables, date pickers, etc.)
  • Focus management with visible focus indicators
  • State mapping — disabled, readonly, required, checked are automatically mapped to their ARIA equivalents (aria-disabled, aria-readonly, aria-required, aria-checked)

Accessibility APIs

Use these properties to enrich the accessibility context for your application.

accessibleName

Maps to aria-label. Provides a text alternative when the visual label is insufficient or absent.

<ui5-button icon="sap-icon://edit" accessible-name="Edit document"></ui5-button>

<ui5-combobox accessible-name="Select country">
    <ui5-cb-item text="Germany"></ui5-cb-item>
</ui5-combobox>

Use accessibleName when there is no visible text label, for example icon-only buttons or inputs without a <ui5-label>.

accessibleNameRef

Alternative to aria-labelledby that works across shadow DOM boundaries. Takes one or more IDs of elements whose text content serves as the label.

<ui5-label id="lblName">Full name</ui5-label>
<ui5-input accessible-name-ref="lblName"></ui5-input>

<!-- Multiple refs -->
<span id="prefix">Shipping</span>
<ui5-label id="lblAddr">Address</ui5-label>
<ui5-input accessible-name-ref="prefix lblAddr"></ui5-input>

Prefer accessibleNameRef over accessibleName when a visible label exists — this keeps the label and the ARIA text in sync automatically.

accessibleDescription / accessibleDescriptionRef

Maps to aria-description. Provides additional descriptive text beyond the label.

<ui5-input accessible-name="Password"
           accessible-description="Must be at least 8 characters">
</ui5-input>

<!-- Or reference an existing element -->
<p id="hint">Must be at least 8 characters</p>
<ui5-input accessible-name="Password"
           accessible-description-ref="hint">
</ui5-input>
accessibleRole

Overrides the default ARIA role of a component.

<ui5-panel accessible-role="Complementary">...</ui5-panel>
<ui5-list accessible-role="Menu">...</ui5-list>
<ui5-button accessible-role="Link">Navigate</ui5-button>

Only change the role when the component is used in a non-standard way (e.g., a List used as a menu).

accessibilityAttributes

An object that sets additional ARIA attributes on the component's root element. Use for aria-expanded, aria-haspopup, aria-controls, and similar relationship attributes.

<ui5-button id="menuBtn">Open Menu</ui5-button>
<ui5-menu id="menu">...</ui5-menu>

<script>
document.getElementById("menuBtn").accessibilityAttributes = {
    expanded: false,
    hasPopup: "menu",
    controls: "menu"
};
</script>

For composite components like ui5-shellbar, the object contains nested objects for different internal elements — check the component's API docs.

Label-Input Relationships

Due to shadow DOM, standard HTML <label for="..."> does not work with custom elements. Use these patterns instead:

Using Label's for property (preferred for forms):

<ui5-label for="nameInput" required show-colon>Name</ui5-label>
<ui5-input id="nameInput" required></ui5-input>

The for property connects the label to the input. Clicking the label focuses the input. Setting required on the label shows an asterisk; setting required on the input sets aria-required.

Using accessibleNameRef:

<ui5-label id="dateLabel">Date of birth</ui5-label>
<ui5-date-picker accessible-name-ref="dateLabel"></ui5-date-picker>

Headings and Semantic Levels

Use the level property on ui5-title and header-level on ui5-panel to set the correct heading level for the document outline.

<ui5-title level="H1">Page Title</ui5-title>

<ui5-panel header-text="Settings" header-level="H2">
    <ui5-title level="H3">General</ui5-title>
</ui5-panel>

Screen readers use heading levels to build a page outline. Skipping levels (e.g., H1 to H4) is an accessibility violation.

Icon Accessibility

The ui5-icon component has a mode property that controls its accessible behavior:

ModeBehaviorUse when
Image (default)role="img"Icon conveys meaning (needs accessible-name)
Interactiverole="button", focusableIcon is clickable
Decorativearia-hidden="true"Icon is purely visual, no meaning
<!-- Meaningful icon — needs accessible-name -->
<ui5-icon name="sap-icon://warning" mode="Image"
          accessible-name="Warning"></ui5-icon>

<!-- Clickable icon -->
<ui5-icon name="sap-icon://delete" mode="Interactive"
          accessible-name="Delete item"></ui5-icon>

<!-- Decorative icon — hidden from screen readers -->
<ui5-icon name="sap-icon://favorite" mode="Decorative"></ui5-icon>

Always set accessible-name on icons in Image or Interactive mode.

Invisible Messaging

Use InvisibleMessage to announce dynamic content changes to screen readers (e.g., search results count, form validation, live updates).

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

// Polite: announced at the next pause (e.g., search results)
announce("5 results found", InvisibleMessageMode.Polite);

// Assertive: announced immediately (e.g., errors)
announce("Invalid email address", InvisibleMessageMode.Assertive);
  • Use Polite for non-urgent updates (search results, status changes)
  • Use Assertive for urgent notifications (errors, warnings)

Tooltip

Use the tooltip property instead of the native title attribute.

<ui5-button icon="sap-icon://edit" tooltip="Edit document"></ui5-button>

Do not set title directly on custom elements — this can cause repetitive speech output or incorrect accessibility tree mapping.

High Contrast and Theming

UI5 Web Components ship with high contrast themes:

ThemeUse case
sap_horizonDefault light theme
sap_horizon_darkDark theme
sap_horizon_hcbHigh Contrast Black
sap_horizon_hcwHigh Contrast White

Detect OS preferences and apply the appropriate theme:

import { setTheme } from "@ui5/webcomponents-base/dist/config/Theme.js";

const darkMode = window.matchMedia("(prefers-color-scheme: dark)");
const highContrast = window.matchMedia("(prefers-contrast: more)");

function applyTheme() {
    if (highContrast.matches) {
        setTheme(darkMode.matches ? "sap_horizon_hcb" : "sap_horizon_hcw");
    } else {
        setTheme(darkMode.matches ? "sap_horizon_dark" : "sap_horizon");
    }
}

darkMode.onchange = applyTheme;
highContrast.onchange = applyTheme;
applyTheme();

Quick Reference

GoalProperty / API
Label a component without visible textaccessible-name="..."
Link a visible label to a componentaccessible-name-ref="labelId" or <ui5-label for="inputId">
Add a descriptionaccessible-description="..." or accessible-description-ref="id"
Change ARIA roleaccessible-role="..."
Set expanded/haspopup/controlsaccessibilityAttributes = { expanded, hasPopup, controls }
Set heading levellevel="H2" on Title, header-level="H2" on Panel
Make icon accessiblemode="Image" + accessible-name="..."
Hide decorative iconmode="Decorative"
Announce dynamic changesannounce(message, InvisibleMessageMode.Polite)
Set tooltiptooltip="..." (not title)
Respond to OS contrast settingsUse prefers-contrast media query + setTheme()

Comments

Markdown supported