[Glitch] Patch over a11y issues caused by "simple" ruby gems
Port 5553448678a8a9f4ef970948b6fb7f013e9a4238 to glitch-soc Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
parent
b0f609bfb7
commit
4eeb1b0118
@ -181,6 +181,8 @@ async function loaded() {
|
|||||||
|
|
||||||
truncateRuleHints();
|
truncateRuleHints();
|
||||||
|
|
||||||
|
applyRailsA11yPatches();
|
||||||
|
|
||||||
const reactComponents = document.querySelectorAll('[data-component]');
|
const reactComponents = document.querySelectorAll('[data-component]');
|
||||||
|
|
||||||
if (reactComponents.length > 0) {
|
if (reactComponents.length > 0) {
|
||||||
@ -515,6 +517,88 @@ on('click', '.rules-list button', ({ target }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Patch accessibility issues caused by Ruby Gems that
|
||||||
|
* don't produce accessible markup (simple-forms & simple-navigation)
|
||||||
|
*/
|
||||||
|
function applyRailsA11yPatches() {
|
||||||
|
/**
|
||||||
|
* Mark current navigation item with aria-current
|
||||||
|
*/
|
||||||
|
const activeNavLink = document.querySelector(
|
||||||
|
'.simple-navigation-active-leaf a.selected',
|
||||||
|
);
|
||||||
|
activeNavLink?.setAttribute('aria-current', 'page');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides the asterisk added to labels of required form fields
|
||||||
|
* from assistive tech. (Those fields already have the `required` attribute)
|
||||||
|
*/
|
||||||
|
document
|
||||||
|
.querySelectorAll<HTMLElement>('.simple_form label.required abbr')
|
||||||
|
.forEach((element) => {
|
||||||
|
element.setAttribute('aria-hidden', 'true');
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate form field hints with their inputs via aria-describedby
|
||||||
|
*/
|
||||||
|
document
|
||||||
|
.querySelectorAll<HTMLDivElement>('.simple_form .field_with_hint')
|
||||||
|
.forEach((field) => {
|
||||||
|
const inputs = field.querySelectorAll<
|
||||||
|
HTMLInputElement | HTMLTextAreaElement
|
||||||
|
>("input[type='text'], input[type='checkbox'], textarea");
|
||||||
|
|
||||||
|
const hint = field.querySelector<HTMLDivElement>('.hint');
|
||||||
|
|
||||||
|
// Bail out if there are more than one input as
|
||||||
|
// the association can't be safely made.
|
||||||
|
if (inputs.length !== 1 || !inputs[0] || !hint) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const input = inputs[0];
|
||||||
|
const inputId = input.getAttribute('id');
|
||||||
|
const hintId = `${inputId}_hint`;
|
||||||
|
|
||||||
|
input.setAttribute('aria-describedby', hintId);
|
||||||
|
hint.setAttribute('id', hintId);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add fieldset-like group labels ("legends") to the date-of-birth selector
|
||||||
|
* and groups of radio buttons
|
||||||
|
*/
|
||||||
|
const groups = document.querySelectorAll<HTMLDivElement>(
|
||||||
|
'.simple_form .date_of_birth, .simple_form .input.with_label.radio_buttons',
|
||||||
|
);
|
||||||
|
groups.forEach((groupWrapper) => {
|
||||||
|
// This is the element serving as the label of the group.
|
||||||
|
const groupLabel = groupWrapper.querySelector<HTMLLabelElement>('label');
|
||||||
|
const labelWithId =
|
||||||
|
groupWrapper.querySelector<HTMLLabelElement>('label[for]');
|
||||||
|
const groupHint = groupWrapper.querySelector<HTMLDivElement>('.hint');
|
||||||
|
|
||||||
|
// We need a unique ID to generate the aria associations. If `groupLabel`
|
||||||
|
// doesn't have one, we just take the first label with a `for` attribute
|
||||||
|
// that we can find, which is fine because we'll modify it before use.
|
||||||
|
const inputId =
|
||||||
|
groupLabel?.getAttribute('for') ?? labelWithId?.getAttribute('for');
|
||||||
|
const labelId = `${inputId}_label`;
|
||||||
|
const hintId = `${inputId}_hint`;
|
||||||
|
|
||||||
|
groupLabel?.setAttribute('id', labelId);
|
||||||
|
groupHint?.setAttribute('id', hintId);
|
||||||
|
|
||||||
|
groupWrapper.setAttribute('role', 'group');
|
||||||
|
groupWrapper.setAttribute('aria-labelledby', labelId);
|
||||||
|
if (groupHint) {
|
||||||
|
groupWrapper.setAttribute('aria-describedby', hintId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
ready(loaded).catch((error: unknown) => {
|
ready(loaded).catch((error: unknown) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user