MOBILE-4565 a11y: Fix ion-fab-button focus

main
Pau Ferrer Ocaña 2024-04-23 12:46:32 +02:00
parent 23fccb22e5
commit a67cf4de7f
3 changed files with 18 additions and 10 deletions

View File

@ -44,7 +44,7 @@ export class CoreLinkDirective implements OnInit {
@Input() autoLogin: boolean | string = true; // Whether to try to use auto-login. Values yes/no/check are deprecated. @Input() autoLogin: boolean | string = true; // Whether to try to use auto-login. Values yes/no/check are deprecated.
@Input() showBrowserWarning = true; // Whether to show a warning before opening browser. Defaults to true. @Input() showBrowserWarning = true; // Whether to show a warning before opening browser. Defaults to true.
protected element: HTMLElement; protected element: HTMLElement | HTMLIonFabButtonElement | HTMLIonButtonElement | HTMLIonItemElement;
constructor( constructor(
element: ElementRef, element: ElementRef,
@ -54,10 +54,18 @@ export class CoreLinkDirective implements OnInit {
} }
/** /**
* Function executed when the component is initialized. * @inheritdoc
*/ */
ngOnInit(): void { async ngOnInit(): Promise<void> {
CoreDom.initializeClickableElementA11y(this.element, (event) => this.performAction(event)); let hasNativeButton = false;
if ('componentOnReady' in this.element) {
await this.element.componentOnReady();
// Native buttons may be already accessible and does not neet to set TabIndex and role.
hasNativeButton = !!this.element.shadowRoot?.querySelector('.button-native');
}
CoreDom.initializeClickableElementA11y(this.element, (event) => this.performAction(event), !hasNativeButton);
} }
/** /**
@ -79,7 +87,7 @@ export class CoreLinkDirective implements OnInit {
href = href || this.element.getAttribute('href') || this.element.getAttribute('xlink:href'); href = href || this.element.getAttribute('href') || this.element.getAttribute('xlink:href');
if (!href || CoreUrlUtils.getUrlScheme(href) == 'javascript') { if (!href || CoreUrlUtils.getUrlScheme(href) === 'javascript') {
return; return;
} }

View File

@ -54,12 +54,10 @@
<ion-fab-button size="small" *ngIf="communicationRoomUrl" [href]="communicationRoomUrl" core-link capture="false" <ion-fab-button size="small" *ngIf="communicationRoomUrl" [href]="communicationRoomUrl" core-link capture="false"
[attr.aria-label]="'core.course.communicationroomlink' | translate"> [attr.aria-label]="'core.course.communicationroomlink' | translate">
<ion-icon name="far-comments" aria-hidden="true" /> <ion-icon name="far-comments" aria-hidden="true" />
<span class="sr-only">{{'core.course.communicationroomlink' | translate }}</span>
</ion-fab-button> </ion-fab-button>
<ion-fab-button *ngIf="displayCourseIndex" (click)="openCourseIndex()" [userTour]="courseIndexTour" <ion-fab-button *ngIf="displayCourseIndex" (click)="openCourseIndex()" [userTour]="courseIndexTour"
[attr.aria-label]="'core.course.courseindex' | translate" color="secondary"> [attr.aria-label]="'core.course.courseindex' | translate" color="secondary">
<ion-icon name="fas-list-ul" aria-hidden="true" /> <ion-icon name="fas-list-ul" aria-hidden="true" />
<span class="sr-only">{{'core.course.courseindex' | translate }}</span>
</ion-fab-button> </ion-fab-button>
</ion-fab> </ion-fab>

View File

@ -537,10 +537,12 @@ export class CoreDom {
* *
* @param element Element to listen to events. * @param element Element to listen to events.
* @param callback Callback to call when clicked or the key is pressed. * @param callback Callback to call when clicked or the key is pressed.
* @param setTabIndex Whether to set tabindex and role.
*/ */
static initializeClickableElementA11y( static initializeClickableElementA11y(
element: HTMLElement & {disabled?: boolean}, element: HTMLElement & {disabled?: boolean},
callback: (event: MouseEvent | KeyboardEvent) => void, callback: (event: MouseEvent | KeyboardEvent) => void,
setTabIndex = true,
): void { ): void {
const enabled = () => !CoreUtils.isTrueOrOne(element.dataset.disabledA11yClicks ?? 'false'); const enabled = () => !CoreUtils.isTrueOrOne(element.dataset.disabledA11yClicks ?? 'false');
@ -563,14 +565,14 @@ export class CoreDom {
} }
if (event.key === ' ' || event.key === 'Enter') { if (event.key === ' ' || event.key === 'Enter') {
callback(event);
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
callback(event);
} }
}); });
if (element.tagName !== 'BUTTON' && element.tagName !== 'A') { if (setTabIndex && element.tagName !== 'BUTTON' && element.tagName !== 'A') {
// Set tabindex if not previously set. // Set tabindex if not previously set.
if (element.getAttribute('tabindex') === null) { if (element.getAttribute('tabindex') === null) {
element.setAttribute('tabindex', element.disabled ? '-1' : '0'); element.setAttribute('tabindex', element.disabled ? '-1' : '0');