From 391ec487a97dd88d357bdbfe1c884cfbcf5e1b55 Mon Sep 17 00:00:00 2001 From: Phil Thompson <=> Date: Wed, 27 Nov 2024 21:09:12 +0000 Subject: [PATCH 1/2] feat: Add semantics to .input-button Add the semantic role of 'button' to the .inpout-button whenever it is created so a screen-reader user is told it is a button Add the tabindex attribute and value of '0' so a keyboard user can tab to the button and https://github.com/OvidijusParsiunas/deep-chat/issues/286 --- component/src/views/chat/input/buttons/camera/cameraButton.ts | 2 ++ component/src/views/chat/input/buttons/inputButton.css | 3 ++- .../views/chat/input/buttons/microphone/microphoneButton.ts | 2 ++ component/src/views/chat/input/buttons/submit/submitButton.ts | 2 ++ .../views/chat/input/buttons/uploadFile/uploadFileButton.ts | 2 ++ 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/component/src/views/chat/input/buttons/camera/cameraButton.ts b/component/src/views/chat/input/buttons/camera/cameraButton.ts index bbbb923aa..4ccc4e220 100644 --- a/component/src/views/chat/input/buttons/camera/cameraButton.ts +++ b/component/src/views/chat/input/buttons/camera/cameraButton.ts @@ -37,6 +37,8 @@ export class CameraButton extends InputButton { private static createButtonElement() { const buttonElement = document.createElement('div'); buttonElement.classList.add('input-button'); + buttonElement.role = 'button'; + buttonElement.setAttribute('tabindex', '0'); return buttonElement; } diff --git a/component/src/views/chat/input/buttons/inputButton.css b/component/src/views/chat/input/buttons/inputButton.css index 19644f784..ad2b770e3 100644 --- a/component/src/views/chat/input/buttons/inputButton.css +++ b/component/src/views/chat/input/buttons/inputButton.css @@ -15,7 +15,8 @@ height: 1.65em; } -.input-button:hover { +.input-button:hover, +.input-button:focus-visible { background-color: #9c9c9c2e; } diff --git a/component/src/views/chat/input/buttons/microphone/microphoneButton.ts b/component/src/views/chat/input/buttons/microphone/microphoneButton.ts index af320b564..aee95663a 100644 --- a/component/src/views/chat/input/buttons/microphone/microphoneButton.ts +++ b/component/src/views/chat/input/buttons/microphone/microphoneButton.ts @@ -43,6 +43,8 @@ export class MicrophoneButton extends InputButton { const buttonElement = document.createElement('div'); buttonElement.id = 'microphone-button'; buttonElement.classList.add('input-button'); + buttonElement.role = 'button'; + buttonElement.setAttribute('tabindex', '0'); return buttonElement; } diff --git a/component/src/views/chat/input/buttons/submit/submitButton.ts b/component/src/views/chat/input/buttons/submit/submitButton.ts index d9647d2bd..d8426df02 100644 --- a/component/src/views/chat/input/buttons/submit/submitButton.ts +++ b/component/src/views/chat/input/buttons/submit/submitButton.ts @@ -95,6 +95,8 @@ export class SubmitButton extends InputButton { private static createButtonContainerElement() { const buttonElement = document.createElement('div'); buttonElement.classList.add('input-button'); + buttonElement.role = 'button'; + buttonElement.setAttribute('tabindex', '0'); return buttonElement; } diff --git a/component/src/views/chat/input/buttons/uploadFile/uploadFileButton.ts b/component/src/views/chat/input/buttons/uploadFile/uploadFileButton.ts index 647b00a3f..0231ee622 100644 --- a/component/src/views/chat/input/buttons/uploadFile/uploadFileButton.ts +++ b/component/src/views/chat/input/buttons/uploadFile/uploadFileButton.ts @@ -61,6 +61,8 @@ export class UploadFileButton extends InputButton { private static createButtonElement() { const buttonElement = document.createElement('div'); buttonElement.classList.add('input-button', 'upload-file-button'); + buttonElement.role = 'button'; + buttonElement.setAttribute('tabindex', '0'); return buttonElement; } From d2af40c467638174793578286aa38dd058eaa6d9 Mon Sep 17 00:00:00 2001 From: Phil Thompson <=> Date: Thu, 28 Nov 2024 09:52:09 +0000 Subject: [PATCH 2/2] Add aria-disabled and aria-busy props to disnbaled and busy buttons When the submit button has the class 'disabled-button' apply the attribute `aria-disabled="true"`. When the submit button has the class 'loading-button' apply the attribute `aria-busy="true"`. These attributes and their values should inform the screen-reader users that the button is not interactive and loading respectively. When the button is not disabled, the `aria-disabled` is removed and same for when the button is not loading, it should not have `aria-busy`. --- .../src/views/chat/input/buttons/submit/submitButton.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/component/src/views/chat/input/buttons/submit/submitButton.ts b/component/src/views/chat/input/buttons/submit/submitButton.ts index d8426df02..216fcbc1f 100644 --- a/component/src/views/chat/input/buttons/submit/submitButton.ts +++ b/component/src/views/chat/input/buttons/submit/submitButton.ts @@ -221,6 +221,8 @@ export class SubmitButton extends InputButton { private changeToStopIcon() { if (this._serviceIO.websocket) return; // stop not used for streaming messages in websocket this.elementRef.classList.remove(SubmitButton.LOADING_CLASS, SubmitButton.DISABLED_CLASS, SubmitButton.SUBMIT_CLASS); + this.elementRef.removeAttribute('aria-busy'); + this.elementRef.removeAttribute('aria-disabled'); this.elementRef.replaceChildren(this._innerElements.stop); this.reapplyStateStyle('stop', ['loading', 'submit']); this.elementRef.onclick = this.stopStream.bind(this); @@ -231,7 +233,9 @@ export class SubmitButton extends InputButton { if (this._serviceIO.websocket) return; if (!this._isSVGLoadingIconOverriden) this.elementRef.replaceChildren(this._innerElements.loading); this.elementRef.classList.remove(SubmitButton.SUBMIT_CLASS, SubmitButton.DISABLED_CLASS); + this.elementRef.removeAttribute('aria-disabled'); this.elementRef.classList.add(SubmitButton.LOADING_CLASS); + this.elementRef.setAttribute('aria-busy', 'true'); this.reapplyStateStyle('loading', ['submit']); this.elementRef.onclick = () => {}; this.status.requestInProgress = true; @@ -242,6 +246,8 @@ export class SubmitButton extends InputButton { public changeToSubmitIcon() { if (this.elementRef.classList.contains(SubmitButton.SUBMIT_CLASS)) return; this.elementRef.classList.remove(SubmitButton.LOADING_CLASS, SubmitButton.DISABLED_CLASS); + this.elementRef.removeAttribute('aria-busy'); + this.elementRef.removeAttribute('aria-disabled'); this.elementRef.classList.add(SubmitButton.SUBMIT_CLASS); this.elementRef.replaceChildren(this._innerElements.submit); SubmitButtonStateStyle.resetSubmit(this, this.status.loadingActive); @@ -259,7 +265,9 @@ export class SubmitButton extends InputButton { this.changeToSubmitIcon(); } else if (!this.elementRef.classList.contains(SubmitButton.DISABLED_CLASS)) { this.elementRef.classList.remove(SubmitButton.LOADING_CLASS, SubmitButton.SUBMIT_CLASS); + this.elementRef.removeAttribute('aria-busy'); this.elementRef.classList.add(SubmitButton.DISABLED_CLASS); + this.elementRef.setAttribute('aria-disabled', 'true'); this.elementRef.replaceChildren(this._innerElements.disabled); this.reapplyStateStyle('disabled', ['submit']); this.elementRef.onclick = () => {};