From 6d148229f193bf5001c985c6216ffdd7a171874d Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Tue, 26 Jan 2021 09:28:46 +0100 Subject: [PATCH] MOBILE-3661 split-view: Support nested split views --- .../components/split-view/split-view.html | 4 +- .../components/split-view/split-view.scss | 68 ++++++++----------- src/core/components/split-view/split-view.ts | 50 ++++++++++++-- src/theme/breakpoints.scss | 13 ---- 4 files changed, 75 insertions(+), 60 deletions(-) delete mode 100644 src/theme/breakpoints.scss diff --git a/src/core/components/split-view/split-view.html b/src/core/components/split-view/split-view.html index ee5f74817..a585f4b0a 100644 --- a/src/core/components/split-view/split-view.html +++ b/src/core/components/split-view/split-view.html @@ -1,5 +1,5 @@ - + - + diff --git a/src/core/components/split-view/split-view.scss b/src/core/components/split-view/split-view.scss index 13cf43e23..d94a6efcc 100644 --- a/src/core/components/split-view/split-view.scss +++ b/src/core/components/split-view/split-view.scss @@ -1,11 +1,11 @@ -@import "~theme/breakpoints"; - // @todo RTL layout :host { - --side-width: 100%; - --side-min-width: 270px; - --side-max-width: 28%; + --menu-min-width: 270px; + --menu-max-width: 28%; + --menu-display: flex; + --content-display: block; + --border-width: 1; top: 0; right: 0; @@ -19,16 +19,28 @@ contain: strict; } +:host(.menu-only) { + --menu-min-width: 0; + --menu-max-width: 100%; + --content-display: none; + --border-width: 0; +} + +:host(.content-only) { + --menu-display: none; + --border-width: 0; +} + :host-context(ion-app.md) { - --border: 1px solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-150, rgba(0, 0, 0, .13)))); + --border: calc(var(--border-width) * 1px) solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-150, rgba(0, 0, 0, .13)))); } :host-context(ion-app.ios) { - --border: .55px solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-250, #c8c7cc))); + --border: calc(var(--border-width) * .55px) solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-250, #c8c7cc))); } -ion-content, -ion-router-outlet { +.menu, +.content { top: 0; right: 0; bottom: 0; @@ -38,49 +50,25 @@ ion-router-outlet { z-index: 0; } -ion-content { - display: flex; +.menu { + display: var(--menu-display); flex-shrink: 0; order: -1; border-left: unset; border-right: unset; border-inline-start: 0; - border-inline-end: 0; + border-inline-end: var(--border); + min-width: var(--menu-min-width); + max-width: var(--menu-max-width); width: 100%; } -ion-router-outlet { +.content { + display: var(--content-display); flex: 1; - display: none; ::ng-deep ion-header { display: none; } } - -:host(.outlet-activated) { - - ion-router-outlet { - display: block; - } - - ion-content { - display: none; - } - -} - -@media (min-width: $breakpoint-tablet) { - - ion-content { - border-inline-end: var(--border); - min-width: var(--side-min-width); - max-width: var(--side-max-width); - } - - :host(.outlet-activated) ion-content { - display: flex; - } - -} diff --git a/src/core/components/split-view/split-view.ts b/src/core/components/split-view/split-view.ts index 6f2488445..69f29e46e 100644 --- a/src/core/components/split-view/split-view.ts +++ b/src/core/components/split-view/split-view.ts @@ -12,10 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { AfterViewInit, Component, HostBinding, OnDestroy, ViewChild } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, HostBinding, OnDestroy, ViewChild } from '@angular/core'; import { IonRouterOutlet } from '@ionic/angular'; +import { CoreScreen } from '@services/screen'; import { Subscription } from 'rxjs'; +enum CoreSplitViewMode { + Default = '', // Shows both menu and content. + MenuOnly = 'menu-only', // Hides content. + ContentOnly = 'content-only', // Hides menu. +} + @Component({ selector: 'core-split-view', templateUrl: 'split-view.html', @@ -24,19 +31,25 @@ import { Subscription } from 'rxjs'; export class CoreSplitViewComponent implements AfterViewInit, OnDestroy { @ViewChild(IonRouterOutlet) outlet!: IonRouterOutlet; - @HostBinding('class.outlet-activated') outletActivated = false; + @HostBinding('class') classes = ''; + private isNestedSplitView = false; private subscriptions?: Subscription[]; + constructor(private element: ElementRef) {} + /** * @inheritdoc */ ngAfterViewInit(): void { - this.outletActivated = this.outlet.isActivated; + this.isNestedSplitView = !!this.element.nativeElement.parentElement?.closest('core-split-view'); this.subscriptions = [ - this.outlet.activateEvents.subscribe(() => this.outletActivated = true), - this.outlet.deactivateEvents.subscribe(() => this.outletActivated = false), + this.outlet.activateEvents.subscribe(() => this.updateClasses()), + this.outlet.deactivateEvents.subscribe(() => this.updateClasses()), + CoreScreen.instance.layoutObservable.subscribe(() => this.updateClasses()), ]; + + this.updateClasses(); } /** @@ -46,4 +59,31 @@ export class CoreSplitViewComponent implements AfterViewInit, OnDestroy { this.subscriptions?.forEach(subscription => subscription.unsubscribe()); } + /** + * Update host classes. + */ + private updateClasses(): void { + this.classes = this.getCurrentMode(); + } + + /** + * Get the current mode. Depending on the layout, outlet status, and whether this split view + * is nested or not, this method will indicate which parts of the split view should be visible. + * + * @return Split view mode. + */ + private getCurrentMode(): CoreSplitViewMode { + if (this.isNestedSplitView) { + return CoreSplitViewMode.MenuOnly; + } + + if (CoreScreen.instance.isMobile) { + return this.outlet.isActivated + ? CoreSplitViewMode.ContentOnly + : CoreSplitViewMode.MenuOnly; + } + + return CoreSplitViewMode.Default; + } + } diff --git a/src/theme/breakpoints.scss b/src/theme/breakpoints.scss deleted file mode 100644 index 8cc9f2207..000000000 --- a/src/theme/breakpoints.scss +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Layout Breakpoints - * - * https://ionicframework.com/docs/layout/grid#default-breakpoints - */ - -$breakpoint-xs: 0px; -$breakpoint-sm: 576px; -$breakpoint-md: 768px; -$breakpoint-lg: 992px; -$breakpoint-xl: 1200px; - -$breakpoint-tablet: $breakpoint-lg;