diff --git a/src/core/components/split-view/split-view.scss b/src/core/components/split-view/split-view.scss index deb84173f..a333f7623 100644 --- a/src/core/components/split-view/split-view.scss +++ b/src/core/components/split-view/split-view.scss @@ -22,6 +22,7 @@ .menu, .content-outlet { top: var(--offset-top); + height: calc(100% - var(--offset-top)); right: 0; bottom: 0; left: 0; diff --git a/src/core/directives/fab.ts b/src/core/directives/fab.ts index d3d0677cb..d8cd1db30 100644 --- a/src/core/directives/fab.ts +++ b/src/core/directives/fab.ts @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Directive, ElementRef, OnDestroy } from '@angular/core'; -import { IonContent } from '@ionic/angular'; +import { Directive, ElementRef, OnDestroy, OnInit } from '@angular/core'; +import { CoreUtils } from '@services/utils/utils'; /** * Directive to move ion-fab components as direct children of the nearest ion-content. @@ -25,47 +25,50 @@ import { IonContent } from '@ionic/angular'; @Directive({ selector: 'ion-fab[core-fab]', }) -export class CoreFabDirective implements OnDestroy { +export class CoreFabDirective implements OnInit, OnDestroy { - protected static readonly PADDINGBOTTOM = 56; - - protected scrollElement?: HTMLElement; - protected done = false; protected element: HTMLElement; + protected content?: HTMLIonContentElement | null; + protected initialPaddingBottom = 0; - constructor(el: ElementRef, protected content: IonContent) { + constructor(el: ElementRef) { this.element = el.nativeElement; - this.asyncInit(); + this.element.setAttribute('slot', 'fixed'); } /** - * Initialize Component. + * @inheritdoc */ - async asyncInit(): Promise { - if (this.content) { - this.scrollElement = await this.content.getScrollElement(); - if (!this.done) { - // Move element to the nearest ion-content if it's not the parent - if (this.element.parentElement?.nodeName != 'ION-CONTENT') { - const ionContent = this.element.closest('ion-content'); - ionContent?.appendChild(this.element); - } + async ngOnInit(retries = 3): Promise { + this.content = this.element.closest('ion-content'); + if (!this.content) { + if(retries > 0) { + await CoreUtils.nextTicks(50); - // Add space at the bottom to let the user see the whole content. - const bottom = parseInt(this.scrollElement.style.paddingBottom, 10) || 0; - this.scrollElement.style.paddingBottom = (bottom + CoreFabDirective.PADDINGBOTTOM) + 'px'; - this.done = true; + this.ngOnInit(retries - 1); } + + return; } + + const initialHeight = this.element.getBoundingClientRect().height || 56; + + // Move element to the nearest ion-content if it's not the parent + if (this.element.parentElement?.nodeName != 'ION-CONTENT') { + this.content.appendChild(this.element); + } + + // Add space at the bottom to let the user see the whole content. + this.initialPaddingBottom = parseFloat(this.content.style.getPropertyValue('--padding-bottom') || '0'); + this.content.style.setProperty('--padding-bottom', this.initialPaddingBottom + initialHeight + 'px'); } /** - * Destroy component. + * @inheritdoc */ ngOnDestroy(): void { - if (this.done && this.scrollElement) { - const bottom = parseInt(this.scrollElement.style.paddingBottom, 10) || 0; - this.scrollElement.style.paddingBottom = (bottom - CoreFabDirective.PADDINGBOTTOM) + 'px'; + if (this.content) { + this.content.style.setProperty('--padding-bottom', this.initialPaddingBottom + 'px'); } } diff --git a/src/theme/theme.base.scss b/src/theme/theme.base.scss index 4b9278132..51f3cb7f2 100644 --- a/src/theme/theme.base.scss +++ b/src/theme/theme.base.scss @@ -906,13 +906,16 @@ ion-back-button.md::part(text) { display: none; } +// Hide close button because when present is read on voice over. ion-fab[core-fab] { - position: fixed; - - // Hide close button because when present is read on voice over. ion-fab-button::part(close-icon) { display: none; } +} + +core-course-module-navigation + ion-fab { + bottom: calc(var(--core-course-module-navigation-height, 0px) + 10px); + @include core-transition(all, 200ms); } .core-media-adapt-width {