MOBILE-3744 splitview: Change selected item to aria-current attribute

main
Pau Ferrer Ocaña 2021-05-03 10:08:20 +02:00
parent 9f42b80b06
commit d8fa2142ea
35 changed files with 56 additions and 47 deletions

View File

@ -17,8 +17,8 @@
</core-empty-box>
<ion-list *ngIf="!badges.empty" class="ion-no-margin">
<ion-item class="ion-text-wrap" *ngFor="let badge of badges.items" [title]="badge.name"
(click)="badges.select(badge)" [class.core-selected-item]="badges.isSelected(badge)">
<ion-item button class="ion-text-wrap" *ngFor="let badge of badges.items" [title]="badge.name"
(click)="badges.select(badge)" [attr.aria-current]="badges.getItemAriaCurrent(badge)">
<ion-avatar slot="start">
<img [src]="badge.badgeurl" [alt]="badge.name" core-external-content>
</ion-avatar>

View File

@ -43,7 +43,8 @@
<ion-label>{{ event.timestart * 1000 | coreFormatDate: "strftimedayshort" }}</ion-label>
</ion-item-divider>
<ion-item class="addon-calendar-event ion-text-wrap" [title]="event.name" (click)="gotoEvent(event.id)"
[class.core-selected-item]="event.id == eventId" [ngClass]="['addon-calendar-eventtype-'+event.eventtype]">
[attr.aria-current]="event.id == eventId ? 'page' : 'false'"
[ngClass]="['addon-calendar-eventtype-'+event.eventtype]">
<img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" slot="start" class="core-module-icon" alt=""
role="presentation">
<ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start"

View File

@ -15,7 +15,7 @@
<ion-list>
<ion-item class="ion-text-wrap" *ngFor="let competency of competencies.items"
[title]="competency.competency.shortname" (click)="competencies.select(competency)"
[class.core-selected-item]="competencies.isSelected(competency)">
[attr.aria-current]="competencies.getItemAriaCurrent(competency)">
<ion-label>
<h2>{{ competency.competency.shortname }} <em>{{competency.competency.idnumber}}</em></h2>
</ion-label>

View File

@ -17,7 +17,7 @@
</core-empty-box>
<ion-list *ngIf="!plans.empty" class="ion-no-margin">
<ion-item class="ion-text-wrap" *ngFor="let plan of plans.items" [title]="plan.name" (click)="plans.select(plan)"
[class.core-selected-item]="plans.isSelected(plan)">
[attr.aria-current]="plans.getItemAriaCurrent(plan)">
<ion-label>
<h2>{{ plan.name }}</h2>
<p *ngIf="plan.duedate > 0">

View File

@ -39,7 +39,7 @@
<ion-item class="ion-text-wrap addon-messages-conversation-item"
*ngIf="contact.profileimageurl || contact.profileimageurlsmall"
[title]="contact.fullname" (click)="gotoDiscussion(contact.id)" detail
[class.core-selected-item]="contact.id == discussionUserId">
[attr.aria-current]="contact.id == discussionUserId ? 'page' : 'false'">
<core-user-avatar [user]="contact" slot="start" [checkOnline]="contact.showonlinestatus"></core-user-avatar>
<ion-label><h2>{{ contact.fullname }}</h2></ion-label>
</ion-item>

View File

@ -28,7 +28,7 @@
<ion-list class="ion-no-margin">
<ion-item class="ion-text-wrap addon-messages-conversation-item"
*ngFor="let contact of confirmedContacts" [title]="contact.fullname" detail
(click)="selectUser(contact.id)" [class.core-selected-item]="contact.id == selectedUserId">
(click)="selectUser(contact.id)" [attr.aria-current]="contact.id == selectedUserId ? 'page' : 'false'">
<core-user-avatar slot="start" [user]="contact"
[checkOnline]="contact.showonlinestatus" [linkProfile]="false">
</core-user-avatar>
@ -65,7 +65,7 @@
<ion-list class="ion-no-margin">
<ion-item class="ion-text-wrap addon-messages-conversation-item" *ngFor="let request of requests"
[title]="request.fullname" (click)="selectUser(request.id)"
[class.core-selected-item]="request.id == selectedUserId" detail>
[attr.aria-current]="request.id == selectedUserId ? 'page' : 'false'" detail>
<core-user-avatar slot="start" [user]="request" [linkProfile]="false"></core-user-avatar>
<ion-label>
<core-format-text [text]="request.fullname" contextLevel="system" [contextInstanceId]="0">

