MOBILE-3996 navbar: Update style on navigation bar
parent
89d8750e82
commit
294c94b934
|
@ -31,9 +31,8 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
|
|
||||||
<core-navigation-bar *ngIf="displayNavBar" [items]="navigationItems" [showTitles]="displayTitlesInNavBar"
|
<core-navigation-bar *ngIf="displayNavBar" [items]="navigationItems" previousTranslate="addon.mod_book.navprevtitle"
|
||||||
previousTranslate="addon.mod_book.navprevtitle" nextTranslate="addon.mod_book.navnexttitle"
|
nextTranslate="addon.mod_book.navnexttitle" (action)="changeChapter($event.id)">
|
||||||
(action)="changeChapter($event.id)">
|
|
||||||
</core-navigation-bar>
|
</core-navigation-bar>
|
||||||
|
|
||||||
<core-swipe-slides [manager]="manager" [options]="slidesOpts">
|
<core-swipe-slides [manager]="manager" [options]="slidesOpts">
|
||||||
|
|
|
@ -62,7 +62,6 @@ export class AddonModBookContentsPage implements OnInit, OnDestroy {
|
||||||
warning = '';
|
warning = '';
|
||||||
displayNavBar = true;
|
displayNavBar = true;
|
||||||
navigationItems: CoreNavigationBarItem<AddonModBookTocChapter>[] = [];
|
navigationItems: CoreNavigationBarItem<AddonModBookTocChapter>[] = [];
|
||||||
displayTitlesInNavBar = false;
|
|
||||||
slidesOpts: CoreSwipeSlidesOptions = {
|
slidesOpts: CoreSwipeSlidesOptions = {
|
||||||
autoHeight: true,
|
autoHeight: true,
|
||||||
scrollOnChange: 'top',
|
scrollOnChange: 'top',
|
||||||
|
@ -135,7 +134,6 @@ export class AddonModBookContentsPage implements OnInit, OnDestroy {
|
||||||
const downloadResult = await this.downloadResourceIfNeeded(module, refresh);
|
const downloadResult = await this.downloadResourceIfNeeded(module, refresh);
|
||||||
|
|
||||||
this.displayNavBar = book.navstyle != AddonModBookNavStyle.TOC_ONLY;
|
this.displayNavBar = book.navstyle != AddonModBookNavStyle.TOC_ONLY;
|
||||||
this.displayTitlesInNavBar = book.navstyle == AddonModBookNavStyle.TEXT;
|
|
||||||
this.title = book.name;
|
this.title = book.name;
|
||||||
|
|
||||||
// Get contents. No need to refresh, it has been done in downloadResourceIfNeeded.
|
// Get contents. No need to refresh, it has been done in downloadResourceIfNeeded.
|
||||||
|
|
|
@ -1,27 +1,17 @@
|
||||||
<ion-row class="ion-justify-content-between ion-align-items-center ion-no-padding"
|
<ion-row class="ion-justify-content-between ion-align-items-center ion-no-padding ion-wrap" *ngIf="items.length > 1">
|
||||||
*ngIf="previousIndex >= 0 || nextIndex >= 0 || items.length > 1">
|
<ion-col class="ion-text-start ion-no-padding core-navigation-arrow" size="auto">
|
||||||
<ion-col class="ion-text-start ion-padding-end" [size]="showTitles ? 4 : 3">
|
<ion-button [disabled]="previousIndex < 0" fill="clear" color="dark" [attr.aria-label]="previousTitle"
|
||||||
<ion-button *ngIf="previousIndex >=0" class="core-navigation-bar-arrow" fill="clear" [attr.aria-label]="previousTitle"
|
|
||||||
(click)="navigate(previousIndex)">
|
(click)="navigate(previousIndex)">
|
||||||
<ion-icon name="fas-arrow-left" [slot]="showTitles ? 'start' : 'icon-only'" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-chevron-left" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
<core-format-text *ngIf="showTitles" [text]="previousTitle" [component]="component" [componentId]="componentId"
|
|
||||||
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" aria-hidden="true">
|
|
||||||
</core-format-text>
|
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col class="ion-text-center" [size]="showTitles ? 4 : 6">
|
<ion-col class="ion-text-center">
|
||||||
<ion-range min="0" [max]="items.length -1" debounce="500" snaps="true" (ionChange)="navigateOnRange($event.target)"
|
<core-progress-bar [progress]="progress" [text]="progressText" *ngIf="currentIndex >= 0">
|
||||||
[value]="currentIndex">
|
</core-progress-bar>
|
||||||
<p slot="end">{{currentIndex + 1}} / {{items.length}}</p>
|
|
||||||
</ion-range>
|
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col class="ion-text-end ion-padding-start" [size]="showTitles ? 4 : 3">
|
<ion-col class="ion-text-end ion-no-padding core-navigation-arrow" size="auto">
|
||||||
<ion-button fill="clear" *ngIf="nextIndex >= 0" class="core-navigation-bar-arrow" [attr.aria-label]="nextTitle"
|
<ion-button [disabled]="nextIndex < 0" fill="clear" color="dark" [attr.aria-label]="nextTitle" (click)="navigate(nextIndex)">
|
||||||
(click)="navigate(nextIndex)">
|
<ion-icon name="fas-chevron-right" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
<core-format-text *ngIf="showTitles" [text]="nextTitle" [component]="component" [componentId]="componentId"
|
|
||||||
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" aria-hidden="true">
|
|
||||||
</core-format-text>
|
|
||||||
<ion-icon name="fas-arrow-right" [slot]="showTitles ? 'end' : 'icon-only'" aria-hidden="true"></ion-icon>
|
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
</ion-row>
|
</ion-row>
|
||||||
|
|
|
@ -1,15 +1,24 @@
|
||||||
:host {
|
@import "~theme/globals";
|
||||||
--background: var(--core-course-module-navigation-background);
|
|
||||||
|
|
||||||
|
:host {
|
||||||
|
--height: var(--core-navigation-height, var(--core-navigation-max-height));
|
||||||
|
--background: var(--core-navigation-background);
|
||||||
|
--button-vertical-margin: 2px;
|
||||||
|
|
||||||
|
height: var(--height);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: var(--background);
|
background-color: var(--background);
|
||||||
display: block;
|
display: block;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 3;
|
||||||
|
border-top: 1px solid var(--stroke);
|
||||||
|
|
||||||
.core-navigation-bar-arrow {
|
@include core-transition(all, 200ms);
|
||||||
text-transform: none;
|
|
||||||
max-width: 100%;
|
ion-button,
|
||||||
ion-icon {
|
::ng-deep ion-button {
|
||||||
flex-shrink: 0;
|
margin-top: var(--button-vertical-margin);
|
||||||
}
|
margin-bottom: var(--button-vertical-margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ import { Translate } from '@singletons';
|
||||||
export class CoreNavigationBarComponent implements OnChanges {
|
export class CoreNavigationBarComponent implements OnChanges {
|
||||||
|
|
||||||
@Input() items: CoreNavigationBarItem[] = []; // List of items.
|
@Input() items: CoreNavigationBarItem[] = []; // List of items.
|
||||||
@Input() showTitles = false; // Display titles on buttons.
|
|
||||||
@Input() previousTranslate = 'core.previous'; // Previous translatable text, can admit $a variable.
|
@Input() previousTranslate = 'core.previous'; // Previous translatable text, can admit $a variable.
|
||||||
@Input() nextTranslate = 'core.next'; // Next translatable text, can admit $a variable.
|
@Input() nextTranslate = 'core.next'; // Next translatable text, can admit $a variable.
|
||||||
@Input() component?: string; // Component the bar belongs to.
|
@Input() component?: string; // Component the bar belongs to.
|
||||||
|
@ -46,6 +45,8 @@ export class CoreNavigationBarComponent implements OnChanges {
|
||||||
previousIndex = -1; // Previous item index. If -1, the previous arrow won't be shown.
|
previousIndex = -1; // Previous item index. If -1, the previous arrow won't be shown.
|
||||||
nextIndex = -1; // Next item index. If -1, the next arrow won't be shown.
|
nextIndex = -1; // Next item index. If -1, the next arrow won't be shown.
|
||||||
currentIndex = 0;
|
currentIndex = 0;
|
||||||
|
progress = 0;
|
||||||
|
progressText = '';
|
||||||
|
|
||||||
// Function to call when arrow is clicked. Will receive as a param the item to load.
|
// Function to call when arrow is clicked. Will receive as a param the item to load.
|
||||||
@Output() action: EventEmitter<unknown> = new EventEmitter<unknown>();
|
@Output() action: EventEmitter<unknown> = new EventEmitter<unknown>();
|
||||||
|
@ -63,6 +64,9 @@ export class CoreNavigationBarComponent implements OnChanges {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.progress = ((this.currentIndex + 1) / this.items.length) * 100;
|
||||||
|
this.progressText = `${this.currentIndex + 1} / ${this.items.length}`;
|
||||||
|
|
||||||
this.nextIndex = this.items[this.currentIndex + 1]?.enabled ? this.currentIndex + 1 : -1;
|
this.nextIndex = this.items[this.currentIndex + 1]?.enabled ? this.currentIndex + 1 : -1;
|
||||||
if (this.nextIndex >= 0) {
|
if (this.nextIndex >= 0) {
|
||||||
this.nextTitle = Translate.instant(this.nextTranslate, { $a: this.items[this.nextIndex].title || '' });
|
this.nextTitle = Translate.instant(this.nextTranslate, { $a: this.items[this.nextIndex].title || '' });
|
||||||
|
@ -88,22 +92,6 @@ export class CoreNavigationBarComponent implements OnChanges {
|
||||||
this.action.emit(this.items[itemIndex].item);
|
this.action.emit(this.items[itemIndex].item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Navigate to an item with the range component.
|
|
||||||
*
|
|
||||||
* @param target: Element changed.
|
|
||||||
*/
|
|
||||||
navigateOnRange(target: HTMLIonRangeElement): void {
|
|
||||||
const selectedIndex = target.value as number; // Single value, use number.
|
|
||||||
if (!this.items[selectedIndex].enabled) {
|
|
||||||
target.value = this.currentIndex;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.navigate(selectedIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CoreNavigationBarItem<T = unknown> = {
|
export type CoreNavigationBarItem<T = unknown> = {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
</progress>
|
</progress>
|
||||||
<div class="core-progress-text">
|
<div class="core-progress-text">
|
||||||
<span class="sr-only" *ngIf="a11yText">{{ a11yText | translate }}</span>
|
<span class="sr-only" *ngIf="a11yText">{{ a11yText | translate }}</span>
|
||||||
{{ 'core.percentagenumber' | translate: {$a: text} }}
|
{{ text }}
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ export class CoreProgressBarComponent implements OnInit, OnChanges {
|
||||||
this.progress = Math.floor(this.progress);
|
this.progress = Math.floor(this.progress);
|
||||||
|
|
||||||
if (!this.textSupplied) {
|
if (!this.textSupplied) {
|
||||||
this.text = String(this.progress);
|
this.text = Translate.instant('core.percentagenumber', { $a: this.progress });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.width = DomSanitizer.bypassSecurityTrustStyle(this.progress + '%');
|
this.width = DomSanitizer.bypassSecurityTrustStyle(this.progress + '%');
|
||||||
|
@ -94,8 +94,7 @@ export class CoreProgressBarComponent implements OnInit, OnChanges {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changes.text || changes.progress || changes.a11yText) {
|
if (changes.text || changes.progress || changes.a11yText) {
|
||||||
this.progressBarValueText = (this.a11yText ? Translate.instant(this.a11yText) + ' ' : '') +
|
this.progressBarValueText = (this.a11yText ? Translate.instant(this.a11yText) + ' ' : '') + this.text;
|
||||||
Translate.instant('core.percentagenumber', { $a: this.text });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<core-loading [hideUntil]="loaded" [fullscreen]="false">
|
<core-loading [hideUntil]="loaded" [fullscreen]="false">
|
||||||
<ion-row class="ion-justify-content-between ion-align-items-center ion-no-padding ion-wrap" *ngIf="previousModule || nextModule">
|
<ion-row class="ion-justify-content-between ion-align-items-center ion-no-padding ion-wrap" *ngIf="previousModule || nextModule">
|
||||||
<ion-col size="auto" class="ion-no-padding core-course-module-navigation-arrow">
|
<ion-col size="auto" class="ion-no-padding core-course-module-navigation-arrow">
|
||||||
<ion-button fill="clear" class="core-course-previous-module" *ngIf="previousModule" (click)="goToActivity(false)"
|
<ion-button fill="clear" class="core-course-previous-module" [disabled]="!previousModule" (click)="goToActivity(false)"
|
||||||
[attr.aria-label]="'core.course.gotopreviousactivity' | translate">
|
[attr.aria-label]="'core.course.gotopreviousactivity' | translate">
|
||||||
<ion-icon name="fas-arrow-left" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-arrow-left" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
</core-course-module-completion>
|
</core-course-module-completion>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col size="auto" class="ion-no-padding core-course-module-navigation-arrow">
|
<ion-col size="auto" class="ion-no-padding core-course-module-navigation-arrow">
|
||||||
<ion-button fill="clear" class="core-course-next-module" *ngIf="nextModule" (click)="goToActivity(true)"
|
<ion-button fill="clear" class="core-course-next-module" [disabled]="!nextModule" (click)="goToActivity(true)"
|
||||||
[attr.aria-label]="'core.course.gotonextactivity' | translate">
|
[attr.aria-label]="'core.course.gotonextactivity' | translate">
|
||||||
<ion-icon name="fas-arrow-right" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-arrow-right" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
@import "~theme/globals";
|
@import "~theme/globals";
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
--height: var(--core-course-module-navigation-height, var(--core-course-module-navigation-max-height));
|
--height: var(--core-navigation-height, var(--core-navigation-max-height));
|
||||||
--background: var(--core-course-module-navigation-background);
|
--background: var(--core-navigation-background);
|
||||||
--button-vertical-margin: 2px;
|
--button-vertical-margin: 2px;
|
||||||
|
|
||||||
height: var(--height);
|
height: var(--height);
|
||||||
|
@ -25,10 +25,6 @@
|
||||||
margin-top: var(--button-vertical-margin);
|
margin-top: var(--button-vertical-margin);
|
||||||
margin-bottom: var(--button-vertical-margin);
|
margin-bottom: var(--button-vertical-margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
.core-course-module-navigation-arrow {
|
|
||||||
min-width: 48px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:host-context(.core-iframe-fullscreen) {
|
:host-context(.core-iframe-fullscreen) {
|
||||||
|
|
|
@ -128,7 +128,7 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.content.classList.add('has-core-course-module-navigation');
|
this.content.classList.add('has-core-navigation');
|
||||||
|
|
||||||
// Move element to the nearest ion-content if it's not the parent.
|
// Move element to the nearest ion-content if it's not the parent.
|
||||||
if (this.element.parentElement?.nodeName != 'ION-CONTENT') {
|
if (this.element.parentElement?.nodeName != 'ION-CONTENT') {
|
||||||
|
@ -347,7 +347,7 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.element.style.opacity = height <= 0 ? '0' : '1';
|
this.element.style.opacity = height <= 0 ? '0' : '1';
|
||||||
this.content?.style.setProperty('--core-course-module-navigation-height', height + 'px');
|
this.content?.style.setProperty('--core-navigation-height', height + 'px');
|
||||||
this.previousHeight = height;
|
this.previousHeight = height;
|
||||||
|
|
||||||
if (height > 0 && height < this.initialHeight) {
|
if (height > 0 && height < this.initialHeight) {
|
||||||
|
|
|
@ -1124,8 +1124,8 @@ ion-fab[core-fab] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-content.has-core-course-module-navigation ion-fab {
|
ion-content.has-core-navigation ion-fab {
|
||||||
bottom: calc(var(--core-course-module-navigation-height, 0px) + 10px);
|
bottom: calc(var(--core-navigation-height, 0px) + 10px);
|
||||||
@include core-transition(all, 200ms);
|
@include core-transition(all, 200ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,8 @@
|
||||||
--core-send-message-input-background: var(--gray-900);
|
--core-send-message-input-background: var(--gray-900);
|
||||||
--core-send-message-input-color: var(--white);
|
--core-send-message-input-color: var(--white);
|
||||||
|
|
||||||
|
--core-navigation-background: var(--contrast-background);
|
||||||
|
|
||||||
--addon-messages-message-bg: var(--gray-800);
|
--addon-messages-message-bg: var(--gray-800);
|
||||||
--addon-messages-message-activated-bg: var(--gray-700);
|
--addon-messages-message-activated-bg: var(--gray-700);
|
||||||
--addon-messages-message-note-text: var(--subdued-text-color);
|
--addon-messages-message-note-text: var(--subdued-text-color);
|
||||||
|
|
|
@ -310,8 +310,8 @@
|
||||||
--core-courseimage-on-course-size: 72px;
|
--core-courseimage-on-course-size: 72px;
|
||||||
--core-courseimage-radius: var(--medium-radius);
|
--core-courseimage-radius: var(--medium-radius);
|
||||||
|
|
||||||
--core-course-module-navigation-max-height: 48px;
|
--core-navigation-max-height: 48px;
|
||||||
--core-course-module-navigation-background: var(--contrast-background);
|
--core-navigation-background: var(--contrast-background);
|
||||||
|
|
||||||
--core-user-menu-site-logo-max-height: 32px;
|
--core-user-menu-site-logo-max-height: 32px;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue