Having explored the 8 common web accessibility mistakes in the first two parts, we now turn to a practical case study!
The example of the Dropdown
We're now going to apply these concepts to an example: the Dropdown.
Le composant Dropdown est probablement l’un des plus “recodé”, puisqu’il vise à remplacer la balise native `<select>` qui est très peu personnalisable pour des applications au design moderne.
Ainsi, nous devons reproduire un à un les comportements et fonctionnalités proposés nativement par le `<select>` natif pour ne pas perdre en accessibilité :
- l’apparition de la liste d’éléments lors du déclanchement d’un `<input>` (click ou via le clavier)
- navigation using directional arrows (up and down) to select an item
- select a previously chosen item from the keyboard
- click to select an element
- l’affichage de la valeur sélectionnée disponible dans un `<input>` (champ de saisie) en `readonly` pouvant recevoir le focus
Note: Many other features also need to be implemented, such as direct focus on an item, filtering from the keyboard, more navigation keys... See here
To meet the defined need, we're going to use several roles and ARIA to semantically complement the use of our html tags:
- role="combobox"` : Input controlling another element that appears dynamically to help the user choose a value.
- role="listbox"` : User can select items from this list
- `role=”option”` : Elément d’une liste pouvant être sélectionné (équivalent à la balise `<option>` mais hors d’un select et autorisant plus de contenu)
- aria-controls`: The combobox controls this listbox
- `aria-expanded`: Describes whether the linked listbox is visible or not
- `aria-activedescendant`: This property identifies the active option in a list during keyboard navigation (via its `id`).
- `aria-selected`: This property indicates that an option is selected.
my-dropdown.component.html
@for (option of options; track $index) {
@let isCurrent = selectedValue === option;
-
{{ option }}
}
my-dropdown.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-dropdown',
templateUrl: './my-dropdown.component.html'
})
export class MyDropdownComponent {
/**
* The possible values
*/
options = ['Choose a value', 'first value', 'second value', 'third value'];
/**
* The selected value
*/
selectedValue = this.options[1];
/**
* Manage the display of the list of values
*/
protected isOpened = false;
/**
* The currently active value using keyboard management
*/
protected activeValue!: string;
/**
* The currently active value using keyboard management
*/
protected activeValueIndex!: number;
/**
* Select the value and focus the dropdown input
*/
selectValue(value: string): void {
this.selectedValue = value;
this.activeValue = value;
this.isOpened = false;
}
/**
* Trigger the opening of the dropdown and the focus element
*/
protected triggerOpening(): void {
this.isOpened = !this.isOpened;
if (this.isOpened) {
this.setActiveItem(this.selectedValue);
} else {
this.selectValue(this.activeValue);
}
}
protected manageInputKeydown(event: KeyboardEvent): void {
switch (event.code) {
case 'Enter':
case 'NumpadEnter':
case 'Space':
this.triggerOpening();
break;
case 'ArrowUp':
if (this.isOpened) {
if (this.activeValueIndex > 0) {
this.setActiveItem(this.options[this.activeValueIndex - 1]);
}
}
break;
case 'ArrowDown':
if (this.isOpened) {
if (this.activeValueIndex < this.options.length) {
this.setActiveItem(this.options[this.activeValueIndex + 1]);
}
}
}
}
protected manageBackdropKeydown(event: KeyboardEvent): void {
switch (event.code) {
case 'Enter':
case 'NumpadEnter':
case 'Space':
case 'Escape':
this.isOpened = false;
}
}
protected manageOptionKeydown(event: KeyboardEvent, value: string): void {
switch (event.code) {
case 'Enter':
case 'NumpadEnter':
this.selectValue(value);
break;
case 'Escape':
this.isOpened = false;
break;
}
}
/**
* Set the active item after keyboard navigation
*/
private setActiveItem(id: string): void {
const item = this.options.find(option => option === id);
if (item) {
this.activeValue = item;
this.activeValueIndex = this.options.findIndex(option => option === id);
}
}
}
Bonus : Test it yourself
During the various tests carried out on the interfaces developed, you can already test certain points relating to accessibility.
For example, by using a screen reader during the development phase and functional testing. We can also check whether the user can navigate simply and efficiently through the application and its components, using only the keyboard and not the mouse.
You need to ask yourself the right questions:
- Am I able to understand the information I want to convey to my user?
- Can I easily access the features I'm looking for?
- Can I understand the page structure and the logical positioning of the content?
- Was it easy to interact with the various elements?
- Was I able to identify the various links, buttons, etc. and their effects?
Conclusion
We've taken a look at 8 different errors that are all too common in web development, and which are detrimental to the accessibility of applications, along with simple solutions to correct them.
Ideally, these rules should be mentioned as soon as a project is launched or new functions are designed. This ensures that they are respected from the outset, and that adaptation costs are limited or avoided.
The implementation of defined rules, whether during the development or validation phase, also helps to maximize compliance.
There are many rules to be respected in terms of accessibility, depending on the content of the application being developed. It is therefore essential to obtain information, for example from the[WCAG] (web accessibility guidelines) or more widely from the[W3C] (consortium defining web standards).
FAQ - Web accessibility
It ensures that all users, including those with disabilities, can navigate, understand and interact with a site. It's an ethical, legal and UX issue.
Lack of contrast, absence of text alternatives, poor content structuring, buttons not accessible from the keyboard or poorly marked decorative visuals.
By complying with the RGAA, testing the site with screen readers, checking contrasts and structuring content with correct tags.
Yes, search engines value structured, accessible, high-performance sites. Accessibility and SEO often go hand in hand.
Alexandre PICARD
Practice Leader Product Development in Toulouse
& Tech Lead Angular