From e9d366aa9828fea795e283b685277ca1d1cde9ea Mon Sep 17 00:00:00 2001 From: ralf Date: Fri, 26 Apr 2024 12:04:37 +0200 Subject: [PATCH] WIP accessibility of widgets: - fixed fallback-order for aria-attributes (done now in connected callback and not updated, which was not reliable in the order called) - aria-label set by (in order of priority): ariaLabel, label, placeholder, statustext - aria-description set by (----- " -----): ariaDescription, helpText, statustext (if not already used for -label) - following widget work now (incl. focus by click on label): et2-textbox, et2-date*, et2-url*, et2-select* --- api/js/etemplate/Et2Button/ButtonMixin.ts | 10 +++++++- .../Et2InputWidget/Et2InputWidget.ts | 25 ++++++++----------- api/js/etemplate/Et2Select/Et2Select.ts | 2 ++ 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/api/js/etemplate/Et2Button/ButtonMixin.ts b/api/js/etemplate/Et2Button/ButtonMixin.ts index db94bd1cb7..4d9a56983e 100644 --- a/api/js/etemplate/Et2Button/ButtonMixin.ts +++ b/api/js/etemplate/Et2Button/ButtonMixin.ts @@ -28,7 +28,7 @@ export const ButtonMixin = (superclass : T) => class exte cancel: /cancel(&|\]|$)/, delete: /delete(&|\]|$)/, discard: /discard(&|\]|$)/, - edit: /edit(&|\[\]|$)/, + edit: /edit(&|\[|\]|$)/, next: /(next|continue)(&|\]|$)/, finish: /finish(&|\]|$)/, back: /(back|previous)(&|\]|$)/, @@ -426,4 +426,12 @@ export const ButtonMixin = (superclass : T) => class exte // array. return null; } + + /** + * Reimplemented to pass aria-attributes to button + */ + getInputNode() + { + return this.shadowRoot.querySelector('button'); + } } \ No newline at end of file diff --git a/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts b/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts index 9a082d60f1..23356a31b9 100644 --- a/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts +++ b/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts @@ -216,6 +216,17 @@ const Et2InputWidgetMixin = >(superclass : T) }); this.addEventListener("focus", this.et2HandleFocus); this.addEventListener("blur", this.et2HandleBlur); + + // set aria-label and -description fallbacks (done here and not in updated to ensure reliable fallback order) + if (!this.ariaLabel) this.ariaLabel = this.label || this.placeholder || this.statustext; + if (!this.ariaDescription) this.ariaDescription = this.helpText || (this.statustext !== this.ariaLabel ? this.statustext : ''); + // pass them on to input-node, if we have one / this.getInputNode() returns one + const input = this.getInputNode(); + if (input) + { + input.ariaLabel = this.ariaLabel; + input.ariaDescription = this.ariaDescription; + } } disconnectedCallback() @@ -253,20 +264,6 @@ const Et2InputWidgetMixin = >(superclass : T) // Base off this.value, not this.getValue(), to ignore readonly this.classList.toggle("hasValue", !(this.value == null || this.value == "")); } - - if (changedProperties.has('ariaLabel') || changedProperties.has('ariaDescription') || - changedProperties.has("statustext") || changedProperties.has('helpText')) - { - const input = this.getInputNode(); - if (input && (changedProperties.has('ariaLabel') || changedProperties.has("statustext"))) - { - input.ariaLabel = this.ariaLabel || this.statustext; - } - if (input && (changedProperties.has('ariaDescription') || changedProperties.has('helpText'))) - { - input.ariaDescription = this.ariaDescription || this.helpText; - } - } } /** diff --git a/api/js/etemplate/Et2Select/Et2Select.ts b/api/js/etemplate/Et2Select/Et2Select.ts index 7968dab2b5..40771c8be3 100644 --- a/api/js/etemplate/Et2Select/Et2Select.ts +++ b/api/js/etemplate/Et2Select/Et2Select.ts @@ -1046,6 +1046,8 @@ export class Et2Select extends Et2WithSearchMixin(Et2WidgetWithSelect) exportparts="form-control-label, prefix, tags, display-input, expand-icon, combobox, combobox:base, listbox, option" label=${this.label} placeholder=${this.placeholder || (this.multiple && this.emptyLabel ? this.emptyLabel : "")} + aria-label=${this.ariaLabel} + aria-description=${this.ariaDesciption} ?multiple=${this.multiple} ?disabled=${this.disabled || this.readonly} ?clearable=${this.clearable}