View File

@ -40,7 +40,7 @@
</ion-item-divider>
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let result of search.results" [title]="result.fullname"
(click)="gotoDiscussion(result.userid, result.messageid)"
[class.core-selected-item]="result.userid == discussionUserId">
[attr.aria-current]="result.userid == discussionUserId ? 'page' : 'false'">
<core-user-avatar [user]="result" slot="start" [checkOnline]="result.showonlinestatus"></core-user-avatar>
<ion-label>
<h2>{{ result.fullname }}</h2>
@ -52,7 +52,7 @@
<ng-container *ngIf="!search.showResults">
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let discussion of discussions"
[title]="discussion.fullname" (click)="gotoDiscussion(discussion.message!.user)"
[class.core-selected-item]="discussion.message!.user == discussionUserId">
[attr.aria-current]="discussion.message!.user == discussionUserId ? 'page' : 'false'">
<core-user-avatar [user]="discussion" slot="start" checkOnline="false"></core-user-avatar>
<ion-label>
<h2>{{ discussion.fullname }}</h2>

View File

@ -108,8 +108,8 @@
<ng-template #conversationsTemplate let-conversations="conversations">
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let conversation of conversations" [title]="conversation.name"
(click)="gotoConversation(conversation.id, conversation.userid)"
[class.core-selected-item]="(conversation.id && conversation.id == selectedConversationId) ||
(conversation.userid && conversation.userid == selectedUserId)"
[attr.aria-current]="((conversation.id && conversation.id == selectedConversationId) ||
(conversation.userid && conversation.userid == selectedUserId)) ? 'page': 'false'"
id="addon-message-conversation-{{ conversation.id ? conversation.id : 'user-' + conversation.userid }}">
<!-- Group conversation image. -->
<ion-avatar slot="start" *ngIf="conversation.type == typeGroup">

View File

@ -43,7 +43,7 @@
<!-- List of results -->
<ion-item class="addon-message-discussion ion-text-wrap" *ngFor="let result of item.results" [title]="result.fullname"
(click)="openConversation(result)" [class.core-selected-item]="result == selectedResult" detail>
(click)="openConversation(result)" [attr.aria-current]="result == selectedResult ? 'page' : 'false'" detail>
<core-user-avatar slot="start" [user]="result" [checkOnline]="true" [linkProfile]="false"></core-user-avatar>
<ion-label>
<h2>

View File

@ -40,7 +40,7 @@
<!-- List of submissions. -->
<ng-container *ngFor="let submission of submissions.items">
<ion-item class="ion-text-wrap" (click)="submissions.select(submission)"
[class.core-selected-item]="submissions.isSelected(submission)">
[attr.aria-current]="submissions.getItemAriaCurrent(submission)">
<core-user-avatar [user]="submission" [linkProfile]="false" slot="start"></core-user-avatar>
<ion-label>
<h2 *ngIf="submission.userfullname">{{submission.userfullname}}</h2>

View File

@ -12,7 +12,7 @@
<nav>
<ion-list>
<ion-item class="ion-text-wrap" *ngFor="let chapter of chapters" (click)="loadChapter(chapter.id)"
[class.core-selected-item]="selected == chapter.id"
[attr.aria-current]="selected == chapter.id ? 'page' : 'false'"
[class.item-dimmed]="chapter.hidden">
<ion-label>
<p [class.ion-padding-left]="addPadding && chapter.level == 1 ? true : null">

View File

@ -31,7 +31,7 @@
</ion-item>
<ion-card *ngFor="let session of sessions.items" (click)="sessions.select(session)"
[class.core-selected-item]="sessions.isSelected(session)"
[attr.aria-current]="sessions.getItemAriaCurrent(session)"
[class.addon-mod-chat-session-show-more]="session.sessionusers.length < session.allsessionusers.length">
<ion-item class="ion-text-wrap">

View File

