From 605aa1b782115407bbd1e4c17a82f80fddd40b44 Mon Sep 17 00:00:00 2001 From: Daniel Blumrich Date: Thu, 8 Sep 2022 11:58:57 +0000 Subject: [PATCH] feat:Change styles on dashboard, add animations --- .../modules/dashboard/dashboard-collapse.ts | 77 +++++++++++++++ .../dashboard.collapse.component.scss | 47 ++++++++++ .../dashboard/dashboard.component.html | 93 ++++++++++--------- .../dashboard/dashboard.component.scss | 87 +++++++---------- .../modules/dashboard/dashboard.component.ts | 44 ++++++++- .../dashboard/section/section.component.scss | 17 +--- .../news-section/news-section.component.ts | 4 +- .../search-section.component.html | 3 +- .../search-section.component.scss | 1 + src/app/modules/menu/tabs/tabs.component.scss | 1 - src/theme/common/_swiper.scss | 2 +- src/theme/components/_section.scss | 2 +- 12 files changed, 252 insertions(+), 126 deletions(-) create mode 100644 src/app/modules/dashboard/dashboard-collapse.ts create mode 100644 src/app/modules/dashboard/dashboard.collapse.component.scss diff --git a/src/app/modules/dashboard/dashboard-collapse.ts b/src/app/modules/dashboard/dashboard-collapse.ts new file mode 100644 index 00000000..c8ec4e3b --- /dev/null +++ b/src/app/modules/dashboard/dashboard-collapse.ts @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +import {Animation, AnimationController} from '@ionic/angular'; +import {NgZone} from '@angular/core'; + +export class DashboardCollapse { + collapseAnimation: Animation; + + nextFrame: number; + + constructor( + private animationControl: AnimationController, + private zone: NgZone, + scrollContainer: HTMLElement, + toolbar: HTMLElement, + schedule: HTMLElement, + ) { + this.zone + .runOutsideAngular(async () => { + this.collapseAnimation = this.animationControl + .create() + .duration(1000) + .addAnimation([ + this.animationControl + .create() + .addElement(toolbar) + .fromTo('transform', 'translateY(0)', 'translateY(-32px)'), + this.animationControl + .create() + .addElement(toolbar.querySelector(':scope > ion-img')!) + .fromTo('transform', 'scale(1)', 'scale(0.35)'), + this.animationControl + .create() + .addElement(schedule) + .fromTo( + 'transform', + 'translateY(0) scaleY(1)', + 'translateY(-75px) scaleY(0.8)', + ), + this.animationControl + .create() + .addElement(schedule.querySelectorAll(':scope > a > *')) + .fromTo('transform', 'scaleY(1)', `scaleY(${1 / 0.8})`), + ]); + this.collapseAnimation.progressStart(true, 0); + + const element = scrollContainer; + let pos = element.scrollTop; + const animate = () => { + if (pos !== element.scrollTop) { + pos = element.scrollTop; + this.collapseAnimation.progressStep(element.scrollTop / 172); + } + this.nextFrame = requestAnimationFrame(animate); + }; + this.nextFrame = requestAnimationFrame(animate); + }) + .then(); + } + + destroy() { + cancelAnimationFrame(this.nextFrame); + } +} diff --git a/src/app/modules/dashboard/dashboard.collapse.component.scss b/src/app/modules/dashboard/dashboard.collapse.component.scss new file mode 100644 index 00000000..978d6268 --- /dev/null +++ b/src/app/modules/dashboard/dashboard.collapse.component.scss @@ -0,0 +1,47 @@ +/*! + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +@import '../../../theme/util/mixins'; + +@include ion-md-down { + ion-toolbar, .logo, .schedule, .schedule > a > * { + will-change: transform; + } + + .logo { + transform-origin: center right; + } + + .schedule { + + > a { + > * { + transform-origin: center; + } + + > ion-label:first-child { + transform-origin: bottom; + } + + > ion-label:last-child { + transform-origin: top; + } + + > ion-icon:first-child { + transform-origin: top; + } + } + } +} diff --git a/src/app/modules/dashboard/dashboard.component.html b/src/app/modules/dashboard/dashboard.component.html index f77b9756..f70340d5 100644 --- a/src/app/modules/dashboard/dashboard.component.html +++ b/src/app/modules/dashboard/dashboard.component.html @@ -1,54 +1,57 @@ - - + + {{ + 'dashboard.header.title' | daytimeKey | translate + }} + + + - -
- - - - - -
+ + + + + + diff --git a/src/app/modules/dashboard/dashboard.component.scss b/src/app/modules/dashboard/dashboard.component.scss index 19b2df8c..12f677ab 100644 --- a/src/app/modules/dashboard/dashboard.component.scss +++ b/src/app/modules/dashboard/dashboard.component.scss @@ -1,23 +1,28 @@ /*! * Copyright (C) 2022 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . */ @import '../../../theme/util/mixins'; +:host ion-header { + z-index: 1; +} + :host ion-toolbar:last-of-type { --padding-top: var(--spacing-md); - --padding-bottom: 0; + --padding-bottom: var(--spacing-md); + z-index: -1; ion-icon { margin-right: var(--spacing-sm); @@ -38,65 +43,27 @@ aspect-ratio: 1/1; object-position: right; margin-left: auto; - margin-right: var(--spacing-sm); - - @include phoneLandscape { - width: auto; - height: 50px; - } - - @include phonePortraitSmall { - width: auto; - height: 50px; - } + margin-right: 0; } } ion-content { --background: var(--ion-color-light); - --overflow: hidden; - - .scrollable-container { - overflow: hidden auto; - height: 100%; - padding-top: 122px; - - @media (max-width: 440px) { - padding-top: 140px; - } - - @include ion-md-up { - padding-top: 0; - padding-bottom: 122px; - } - } - - @include phoneLandscape { - --overflow: hidden auto; - - .scrollable-container { - overflow: initial; - height: initial; - padding-top: 0; - padding-bottom: 0; - } - } } .schedule { - position: fixed; width: 100%; z-index: 3; background: var(--ion-color-primary); display: flex; justify-content: space-between; gap: var(--spacing-md); - padding: var(--spacing-sm) var(--spacing-sm) var(--spacing-xl); + padding: var(--spacing-sm); + padding-top: 0; @include ion-md-up { position: unset; width: unset; - z-index: unset; height: calc(var(--tablet-top-bar-height) + (2 * var(--spacing-xl))); margin: 0; padding: var(--spacing-xl); @@ -113,22 +80,25 @@ ion-content { } a:first-child { - border: 2px solid var(--ion-color-primary-tint); text-align: center; flex: 0 0 auto; aspect-ratio: 1; box-sizing: content-box; max-height: 60px; + overflow: hidden; + border: 2px solid var(--ion-color-primary-tint); @include phoneLandscape { height: auto; } + } + + a:first-child { + justify-content: space-around; + align-items: center; + gap: var(--spacing-sm); - ion-icon { - margin: auto auto var(--spacing-xs); - } ion-label { - margin: 0 auto auto; font-size: var(--font-size-xxs); font-weight: var(--font-weight-semi-bold); } @@ -142,6 +112,7 @@ ion-content { flex: 1 1 65%; background: var(--linear-gradient); justify-content: center; + z-index: 1; @include ion-md-up { flex: 1 1 100%; @@ -156,10 +127,12 @@ ion-content { font-weight: var(--font-weight-bold); line-height: 1.4; } + ion-label:first-child { text-transform: uppercase; color: var(--ion-color-secondary); } + ion-label:nth-child(2n) { font-size: var(--font-size-lg); font-weight: var(--font-weight-semi-bold); @@ -173,6 +146,7 @@ ion-content { &.section-extended { padding-right: 0; + ion-icon[name='edit'] { margin-right: var(--spacing-md); } @@ -232,6 +206,7 @@ ion-searchbar { input { padding: var(--spacing-lg); } + ion-icon { left: auto; right: var(--spacing-lg); diff --git a/src/app/modules/dashboard/dashboard.component.ts b/src/app/modules/dashboard/dashboard.component.ts index 03ae27d7..8157993d 100644 --- a/src/app/modules/dashboard/dashboard.component.ts +++ b/src/app/modules/dashboard/dashboard.component.ts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 StApps + * Copyright (C) 2022 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. @@ -12,7 +12,14 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, OnInit, OnDestroy} from '@angular/core'; +import { + Component, + ElementRef, + NgZone, + OnDestroy, + OnInit, + ViewChild, +} from '@angular/core'; import {Router} from '@angular/router'; import {Location} from '@angular/common'; import {Subscription} from 'rxjs'; @@ -22,11 +29,18 @@ import {SplashScreen} from '@capacitor/splash-screen'; import {DataRoutingService} from '../data/data-routing.service'; import {ScheduleProvider} from '../calendar/schedule.provider'; +import {AnimationController, IonContent} from '@ionic/angular'; +import {DashboardCollapse} from './dashboard-collapse'; + +// const scrollTimeline = new ScrollTimeline(); @Component({ selector: 'app-dashboard', templateUrl: './dashboard.component.html', - styleUrls: ['./dashboard.component.scss'], + styleUrls: [ + './dashboard.component.scss', + '/dashboard.collapse.component.scss', + ], }) export class DashboardComponent implements OnInit, OnDestroy { /** @@ -34,6 +48,14 @@ export class DashboardComponent implements OnInit, OnDestroy { */ subscriptions: Subscription[] = []; + @ViewChild('toolbar', {read: ElementRef}) toolbarRef: ElementRef; + + @ViewChild('schedule', {read: ElementRef}) scheduleRef: ElementRef; + + @ViewChild('ionContent') ionContentRef: IonContent; + + collapseAnimation: DashboardCollapse; + /** * UUID subscription */ @@ -44,6 +66,11 @@ export class DashboardComponent implements OnInit, OnDestroy { */ private uuids: SCUuid[]; + /** + * Enable header animation + */ + isHeaderAnimated = true; + /** * Next event in calendar */ @@ -66,6 +93,8 @@ export class DashboardComponent implements OnInit, OnDestroy { private scheduleProvider: ScheduleProvider, protected router: Router, public location: Location, + private animationControl: AnimationController, + private zone: NgZone, ) { this.subscriptions.push( this.dataRoutingService.itemSelectListener().subscribe(item => { @@ -82,6 +111,14 @@ export class DashboardComponent implements OnInit, OnDestroy { }, ); await SplashScreen.hide(); + + this.collapseAnimation = new DashboardCollapse( + this.animationControl, + this.zone, + await this.ionContentRef.getScrollElement(), + this.toolbarRef.nativeElement, + this.scheduleRef.nativeElement, + ); } async loadNextEvent() { @@ -103,5 +140,6 @@ export class DashboardComponent implements OnInit, OnDestroy { sub.unsubscribe(); } this._uuidSubscription.unsubscribe(); + this.collapseAnimation.destroy(); } } diff --git a/src/app/modules/dashboard/section/section.component.scss b/src/app/modules/dashboard/section/section.component.scss index 0ccc6415..5ae00030 100644 --- a/src/app/modules/dashboard/section/section.component.scss +++ b/src/app/modules/dashboard/section/section.component.scss @@ -17,7 +17,7 @@ :host { display: block; - padding: var(--spacing-md) var(--spacing-md) var(--spacing-sm); + padding: var(--spacing-sm) var(--spacing-md) var(--spacing-sm); @include ion-md-up { padding: var(--spacing-lg) var(--spacing-xxl) var(--spacing-sm); @@ -40,28 +40,13 @@ } } - // TODO - &:first-of-type { - padding-top: var(--spacing-lg); - } - & > ion-label:first-child { font-family: var(--headline-font-family); - font-size: var(--font-size-lg); font-weight: var(--font-weight-bold); - font-stretch: condensed; - text-transform: uppercase; - margin-bottom: var(--spacing-xs); - - width: 100%; - display: flex; - flex-direction: revert; - justify-content: space-between; ion-icon { color: var(--ion-color-medium-shade); position: relative; - bottom: var(--spacing-sm); margin-block: auto; cursor: pointer; diff --git a/src/app/modules/dashboard/sections/news-section/news-section.component.ts b/src/app/modules/dashboard/sections/news-section/news-section.component.ts index 6e9b3423..f46c4010 100644 --- a/src/app/modules/dashboard/sections/news-section/news-section.component.ts +++ b/src/app/modules/dashboard/sections/news-section/news-section.component.ts @@ -43,10 +43,10 @@ export class NewsSectionComponent extends NewsPageComponent implements OnInit { enabled: true, sticky: true, }, - width: 240, + width: 300, breakpoints: { 768: { - width: 280, + width: 380, }, }, }; diff --git a/src/app/modules/dashboard/sections/search-section/search-section.component.html b/src/app/modules/dashboard/sections/search-section/search-section.component.html index 2f01484a..0cd4964c 100644 --- a/src/app/modules/dashboard/sections/search-section/search-section.component.html +++ b/src/app/modules/dashboard/sections/search-section/search-section.component.html @@ -26,7 +26,8 @@ [(ngModel)]="searchTerm" >