-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Accessibility
In order for VoiceOver to work properly with a checkbox component there must be a native input
with type="checkbox"
, and aria-checked
and role="checkbox"
must be on the host element. The aria-hidden
attribute needs to be added if the checkbox is disabled, preventing iOS users from selecting it:
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="checkbox"
>
<input
type="checkbox"
/>
...
</Host>
);
}
It is required to have aria-checked
on the native input for checked to read properly and disabled
to prevent tabbing to the input:
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="checkbox"
>
<input
type="checkbox"
aria-checked={`${checked}`}
disabled={disabled}
/>
...
</Host>
);
}
A helper function has been created to get the proper aria-label
for the checkbox. This can be imported as getAriaLabel
like the following:
const { label, labelId, labelText } = getAriaLabel(el, inputId);
where el
and inputId
are the following:
export class Checkbox implements ComponentInterface {
private inputId = `ion-cb-${checkboxIds++}`;
@Element() el!: HTMLElement;
...
}
This can then be added to the Host
like the following:
<Host
aria-labelledby={label ? labelId : null}
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="checkbox"
>
In addition to that, the checkbox input should have a label added:
<Host
aria-labelledby={label ? labelId : null}
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="checkbox"
>
<label htmlFor={inputId}>
{labelText}
</label>
<input
type="checkbox"
aria-checked={`${checked}`}
disabled={disabled}
id={inputId}
/>
A helper function to render a hidden input has been added, it can be added in the render
:
renderHiddenInput(true, el, name, (checked ? value : ''), disabled);
This is required for the checkbox to work with forms.
When using VoiceOver on macOS, Chrome will announce the following when you are focused on a checkbox:
currently on a checkbox inside of a checkbox
This is a compromise we have to make in order for it to work with the other screen readers & Safari.
In order for VoiceOver to work properly with a switch component there must be a native input
with type="checkbox"
and role="switch"
, and aria-checked
and role="switch"
must be on the host element. The aria-hidden
attribute needs to be added if the switch is disabled, preventing iOS users from selecting it:
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="switch"
>
<input
type="checkbox"
role="switch"
/>
...
</Host>
);
}
It is required to have aria-checked
on the native input for checked to read properly and disabled
to prevent tabbing to the input:
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="switch"
>
<input
type="checkbox"
role="switch"
aria-checked={`${checked}`}
disabled={disabled}
/>
...
</Host>
);
}
A helper function has been created to get the proper aria-label
for the switch. This can be imported as getAriaLabel
like the following:
const { label, labelId, labelText } = getAriaLabel(el, inputId);
where el
and inputId
are the following:
export class Toggle implements ComponentInterface {
private inputId = `ion-tg-${toggleIds++}`;
@Element() el!: HTMLElement;
...
}
This can then be added to the Host
like the following:
<Host
aria-labelledby={label ? labelId : null}
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="switch"
>
In addition to that, the checkbox input should have a label added:
<Host
aria-labelledby={label ? labelId : null}
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="switch"
>
<label htmlFor={inputId}>
{labelText}
</label>
<input
type="checkbox"
role="switch"
aria-checked={`${checked}`}
disabled={disabled}
id={inputId}
/>
A helper function to render a hidden input has been added, it can be added in the render
:
renderHiddenInput(true, el, name, (checked ? value : ''), disabled);
This is required for the switch to work with forms.
When using VoiceOver on macOS or iOS, Chrome will announce the switch as a checked or unchecked checkbox
:
You are currently on a switch. To select or deselect this checkbox, press Control-Option-Space.
There is a WebKit bug open for this: https://bugs.webkit.org/show_bug.cgi?id=196354