@ -33,7 +33,7 @@
</ion-label>
</ion-item-divider>
<ion-item *ngFor="let attempt of responses.responses.attempts" class="ion-text-wrap" tappable detail="true"
(click)="responses.select(attempt)" [class.core-selected-item]="responses.isSelected(attempt)">
(click)="responses.select(attempt)" [attr.aria-current]="responses.getItemAriaCurrent(attempt)">
<core-user-avatar [user]="attempt" slot="start"></core-user-avatar>
<ion-label>
<h2>{{ attempt.fullname }}</h2>
@ -58,7 +58,7 @@
</ion-label>
</ion-item-divider>
<ion-item *ngFor="let attempt of responses.anonResponses.attempts" class="ion-text-wrap" tappable detail="true"
(click)="responses.select(attempt)" [class.core-selected-item]="responses.isSelected(attempt)">
(click)="responses.select(attempt)" [attr.aria-current]="responses.getItemAriaCurrent(attempt)">
<ion-label>
<h2>{{ 'addon.mod_feedback.response_nr' |translate }}: {{attempt.number}}</h2>
</ion-label>

View File

@ -80,7 +80,7 @@
<ion-item *ngFor="let discussion of discussions.items"
class="addon-mod-forum-discussion" detail="true"
[lines]="discussion.groupname && 'none'" [class.core-selected-item]="discussions.isSelected(discussion)"
[lines]="discussion.groupname && 'none'" [attr.aria-current]="discussions.getItemAriaCurrent(discussion)"
(click)="discussions.select(discussion)">
<ion-label>
<div class="addon-mod-forum-discussion-title">

View File

@ -11,9 +11,9 @@
<ion-content>
<ion-list id="addon-mod-forum-sort-selector" role="menu" aria-labelledby="addon-mod-forum-sort-order-button">
<ng-container *ngFor="let sortOrder of sortOrders">
<ion-item class="ion-text-wrap" detail="false" role="combobox" button aria-haspopup="dialog"
[attr.aria-current]="selected == sortOrder.value ? 'page' : 'false'"
[attr.aria-label]="sortOrder.label | translate" (click)="selectSortOrder(sortOrder)">
<ion-item class="ion-text-wrap" detail="false" role="combobox"
[attr.aria-current]="selected == sortOrder.value ? 'page' : 'false'" [attr.aria-label]="sortOrder.label | translate"
(click)="selectSortOrder(sortOrder)" button aria-haspopup="dialog">
<ion-label>
<h2>{{ sortOrder.label | translate }}</h2>
</ion-label>

View File

@ -67,7 +67,7 @@
<ion-label>{{ 'addon.mod_glossary.entriestobesynced' | translate }}</ion-label>
</ion-item-divider>
<ion-item *ngFor="let entry of entries.offlineEntries" (click)="entries.select(entry)" detail="false"
[class.core-selected-item]="entries.isSelected(entry)">
[attr.aria-current]="entries.getItemAriaCurrent(entry)">
<ion-label>
<core-format-text [text]="entry.concept" contextLevel="module" [contextInstanceId]="glossary!.coursemodule"
[courseId]="courseId">
@ -82,7 +82,8 @@
{{ getDivider!(entry) }}
</ion-item-divider>
<ion-item (click)="entries.select(entry)" [class.core-selected-item]="entries.isSelected(entry)" detail="false">
<ion-item button (click)="entries.select(entry)" [attr.aria-current]="entries.getItemAriaCurrent(entry)"
detail="false">
<ion-label>
<core-format-text [text]="entry.concept" contextLevel="module" [contextInstanceId]="glossary!.coursemodule"
[courseId]="courseId">

View File

@ -12,7 +12,7 @@
<nav>
<ion-list>
<ion-item *ngFor="let item of items" (click)="loadItem(item.href)"
[class.core-selected-item]="selected == item.href">
[attr.aria-current]="selected == item.href ? 'page' : 'false'">
<ion-label [class.core-bold]="!item.href">
<span class="ion-padding-left" *ngFor="let i of getNumberForPadding(item.level)"></span>{{item.title}}
</ion-label>

View File

@ -33,7 +33,7 @@
<div *ngIf="!pageInstance.loadingMenu">
<ng-container *ngFor="let page of pageInstance.lessonPages">
<ion-item class="ion-text-wrap" *ngIf="page.display && page.displayinmenublock" (click)="loadPage(page.id)"
[ngClass]='{"core-selected-item": !pageInstance.eolData && pageInstance.currentPage == page.id}'
[attr.aria-current]="!pageInstance.eolData && pageInstance.currentPage == page.id ? 'page' : 'false'"
button detail="true">
<ion-label>
<core-format-text [text]="page.title" contextLevel="module" [courseId]="pageInstance.courseId"

View File

