Document Properties
Kbid
308A37
Last Modified
22-Feb-2024
Added to KB
18-Apr-2023
Public Access
Everyone
Status
Online
Doc Type
Guidelines
Product
Intershop Progressive Web App
Guide - Intershop Progressive Web App - Accessibility

The goal of accessibility is to unlock the full potential of the Web and enable people with disabilities to participate equally.
The @angular-eslint repo contains a number of linting rules that can help enforce accessibility best practices in Angular component templates.

Most of the accessibility rules that are enabled in the Intershop PWA are contained in the plugin @angular-eslint/template/accessibility that is configured in the .eslintrc.json file of the project.
To check whether the rules are followed in your custom code or not, run npm run lint.

General

Attributes and Roles

Generally it is checked if valid aria-* and role=* attributes are used and that every necessary element is reachable with the keyboard, and that an action (like pressing enter) can be performed on them.

Titles instead of ARIA-Attributes

If an element has to be made more descriptive by adding a title-attribute or an aria-label, we decided to use the title and not the label, because a title provides visual feedback and can also be read as a label by screen-readers.

Wrong HTML structure, title and aria-label would be read by a screen-reader

<button [title]="Close" [aria-label]="close">
  <span>x</span>
</button>

⚠️ Only use when no title is needed

<button [title]="Close" [aria-label]="close">
  <span>x</span>
</button>

✔️ Preferred HTML structure

<button [title]="Close">
  <span>x</span>
</button>

Usage of native HTML-Elements

It is generally advised to use native HTML-elements instead of giving roles to container-elements like a <div>, because native elements already bring most accessibility functionalities with them, like tab-focus and confirm by pressing enter.
If, for example, instead of a <button> a <div role="button"> is used, the functionality of pressing enter to activate the button has to be manually implemented via code.

⚠️ Don't assign roles to HTML-elements that exist natively

<div role="button">
  <span>x</span>
</div>

✔️ Use native HTML-elements if they exist

<button [title]="Close">
  <span>x</span>
</button>

ESLint Rules

ESLint provides a plugin that includes most of the necessary accessibility-rules.
Only some individual rules that do not come with this plugin are specifically written down here.

Accessibility Plugin

plugin:@angular-eslint/template/accessibility

For reference on which rules the plugin currently includes, please check the official repository:

Additional Rules

@angular-eslint/template/no-positive-tabindex

If an unreachable element has to be made reachable by providing a tabindex, the index should never be a positive number, only 0 (element is tab focusable) or -1 (element is not tab focusable).
The tab-order has to be determined by the HTML-structure, not by the index.

Project specific Applications

How to fix click-events-have-key-events problems

To address this issue, make sure that every <a> tag in the HTML files includes a routerLink attribute.
If a link is only intended to trigger an action and not used to navigate the user to another page, it is recommended to use <button> tags instead of anchor tags, because buttons inherently provide better support for keyboard interactions and enhance overall accessibility.
To make the buttons look like links use the css classes btn btn-link btn-link-action for text links and btn-tool btn-link for icon links.
In case you have to use anchor tags nevertheless e.g. because of styling issues make sure you define a keypress.enter action and the tabindex="0" attribute for the anchor tag.

Other HTML elements (<div>, <span>, etc.) with a click() event that report this ESLint error can be fixed by adding a (keydown.enter) event that should be assigned with the click() event's method.
In addition, a tabindex="0" needs to be added to such elements to make them tab focusable.

Form Submission using the key "Enter"

Implicit form submission using the "Enter" key is vital to assistive technologies, see also HTML5 specification.
Therefore, the form tag has to include an input of type="submit", for example

<form>
  <label for="foo">Name:</label>
  <input type="text" name="foo" id="foo" />
  <input type="submit" value="Submit" />
</form>

or a button of type "submit"

<form>
  <label for="foo">Name:</label>
  <input type="text" name="foo" id="foo" />
  <button type="submit">Submit</button>
</form>

Form submission in dialogs

Dialogs (or modals) are separated into three sections:

  • modal header
  • modal body
  • modal footer

where the form is positioned inside the model body and the buttons are positioned inside the modal footer.
The following simplified example shows the wrong HTML structure:

⚠️ Wrong HTML structure

<div class="modal-body">
  <form (ngSubmit)="submit()">
    <formly-form></formly-form>
  </form>
</div>
<div class="modal-footer">
  <button type="button" (click)="submit()">Submit</button>
  <button type="button" (click)="cancel()">Cancel</button>
</div>

The button with the text "Submit" calls the same function foo() as the form (ngSubmit) but the form would not be submitted using the "Enter" key because the submit button is positioned outside the form tag.
The following example shows the correct HTML structure:

✔️ Correct HTML structure

<form (ngSubmit)="submit()">
  <div class="modal-body">
    <formly-form></formly-form>
  </div>
  <div class="modal-footer">
    <button type="submit">Submit</button>
    <button type="button" (click)="cancel()">Cancel</button>
  </div>
</form>

where

  • the form tag surrounds both the formly form (including the form elements) and the submit button
  • the function submit() is only called at the form tag
  • the "Submit" button is correctly defined using type="submit" and does not call submit() using (click)=""
  • the "Cancel" button is only defined as type="button" to prevent any default behavior

Further References

Disclaimer
The information provided in the Knowledge Base may not be applicable to all systems and situations. Intershop Communications will not be liable to any party for any direct or indirect damages resulting from the use of the Customer Support section of the Intershop Corporate Web site, including, without limitation, any lost profits, business interruption, loss of programs or other data on your information handling system.
The Intershop Knowledge Portal uses only technically necessary cookies. We do not track visitors or have visitors tracked by 3rd parties. Please find further information on privacy in the Intershop Privacy Policy and Legal Notice.
Home
Knowledge Base
Product Releases
Log on to continue
This Knowledge Base document is reserved for registered customers.
Log on with your Intershop Entra ID to continue.
Write an email to supportadmin@intershop.de if you experience login issues,
or if you want to register as customer.