New Checkbox Dropdown Component (similar to and interchangeable with the ComboBox)
Problem
The current IGX ComboBox component is not entirely accessible due to a defect in JAWS and Chrome as well as the current use of accessibility roles within the Infragistics coding. The checkbox state is not announced. Ideally, the screen readers should pick up the aria-selected on the list options. But this is not working.
Solution Proposition
I propose a new component similar to (and interchangeable with) the ComboBox, but with a different approach to its accessibility code. By creating a brand new component, (with a new name) Infragistics can avoid any concern about breaking changes to the existing component, while providing its customers with a ComboBox-like alternative for improved accessibility. Presumably, this new component could be easily swapped out with the existing ComboBox component. This new component will used the checked state of the checkbox instead of relying on the aria-selected attribute (currently defective in JAWS + Chrome | Edge). I will offer a more detail in the "Details..." section below.
As an additional accessibility feature. This component could add an optional status message to indicate and update how many options are in the dropdown list as the user types. For example, as the user enters text in the textfield, a message (using aria-live="polite") would indicate "X results in list".
Alternatives Considered
I have opened (and consequently closed on June 6) a ticket with Infragistics to fix the ComboBox. Ref: https://github.com/IgniteUI/igniteui-angular/issues/15843. Because the primary problem is due to a documented defect with JAWS and Chrome, Infragistics has opted not to fix the current ComboBox, however, this does not solve our need to pass accessibility tests for out web app (the base-line for our accessibility testers is Chrome + JAWS). Ref:
- Chrome issue: https://issues.chromium.org/issues/337904204
- JAWS defect: https://github.com/FreedomScientific/standards-support/issues/733
Details: To Create a new component based on the existing ComboBox
First, give it a new name (CheckboxMenu?) and different accessibility roles:
-
Within the existing ComboBox code, strip out all the existing roles pertaining to combobox and listboxes:
-
Remove: role="combobox" from
<igx-combo-item class="igx-drop-down__item">, replace with role="menuitem" (I'm not 100% sure on this. I believe the role="menuitem" needs to go on either the<igx-combo-item>or the<igx-checkbox>itself, it looks like the focus is going to the igx-combo item. You may need to either remove this and set the focus on the<igxcheckbox>, or convert the igx-combo-item to a custom checkbox. In that case, you'll want to use role="checkbox" and THEN we can use aria-checked (since custom components use aria-checked and not "checked", you'll have to test this in JAWS) -
Remove: role="listbox" from
<div class="igx-drop-down__list-scroll"> -
Remove: aria-multiselectable from
<div class="igx-combo__content">(that's on the wrong div anyway) -
Remove: role="option" from
<div class="igx-drop-down__item"> -
Add: role="menu" to your
<igx-display-container>, as well as an aria-labelledby="igx-menubutton-{{X}}" (this ID will have to match a dynamically generated ID for the "toggle button". We'll get to that next.
Fix the existing toggle button:
The ComboBox menu toggle button is missing a label and other aria- attributes (I recommended fixing this button in the existing ComboBox in this tix: https://github.com/IgniteUI/igniteui-angular/issues/16472). These are already used on the <input class="igx-input-group__input"> so you only need to duplicate this on the toggle button.
- Add: aria-label="Toggle menu" to the
<igx-suffix class="igx-combo__toggle-button">(this would be a minimum fix, an improvement would be: aria-label="Toggle menu for {{label_of_input}}" and use the label text in there. This decreases the possibility that multiple "Toggle menu" buttons appearing on the same page. Which is considered an accessibility issue as well. If we want to take it to the next level, set this aria-label to be aria-label="{{Expand | Collapse}} menu for {{label_of_input}}" to reflect the current state, but we this can also be handled with the next step, and thus not needed if you... - Add: aria-expanded="{{ true | false }}" on this toggle button to reflect the current state of the menu. Next...
- Add: aria-controls={{ igx-drop-down-XX-list }} (set to the ID of the dropdown container)
Improve the existing toggle button's (and clear button's) visual focus indication:
- Currently, the focus indication is too subtle to pass overly picky testers because it is relying only on color changes (i.e. the button shifts its gray color and the arrow indicator turns magenta). I suggest editing the default CSS to also indicate focus by adding a black dotted outline around the buttons.
- I also added a white glow around focused buttons in my own custom CSS, as this ensures visual focus regardless of what "theme" is chosen (i.e. Material Dark, etc.)
Fix the existing <igx-checkbox>
-
Note: I have requested this fix in another bug ticket (Ref: https://github.com/IgniteUI/igniteui-angular/issues/16469). But I will include it here as well. As stated in my Bug ticket 16469, the checkboxes are native HTML checkboxes (i.e.
<input type="checkbox">) but they are using aria-checked instead of just adding and removing the "checked" attribute. The screen readers don't consistently announce aria-checked state on native HTML checkboxes. I suggest adding/removing "checked" attribute. - Add role="menuitem" needs to go on either the
<igx-combo-item>or the<igx-checkbox> -
Note: JAWS is picky about the correct parent/child relationship with its interpretation of "roles". If role="menuitem" is not the immediate child of role="menu", JAWS may not announce it. I have discovered that in order for the screen reader to properly interpret the roles, if any other node (be it a
<div>or web component) is in between a "menu" and a "menuitem" (or between a "listbox" and an "option") you have to use role="presentation" on that interfering element. (see Example here: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/menu_role )
Notes
- You may need to adjust the tabindex settings on this new component.
- The source of the screen reader problems are because the existing ComboBox is trying to force two different types of form elements (
<select multiple>and<input type="checkbox">into the same thing. The screen reader is not programmed to understand this. By creating a new component, this may free you up to making adjustments that won't affect existing components. For my project, I'd like to be able to swap out all of our accessibility-failing ComboBoxes with a new component that works with the current state of browsers/screen readers. - The status message to indicating how many options are in the dropdown list as the user types, could be set to display or not to display.
Additional Notes
- I am not sure why you're using aria-labelledby on the
<input>tags instead of using the standard ID/for pattern. For the existing ComboBox it doesn't matter since it's overwritten by the aria-label on the igx-combo-item. I bring this up because any<input>that doesn't have a corresponding<label>gets flagged in HTML validators and accessibility testing tools. - I've also noticed that the
<div class="igx-drop-down__list-scroll">uses an aria-labelledby set to a string (not an ID). I think that got fixed in the latest updates but its still showing on your example page: (https://www.infragistics.com/products/ignite-ui-angular/angular/components/combo)