@ -26,7 +26,7 @@
</ion-item>
<ion-item button class="ion-text-wrap {{question.stateClass}}" *ngFor="let question of navigation"
[ngClass]='{"core-selected-item": !summaryShown && currentPage == question.page}'
[attr.aria-current]="!summaryShown && currentPage == question.page ? 'page' : 'false'"
(click)="loadPage(question.page, question.slot)" detail="true">
<ion-label>

View File

@ -31,7 +31,7 @@
<ng-container *ngFor="let sco of toc">
<ion-item *ngIf="sco.isvisible" class="ion-text-wrap" [detail]="sco.prereq && sco.launch"
[ngClass]="'core-padding-' + sco.level + ' addon-mod_scorm-type-' + sco.scormtype"
[class.core-selected-item]="selected == sco.id" (click)="loadSco(sco)"
[attr.aria-current]="selected == sco.id ? 'page' : 'false'" (click)="loadSco(sco)"
[disabled]="!sco.prereq || !sco.launch ? true : null" tappable>
<ion-icon *ngIf="sco.icon" [name]="sco.icon.icon" [attr.aria-label]="sco.icon.description" slot="start">
</ion-icon>

View File

@ -21,7 +21,7 @@
<ion-label>{{ letter.label }}</ion-label>
</ion-item-divider>
<ion-item class="ion-text-wrap" *ngFor="let page of letter.pages" (click)="goToPage(page)"
[class.core-selected-item]="selectedTitle == page.title" tappable>
[attr.aria-current]="selectedTitle == page.title ? 'page' : 'false'" tappable>
<ion-icon name="fas-home" slot="start" *ngIf="page.firstpage" aria-hidden="true"></ion-icon>
<ion-label>
<core-format-text [text]="page.title" contextLevel="module" [contextInstanceId]="moduleId"

View File

@ -5,7 +5,7 @@
</ion-item-divider>
<ion-item class="ion-text-wrap" *ngFor="let subwiki of group.subwikis" (click)="openSubwiki(subwiki)"
[attr.disabled]="!subwiki.canedit && subwiki.id <= 0 ? true : null" tappable
[class.core-selected-item]="isSubwikiSelected(subwiki)" detail="false">
[attr.aria-current]="isSubwikiSelected(subwiki) ? 'page' : 'false'" detail="false">
<ion-label>{{ subwiki.name }}</ion-label>
<ion-icon *ngIf="isSubwikiSelected(subwiki)" name="fas-check" slot="end" aria-hidden="true"></ion-icon>
</ion-item>

View File

@ -14,7 +14,7 @@
<ion-content>
<ion-list>
<ng-container *ngFor="let phase of phases">
<ion-item-divider [class.core-selected-item]="workshopPhase == phase.code">
<ion-item-divider [attr.aria-current]="workshopPhase == phase.code ? 'page' : 'false'">
<ion-label>
<h2>{{ phase.title }}</h2>
<p class="ion-text-wrap" *ngIf="workshopPhase == phase.code">

View File

@ -121,6 +121,16 @@ export abstract class CorePageItemsListManager<Item> {
return this.selectedItem === item;
}
/**
* Return the current aria value.
*
* @param item Item.
* @return Will return the current value of the item if selected, false otherwise.
*/
getItemAriaCurrent(item: Item): string {
return this.isSelected(item) ? 'page' : 'false';
}
/**
* Select an item.
*

View File

@ -12,7 +12,7 @@
<ion-list id="core-course-section-selector">
<ng-container *ngFor="let section of sections">
<ion-item *ngIf="!section.hiddenbynumsections && section.id != stealthModulesSectionId" class="ion-text-wrap"
(click)="selectSection(section)" [class.core-selected-item]="selected?.id == section.id"
(click)="selectSection(section)" [attr.aria-current]="selected?.id == section.id ? 'page' : 'false'"
[class.item-dimmed]="section.visible === 0 || section.uservisible === false" detail="false"
[attr.aria-hidden]="section.uservisible === false" button>

View File

@ -45,7 +45,7 @@
<th
class="core-grades-table-gradeitem ion-text-start"
[class.column-itemname]="row.itemtype == 'category'"
[class.core-selected-item]="grades.isSelected(row)"
[attr.aria-current]="grades.getItemAriaCurrent(row)"
[attr.colspan]="row.colspan"
>
<ion-icon *ngIf="row.icon" name="{{row.icon}}" slot="start" [attr.aria-label]="row.iconAlt">

View File

@ -90,7 +90,7 @@
.odd {
td, th, th.core-selected-item {
td, th, th[aria-current="page"] {
background-color: var(--gray-lighter);
// @include darkmode() {
@ -102,7 +102,7 @@
.even {
td, th, th.core-selected-item {
td, th, th[aria-current="page"] {
background-color: var(--white);
// @include darkmode() {

View File

@ -22,7 +22,7 @@
<ion-item
*ngFor="let course of courses.items"
[title]="course.courseFullName"
[class.core-selected-item]="courses.isSelected(course)"
[attr.aria-current]="courses.getItemAriaCurrent(course)"
class="ion-text-wrap"
button
detail

View File

@ -10,7 +10,7 @@
<ion-content>
<core-split-view>
<ion-list>
<ion-item *ngFor="let section of sections.items" [class.core-selected-item]="sections.isSelected(section)" button
<ion-item *ngFor="let section of sections.items" [attr.aria-current]="sections.getItemAriaCurrent(section)" button
detail="true" (click)="sections.select(section)">
<ion-icon [name]="section.icon" slot="start" aria-hidden="true"></ion-icon>
<ion-label>{{ section.name | translate }}</ion-label>

View File

@ -29,7 +29,7 @@
<ion-item *ngFor="let handler of handlers.items" [ngClass]="['core-settings-handler', handler.class]"
[title]="handler.title | translate" detail="true" (click)="handlers.select(handler)" button
[class.core-selected-item]="handlers.isSelected(handler)">
[attr.aria-current]="handlers.getItemAriaCurrent(handler)">
<ion-icon [name]="handler.icon" slot="start" *ngIf="handler.icon" aria-hidden="true">
</ion-icon>
<ion-label>

View File

@ -18,7 +18,7 @@
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
</ion-refresher>
<core-loading [hideUntil]="loaded">
<ion-item *ngFor="let site of sites" [class.core-selected-item]="site.id == currentSiteId">
<ion-item *ngFor="let site of sites" [attr.aria-current]="site.id == currentSiteId ? 'page' : 'false'">
<ion-label class="ion-text-wrap">
<h2>
<core-format-text [text]="site.siteName" clean="true" [siteId]="site.id"></core-format-text>

View File

@ -30,7 +30,7 @@
<h2>{{ 'core.settings.sites' | translate }}</h2>
</ion-label>
</ion-item-divider>
<ion-item *ngFor="let site of sites" [class.core-selected-item]="site.id == currentSiteId" class="ion-text-wrap">
<ion-item *ngFor="let site of sites" [attr.aria-current]="site.id == currentSiteId ? 'page' : 'false'" class="ion-text-wrap">
<ion-label>
<h2>
<core-format-text [text]="site.siteName" clean="true" [siteId]="site.id"></core-format-text>

View File

@ -19,7 +19,7 @@
<ion-label class="ion-text-wrap">{{ 'core.tag.warningareasnotsupported' | translate }}</ion-label>
</ion-item>
<ion-item class="ion-text-wrap" *ngFor="let area of areas" [title]="area.nameKey | translate"
(click)="openArea(area)" [class.core-selected-item]="area!.id == selectedAreaId">
(click)="openArea(area)" [attr.aria-current]="area!.id == selectedAreaId ? 'page' : 'false'">
<ion-label>
<h2>{{ area!.nameKey | translate }}</h2>
</ion-label>

View File

@ -28,7 +28,7 @@
<ion-list *ngIf="!participants.empty">
<ion-item *ngFor="let participant of participants.items"
class="ion-text-wrap" [class.core-selected-item]="participants.isSelected(participant)"
class="ion-text-wrap" [attr.aria-current]="participants.getItemAriaCurrent(participant)"
[title]="participant.fullname" (click)="participants.select(participant)">
<core-user-avatar [user]="participant" [linkProfile]="false" [checkOnline]="true" slot="start">

View File

@ -215,14 +215,11 @@ ion-toolbar {
font-size: 14px;
}
.core-selected-item {
border-inline-start: var(--selected-item-border-width) solid var(--selected-item-color);
}
// Item styles
.item.core-selected-item {
[aria-current="page"] {
// TODO: Add safe area to border and RTL
--ion-safe-area-left: calc(-1 * var(--selected-item-border-width));
border-inline-start: var(--selected-item-border-width) solid var(--selected-item-color);
}
.item.item-file {