diff --git a/src/core/components/user-avatar/core-user-avatar.html b/src/core/components/user-avatar/core-user-avatar.html
index 1e90d6bf3..67eae965c 100644
--- a/src/core/components/user-avatar/core-user-avatar.html
+++ b/src/core/components/user-avatar/core-user-avatar.html
@@ -1,10 +1,14 @@
-
+
-
+
+
+
+
+
diff --git a/src/core/components/user-avatar/user-avatar.scss b/src/core/components/user-avatar/user-avatar.scss
index 38eea5500..f2028ece8 100644
--- a/src/core/components/user-avatar/user-avatar.scss
+++ b/src/core/components/user-avatar/user-avatar.scss
@@ -5,9 +5,6 @@
width: var(--core-avatar-size);
height: var(--core-avatar-size);
- .clickable {
- cursor: pointer;
- }
img {
border-radius: 50%;
width: var(--core-avatar-size);
diff --git a/src/core/directives/aria-button.ts b/src/core/directives/aria-button.ts
index 3d0d29593..ec05e4cab 100644
--- a/src/core/directives/aria-button.ts
+++ b/src/core/directives/aria-button.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Directive, ElementRef, OnInit, Output, EventEmitter } from '@angular/core';
+import { Directive, ElementRef, OnInit, Output, EventEmitter, OnChanges, SimpleChanges, Input } from '@angular/core';
import { CoreDom } from '@singletons/dom';
/**
@@ -21,10 +21,11 @@ import { CoreDom } from '@singletons/dom';
@Directive({
selector: '[ariaButtonClick]',
})
-export class CoreAriaButtonClickDirective implements OnInit {
+export class CoreAriaButtonClickDirective implements OnInit, OnChanges {
protected element: HTMLElement;
+ @Input() disabled = false;
@Output() ariaButtonClick = new EventEmitter();
constructor(
@@ -34,10 +35,27 @@ export class CoreAriaButtonClickDirective implements OnInit {
}
/**
- * Initialize actions.
+ * @inheritdoc
*/
ngOnInit(): void {
- CoreDom.onActivate(this.element, (event) => this.ariaButtonClick.emit(event));
+ CoreDom.initializeClickableElementA11y(this.element, (event) => this.ariaButtonClick.emit(event));
+ }
+
+ /**
+ * @inheritdoc
+ */
+ ngOnChanges(changes: SimpleChanges): void {
+ if (!changes.disabled) {
+ return;
+ }
+
+ if (this.element.getAttribute('tabindex') === '0' && this.disabled) {
+ this.element.setAttribute('tabindex', '-1');
+ }
+
+ if (this.element.getAttribute('tabindex') === '-1' && !this.disabled) {
+ this.element.setAttribute('tabindex', '0');
+ }
}
}
diff --git a/src/core/directives/format-text.ts b/src/core/directives/format-text.ts
index 7fdd4e165..05e911330 100644
--- a/src/core/directives/format-text.ts
+++ b/src/core/directives/format-text.ts
@@ -610,12 +610,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo
return;
}
- if (element.tagName !== 'BUTTON' && element.tagName !== 'A') {
- element.setAttribute('tabindex', '0');
- element.setAttribute('role', 'button');
- }
-
- CoreDom.onActivate(element, async (event) => {
+ CoreDom.initializeClickableElementA11y(element, async (event) => {
event.preventDefault();
event.stopPropagation();
diff --git a/src/core/directives/link.ts b/src/core/directives/link.ts
index 86d2c18ef..7511193d1 100644
--- a/src/core/directives/link.ts
+++ b/src/core/directives/link.ts
@@ -57,12 +57,7 @@ export class CoreLinkDirective implements OnInit {
* Function executed when the component is initialized.
*/
ngOnInit(): void {
- if (this.element.tagName != 'BUTTON' && this.element.tagName != 'A') {
- this.element.setAttribute('tabindex', '0');
- this.element.setAttribute('role', 'button');
- }
-
- CoreDom.onActivate(this.element, (event) => this.performAction(event));
+ CoreDom.initializeClickableElementA11y(this.element, (event) => this.performAction(event));
}
/**
diff --git a/src/core/features/mainmenu/components/user-menu-button/user-menu-button.html b/src/core/features/mainmenu/components/user-menu-button/user-menu-button.html
index 1282c55ab..5e8829b0b 100644
--- a/src/core/features/mainmenu/components/user-menu-button/user-menu-button.html
+++ b/src/core/features/mainmenu/components/user-menu-button/user-menu-button.html
@@ -1,4 +1,4 @@
diff --git a/src/core/singletons/dom.ts b/src/core/singletons/dom.ts
index 43e20abbe..6e6b3d8d8 100644
--- a/src/core/singletons/dom.ts
+++ b/src/core/singletons/dom.ts
@@ -514,8 +514,26 @@ export class CoreDom {
*
* @param element Element to listen to events.
* @param callback Callback to call when clicked or the key is pressed.
+ * @deprecated since 4.1.1: Use initializeClickableElementA11y instead.
*/
- static onActivate(element: HTMLElement, callback: (event: MouseEvent | KeyboardEvent) => void): void {
+ static onActivate(
+ element: HTMLElement & {disabled?: boolean},
+ callback: (event: MouseEvent | KeyboardEvent) => void,
+ ): void {
+ this.initializeClickableElementA11y(element, callback);
+ }
+
+ /**
+ * Initializes a clickable element a11y calling the click action when pressed enter or space
+ * and adding tabindex and role if needed.
+ *
+ * @param element Element to listen to events.
+ * @param callback Callback to call when clicked or the key is pressed.
+ */
+ static initializeClickableElementA11y(
+ element: HTMLElement & {disabled?: boolean},
+ callback: (event: MouseEvent | KeyboardEvent) => void,
+ ): void {
element.addEventListener('click', (event) => callback(event));
element.addEventListener('keydown', (event) => {
@@ -526,10 +544,27 @@ export class CoreDom {
});
element.addEventListener('keyup', (event) => {
- if ((event.key == ' ' || event.key == 'Enter')) {
+ if (event.key === ' ' || event.key === 'Enter') {
+ event.preventDefault();
+ event.stopPropagation();
+
callback(event);
}
});
+
+ if (element.tagName !== 'BUTTON' && element.tagName !== 'A') {
+ // Set tabindex if not previously set.
+ if (element.getAttribute('tabindex') === null) {
+ element.setAttribute('tabindex', element.disabled ? '-1' : '0');
+ }
+
+ // Set role if not previously set.
+ if (!element.getAttribute('role')) {
+ element.setAttribute('role', 'button');
+ }
+
+ element.classList.add('clickable');
+ }
}
}