diff --git a/src/core/components/loading/core-loading.html b/src/core/components/loading/core-loading.html index 569682040..cabe746af 100644 --- a/src/core/components/loading/core-loading.html +++ b/src/core/components/loading/core-loading.html @@ -2,8 +2,4 @@

{{message}}

-
- - -
+ diff --git a/src/core/components/loading/loading.scss b/src/core/components/loading/loading.scss index efa86a0de..82ab20289 100644 --- a/src/core/components/loading/loading.scss +++ b/src/core/components/loading/loading.scss @@ -1,5 +1,27 @@ @import "~theme/globals"; +@mixin inline() { + min-height: var(--internal-loading-inline-min-height); + max-height: 100vh; // In order show it on the page (content will be cut). + + &:not(.core-loading-loaded) { + position: relative; + --contents-display: flex; + flex-direction: column; + } + + .core-loading-container { + --loading-background: rgba(var(--loading-background-inline), 0.4); + flex-direction: row; + height: auto; + width: auto; + + .core-loading-message { + @include margin(0, 0, 0, 10px); + } + } +} + :host { --loading-background: var(--ion-background-color); --loading-background-inline: var(--ion-background-color-rgb); @@ -8,27 +30,28 @@ --loading-inline-margin: 0px; --loading-inline-min-height: 28px; --internal-loading-inline-min-height: var(--loading-inline-min-height); - --content-display: contents; + --loading-display: flex; + --loading-display-message: block; + --contents-display: contents; - position: static; - color: var(--loading-text-color); @include core-transition(all, 200ms); - - &.margin { - --loading-inline-margin: 10px; - --internal-loading-inline-min-height: calc(var(--loading-inline-min-height) + var(--loading-inline-margin) + var(--loading-inline-margin)); - } + pointer-events: none; + display: var(--contents-display); &.core-loading-loaded { + position: static; + pointer-events: auto; --internal-loading-inline-min-height: 0px; - } - ion-spinner { - --color: var(--loading-spinner); - color: var(--color); + &.has-spacer { + --contents-display: flex; + min-height: 100%; + flex-direction: column; + } } .core-loading-container { + pointer-events: none; position: absolute; @include position(0, 0, 0, 0); height: 100%; @@ -36,78 +59,38 @@ z-index: 3; margin: 0; padding: 0; + color: var(--loading-text-color); background-color: var(--loading-background); @include core-transition(all, 200ms); - display: flex; + display: var(--loading-display); justify-content: center; align-items: center; flex-direction: column; - } - - .core-loading-content { - @include core-transition(opacity, 200ms); - display: var(--content-display); - } - - .core-loading-message { - @include margin(10px, 0, 0, 0); - } - - &.core-loading-loaded { - position: unset; - display: contents; - } - - &.core-loading-inline { - --loading-background: rgba(var(--loading-background-inline), 0.5); - position: relative; - display: block; - min-height: var(--internal-loading-inline-min-height); .core-loading-message { - @include margin(0, 0, 0, 10px); + @include margin(10px, 0, 0, 0); + display: var(--loading-display-message); } - .core-loading-container { - flex-direction: row; + ion-spinner { + --color: var(--loading-spinner); + color: var(--color); } } - &.core-loading-full-height .core-loading-content { - height: 100%; - } - - &.has-spacer { - --content-display: flex; - - .core-loading-content { - min-height: 100%; - flex-direction: column; - } - } - - &.list-item-limited-width .core-loading-content { - max-width: var(--list-item-max-width); - margin-left: auto !important; - margin-right: auto !important; - } - - &.safe-area-padding:not(.core-loading-inline) .core-loading-content, - &.safe-area-padding-horizontal:not(.core-loading-inline) .core-loading-content { - @include safe-area-padding-horizontal(0px, 0px); - } - - &.safe-area-padding:not(.core-loading-inline) .core-loading-content { - padding-bottom: var(--ion-safe-area-bottom); - > * { - --ion-safe-area-bottom: 0px; - } - } -} - -:host-context(ion-item) { &.core-loading-inline { - position: static; - display: block; + @include inline(); } } + +// Force inline on some contexts. +:host-context(ion-item), +:host-context(core-block) { + // Implicit Inline. + @include inline(); +} + +:host-context(.limited-width > ):not([slot]) { + --contents-display: flex; + flex-direction: column; +} diff --git a/src/core/components/loading/loading.ts b/src/core/components/loading/loading.ts index d5be19770..7485ade46 100644 --- a/src/core/components/loading/loading.ts +++ b/src/core/components/loading/loading.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, Input, OnInit, OnChanges, SimpleChange, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; +import { Component, Input, OnInit, OnChanges, SimpleChange, ElementRef, AfterViewInit } from '@angular/core'; import { CoreEventLoadingChangedData, CoreEvents } from '@singletons/events'; import { CoreUtils } from '@services/utils/utils'; @@ -50,15 +50,14 @@ import { AsyncComponent } from '@classes/async-component'; }) export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit, AsyncComponent { - @Input() hideUntil: unknown; // Determine when should the contents be shown. + @Input() hideUntil = false; // Determine when should the contents be shown. @Input() message?: string; // Message to show while loading. @Input() fullscreen = true; // Use the whole screen. - @ViewChild('content') content?: ElementRef; - uniqueId: string; - protected element: HTMLElement; // Current element. loaded = false; // Only comes true once. + + protected element: HTMLElement; // Current element. protected onReadyPromise = new CorePromisedValue(); constructor(element: ElementRef) { @@ -67,6 +66,7 @@ export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit, A // Calculate the unique ID. this.uniqueId = 'core-loading-content-' + CoreUtils.getUniqueId('CoreLoadingComponent'); + this.element.setAttribute('id', this.uniqueId); } /** @@ -77,7 +77,6 @@ export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit, A // Default loading message. this.message = Translate.instant('core.loading'); } - this.element.classList.toggle('core-loading-inline', !this.fullscreen); } @@ -85,7 +84,7 @@ export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit, A * @inheritdoc */ ngAfterViewInit(): void { - this.changeState(!!this.hideUntil); + this.changeState(this.hideUntil); } /** @@ -93,7 +92,7 @@ export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit, A */ ngOnChanges(changes: { [name: string]: SimpleChange }): void { if (changes.hideUntil) { - this.changeState(!!this.hideUntil); + this.changeState(this.hideUntil); } } @@ -105,7 +104,7 @@ export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit, A */ async changeState(loaded: boolean): Promise { this.element.classList.toggle('core-loading-loaded', loaded); - this.content?.nativeElement.classList.toggle('core-loading-content', loaded); + this.element.setAttribute('aria-busy', loaded ? 'false' : 'true'); if (!this.loaded && loaded) { this.loaded = true; // Only comes true once.