From 77e16bbc3f708792bb2e2701c68b6ff28b2a9061 Mon Sep 17 00:00:00 2001 From: Mike Hartington Date: Fri, 9 Feb 2018 13:03:26 -0500 Subject: [PATCH] feat(animations): back button and view animationsa (#13989) * feat(animations): back button and view animations * chore(): remove unused css * fix(): fix unsaved css * fix(): hide back button when no history --- packages/core/src/components.d.ts | 2 +- .../back-button/back-button.ios.scss | 5 - .../back-button/back-button.ios.vars.scss | 4 - .../back-button/back-button.md.scss | 22 -- .../back-button/back-button.md.vars.scss | 4 - .../components/back-button/back-button.scss | 10 +- .../components/back-button/back-button.tsx | 72 ++--- .../core/src/components/back-button/readme.md | 77 +++++ .../back-button/test/basic/index.html | 25 +- .../core/src/components/button/button.tsx | 2 +- .../src/components/nav-pop/nav-pop.ios.scss | 0 .../src/components/nav-pop/nav-pop.md.scss | 0 .../core/src/components/nav-pop/nav-pop.tsx | 7 - packages/core/src/components/nav/nav-utils.ts | 10 +- packages/core/src/components/nav/nav.scss | 3 + packages/core/src/components/nav/nav.tsx | 12 +- .../nav/transitions/transition.ios.ts | 296 ++++++++++-------- .../nav/transitions/transition.md.ts | 24 +- .../src/components/toolbar/toolbar.ios.scss | 54 ++-- .../core/src/components/toolbar/toolbar.scss | 17 - packages/core/src/global/platform-utils.ts | 2 +- 21 files changed, 356 insertions(+), 292 deletions(-) delete mode 100644 packages/core/src/components/back-button/back-button.ios.scss delete mode 100644 packages/core/src/components/back-button/back-button.ios.vars.scss delete mode 100644 packages/core/src/components/back-button/back-button.md.scss delete mode 100644 packages/core/src/components/back-button/back-button.md.vars.scss delete mode 100644 packages/core/src/components/nav-pop/nav-pop.ios.scss delete mode 100644 packages/core/src/components/nav-pop/nav-pop.md.scss diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index faf562e17a..89355581f9 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -312,7 +312,7 @@ declare global { } namespace JSXElements { export interface IonBackButtonAttributes extends HTMLAttributes { - + mode?: 'ios' | 'md'; } } } diff --git a/packages/core/src/components/back-button/back-button.ios.scss b/packages/core/src/components/back-button/back-button.ios.scss deleted file mode 100644 index c1221f8eac..0000000000 --- a/packages/core/src/components/back-button/back-button.ios.scss +++ /dev/null @@ -1,5 +0,0 @@ -@import "./back-button"; -@import "./back-button.ios.vars"; - -// iOS Back Button -// -------------------------------------------------- diff --git a/packages/core/src/components/back-button/back-button.ios.vars.scss b/packages/core/src/components/back-button/back-button.ios.vars.scss deleted file mode 100644 index adf7c1462e..0000000000 --- a/packages/core/src/components/back-button/back-button.ios.vars.scss +++ /dev/null @@ -1,4 +0,0 @@ -@import "../../themes/ionic.globals.ios"; - -// iOS Back Button -// -------------------------------------------------- diff --git a/packages/core/src/components/back-button/back-button.md.scss b/packages/core/src/components/back-button/back-button.md.scss deleted file mode 100644 index 09ffa18962..0000000000 --- a/packages/core/src/components/back-button/back-button.md.scss +++ /dev/null @@ -1,22 +0,0 @@ -@import "./back-button"; -@import "./back-button.md.vars"; - -// Material Design Back Button -// -------------------------------------------------- - -.back-button-md { - @include margin(0, 6px); - - min-width: 44px; - - box-shadow: none; -} - -.back-button-icon-md { - @include margin(0); - @include padding(0, 6px); - @include text-align(start); - - font-size: 2.4rem; - font-weight: normal; -} diff --git a/packages/core/src/components/back-button/back-button.md.vars.scss b/packages/core/src/components/back-button/back-button.md.vars.scss deleted file mode 100644 index ad840cb1fd..0000000000 --- a/packages/core/src/components/back-button/back-button.md.vars.scss +++ /dev/null @@ -1,4 +0,0 @@ -@import "../../themes/ionic.globals.md"; - -// Material Design Back Button -// -------------------------------------------------- diff --git a/packages/core/src/components/back-button/back-button.scss b/packages/core/src/components/back-button/back-button.scss index a0eba3a845..d7877913d4 100644 --- a/packages/core/src/components/back-button/back-button.scss +++ b/packages/core/src/components/back-button/back-button.scss @@ -2,14 +2,12 @@ // Back Button // -------------------------------------------------- -// .back-button { -// display: none; -// } - -// .back-button.show-back-button { .back-button { - display: inline-block; + display: none; +} +.back-button.show-back-button { + display: inline-block; } .back-button-text { diff --git a/packages/core/src/components/back-button/back-button.tsx b/packages/core/src/components/back-button/back-button.tsx index 7c0315b96a..bd7f2eb017 100644 --- a/packages/core/src/components/back-button/back-button.tsx +++ b/packages/core/src/components/back-button/back-button.tsx @@ -1,53 +1,53 @@ -import { Component, Prop } from '@stencil/core'; +import { Component, Element, Prop, State } from '@stencil/core'; import { Config } from '../../index'; - @Component({ tag: 'ion-back-button', - styleUrls: { - ios: 'back-button.ios.scss', - md: 'back-button.md.scss' - }, + styleUrl: 'back-button.scss', host: { theme: 'back-button' } }) export class BackButton { - private mode: string; + + @State() custom: boolean; + + /** + * The mode determines which platform styles to use. + * Possible values are: `"ios"` or `"md"`. + * For more information, see [Platform Styles](/docs/theming/platform-specific-styles). + */ + @Prop() mode: 'ios' | 'md'; @Prop({ context: 'config' }) config: Config; + @Element() el: HTMLElement; + + componentWillLoad() { + this.custom = this.el.childElementCount > 0; + } render() { - const iconName = this.config.get('backButtonIcon', this.mode + '-arrow-back'); - const text = this.config.get('backButtonText', 'Back'); + const backButtonIcon = this.config.get('backButtonIcon', 'arrow-back'); + const backButtonText = this.config.get('backButtonText', 'Back'); + const buttonColor = this.mode === 'ios' ? 'primary' : ''; - const iconClass: any = { - 'back-button-icon': true - }; - const textClass: any = { - 'back-button-text': true - }; - - if (this.mode) { - iconClass['back-button-icon-' + this.mode] = true; - iconClass['back-button-text-' + this.mode] = true; + if (this.custom) { + return ( + + + + ); + } else if (!this.custom) { + return ( + + + + {backButtonText} + + + ); + } else { + return undefined; } - - return ( - - - - ); } } diff --git a/packages/core/src/components/back-button/readme.md b/packages/core/src/components/back-button/readme.md index efd344f38e..6e740a8fc2 100644 --- a/packages/core/src/components/back-button/readme.md +++ b/packages/core/src/components/back-button/readme.md @@ -1,9 +1,86 @@ # ion-back-button +A back button is a component that allows you navigate back into app history. To +add a back button to your view, all you need is: + +```html + + + + + + + + + +``` + +The back button component is smart enough to know what to render and what content to show. + +If, however, you want more control over what is shown in the back button, you can pass your own button markup. + +```html + + + + + + + Button Text + + + + + + + +``` + +Or no button text at all: + + +```html + + + + + + + + + + + + + +``` + +## Properties + +#### mode + + + +The mode determines which platform styles to use. +Possible values are: `"ios"` or `"md"`. +For more information, see [Platform Styles](/docs/theming/platform-specific-styles). + + +## Attributes + +#### mode + + + +The mode determines which platform styles to use. +Possible values are: `"ios"` or `"md"`. +For more information, see [Platform Styles](/docs/theming/platform-specific-styles). + + ---------------------------------------------- diff --git a/packages/core/src/components/back-button/test/basic/index.html b/packages/core/src/components/back-button/test/basic/index.html index c1a3d09307..f5ea15d7b1 100644 --- a/packages/core/src/components/back-button/test/basic/index.html +++ b/packages/core/src/components/back-button/test/basic/index.html @@ -35,6 +35,9 @@ firstPage.innerHTML = ` + + + Page One @@ -47,7 +50,7 @@ await nav.push(firstPage); // okay cool, we're in the DOM now - const button = firstPage.querySelector('ion-button'); + const button = firstPage.querySelector('.next'); button.addEventListener('click', async () => { await goToPageTwo(nav); }); @@ -60,14 +63,14 @@ - - + Page Two

Page Two

+

Just an empty ion-back-button

Go to Page Three
`; @@ -89,6 +92,9 @@ + + + Page Three @@ -96,6 +102,7 @@

Page Three

+

Custom back button

`; @@ -103,10 +110,10 @@ await nav.push(thirdPage); } - + + + + + + diff --git a/packages/core/src/components/button/button.tsx b/packages/core/src/components/button/button.tsx index 2bbcb93e2f..43e84ae285 100644 --- a/packages/core/src/components/button/button.tsx +++ b/packages/core/src/components/button/button.tsx @@ -134,7 +134,7 @@ export class Button { - + { this.mode === 'md' && } diff --git a/packages/core/src/components/nav-pop/nav-pop.ios.scss b/packages/core/src/components/nav-pop/nav-pop.ios.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/core/src/components/nav-pop/nav-pop.md.scss b/packages/core/src/components/nav-pop/nav-pop.md.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/core/src/components/nav-pop/nav-pop.tsx b/packages/core/src/components/nav-pop/nav-pop.tsx index a5cd173eab..326f35dc34 100644 --- a/packages/core/src/components/nav-pop/nav-pop.tsx +++ b/packages/core/src/components/nav-pop/nav-pop.tsx @@ -2,13 +2,6 @@ import { Component, Element, Listen } from '@stencil/core'; @Component({ tag: 'ion-nav-pop', - styleUrls: { - ios: 'nav-pop.ios.scss', - md: 'nav-pop.md.scss' - }, - host: { - theme: 'nav-pop' - } }) export class NavPop { diff --git a/packages/core/src/components/nav/nav-utils.ts b/packages/core/src/components/nav/nav-utils.ts index 516b890b75..51cd12458c 100644 --- a/packages/core/src/components/nav/nav-utils.ts +++ b/packages/core/src/components/nav/nav-utils.ts @@ -70,17 +70,15 @@ export function updateZIndex(viewController: ViewController, newZIndex: number) } } -export function toggleHidden(element: HTMLElement, isVisible: Boolean, shouldBeVisible: boolean) { - if (isVisible !== shouldBeVisible) { - element.hidden = shouldBeVisible; - } +export function toggleHidden(element: HTMLElement, shouldBeHidden: boolean) { + element.hidden = shouldBeHidden; } -export function canNavGoBack(nav: Nav) { +export function canNavGoBack(nav: Nav, view?: ViewController) { if (!nav) { return false; } - return !!nav.getPrevious(); + return nav.getPrevious(view); } export function transitionFactory(animation: Animation): Transition { diff --git a/packages/core/src/components/nav/nav.scss b/packages/core/src/components/nav/nav.scss index 5ae2bec48f..3a0da0092b 100644 --- a/packages/core/src/components/nav/nav.scss +++ b/packages/core/src/components/nav/nav.scss @@ -13,7 +13,10 @@ ion-nav { width: 100%; height: 100%; + background-color: black; + contain: layout size style; + } .ion-page { diff --git a/packages/core/src/components/nav/nav.tsx b/packages/core/src/components/nav/nav.tsx index 1683cc8abe..95bc687cbe 100644 --- a/packages/core/src/components/nav/nav.tsx +++ b/packages/core/src/components/nav/nav.tsx @@ -737,7 +737,6 @@ export function loadViewAndTransition(nav: Nav, enteringView: ViewController, le }); } - export function executeAsyncTransition(nav: Nav, transition: Transition, enteringView: ViewController, leavingView: ViewController, delegate: FrameworkDelegate, opts: NavOptions, configShouldAnimate: boolean): Promise { assert(nav.transitioning, 'must be transitioning'); nav.transitionId = null; @@ -746,11 +745,11 @@ export function executeAsyncTransition(nav: Nav, transition: Transition, enterin // always ensure the entering view is viewable // ******** DOM WRITE **************** // TODO, figure out where we want to read this data from - enteringView && toggleHidden(enteringView.element, true, true); + enteringView && toggleHidden(enteringView.element, false); // always ensure the leaving view is viewable // ******** DOM WRITE **************** - leavingView && toggleHidden(leavingView.element, true, true); + leavingView && toggleHidden(leavingView.element, false); const isFirstPage = !nav.isViewInitialized && nav.views.length === 1; const shouldNotAnimate = isFirstPage && !nav.isPortal; @@ -834,15 +833,16 @@ export function transitionFinish(nav: Nav, transition: Transition, delegate: Fra } export function cleanUpView(nav: Nav, delegate: FrameworkDelegate, activeViewController: ViewController): Promise { - if (nav.destroyed) { return Promise.resolve(); } const activeIndex = nav.views.indexOf(activeViewController); const promises: Promise[] = []; + for (let i = nav.views.length - 1; i >= 0; i--) { const inactiveViewController = nav.views[i]; + if (i > activeIndex) { // this view comes after the active view inactiveViewController.willUnload(); @@ -850,14 +850,14 @@ export function cleanUpView(nav: Nav, delegate: FrameworkDelegate, activeViewCon } else if ( i < activeIndex && !nav.isPortal) { // this view comes before the active view // and it is not a portal then ensure it is hidden - toggleHidden(inactiveViewController.element, true, false); + toggleHidden(inactiveViewController.element, true); } + // TODO - review existing z index code! } return Promise.all(promises); } - export function fireViewWillLifecycles(enteringView: ViewController, leavingView: ViewController) { leavingView && leavingView.willLeave(!enteringView); enteringView && enteringView.willEnter(); diff --git a/packages/core/src/components/nav/transitions/transition.ios.ts b/packages/core/src/components/nav/transitions/transition.ios.ts index b4a2170cee..f76da51cb5 100644 --- a/packages/core/src/components/nav/transitions/transition.ios.ts +++ b/packages/core/src/components/nav/transitions/transition.ios.ts @@ -11,174 +11,198 @@ const CENTER = '0%'; const OFF_OPACITY = 0.8; const SHOW_BACK_BTN_CSS = 'show-back-button'; -// TODO - make sure this uses the `ion-page` logic from the md transition -// DO this later since the transition is broke as a joke anyway -// Dan B 1/9/2018 - export function buildIOSTransition(rootTransition: Transition, enteringView: ViewController, leavingView: ViewController, opts: AnimationOptions): Promise { - - rootTransition.enteringView = enteringView; - rootTransition.leavingView = leavingView; - - const isRTL = document.dir === 'rtl'; - const OFF_RIGHT = isRTL ? '-99.5%' : '99.5%'; - const OFF_LEFT = isRTL ? '33%' : '-33%'; - - rootTransition.duration(isDef(opts.duration) ? opts.duration : DURATION); - rootTransition.easing(isDef(opts.easing) ? opts.easing : EASING); - - - rootTransition.addElement(enteringView.element); - rootTransition.beforeRemoveClass('hide-page'); - - const backDirection = (opts.direction === 'back'); - + const componentReadyPromise: Promise[] = []; + // Let makes sure everything is hydrated and ready to animate if (enteringView) { - const enteringContent = rootTransition.create(); - enteringContent.addElement(enteringView.element.querySelectorAll('ion-header > *:not(ion-toolbar),ion-footer > *')); + componentReadyPromise.push((enteringView.element as any).componentOnReady()); + } + if (leavingView) { + componentReadyPromise.push((leavingView.element as any).componentOnReady()); + } - rootTransition.add(enteringContent); + return Promise.all(componentReadyPromise).then(() => { + // Cool we're all hydrated, and can do deep selector + rootTransition.enteringView = enteringView; + rootTransition.leavingView = leavingView; - if (backDirection) { - enteringContent.fromTo(TRANSLATEX, OFF_LEFT, CENTER, true).fromTo(OPACITY, OFF_OPACITY, 1, true); - } else { - // entering content, forward direction - enteringContent.beforeClearStyles([OPACITY]).fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true); - } + const isRTL = document.dir === 'rtl'; + const OFF_RIGHT = isRTL ? '-99.5%' : '99.5%'; + const OFF_LEFT = isRTL ? '33%' : '-33%'; - const enteringToolBarEle = enteringView.element.querySelector('ion-toolbar'); - if (enteringToolBarEle) { - const enteringToolBar = rootTransition.create(); - enteringToolBar.addElement(enteringToolBarEle); + rootTransition.duration(isDef(opts.duration) ? opts.duration : DURATION); + rootTransition.easing(isDef(opts.easing) ? opts.easing : EASING); - rootTransition.add(enteringToolBar); - const enteringTitle = rootTransition.create(); - enteringTitle.addElement(enteringToolBarEle.querySelector('ion-title')); - const enteringToolBarItems = rootTransition.create(); - enteringToolBarItems.addElement(enteringToolBarEle.querySelectorAll('ion-buttons,[menuToggle]')); - const enteringToolBarBg = rootTransition.create(); - enteringToolBarBg.addElement(enteringToolBarEle.querySelector('.toolbar-background')); - const enteringBackButton = rootTransition.create(); - enteringBackButton.addElement(enteringToolBarEle.querySelector('.back-button')); + rootTransition.addElement(enteringView.element); + rootTransition.beforeRemoveClass('hide-page'); - enteringToolBar - .add(enteringTitle) - .add(enteringToolBarItems) - .add(enteringToolBarBg) - .add(enteringBackButton); + const backDirection = (opts.direction === 'back'); - enteringTitle.fromTo(OPACITY, 0.01, 1, true); - enteringToolBarItems.fromTo(OPACITY, 0.01, 1, true); + // setting up enter view + if (enteringView) { + + const enteringContent = rootTransition.create(); + enteringContent.addElement(enteringView.element.querySelector('ion-content')); + enteringContent.addElement(enteringView.element.querySelectorAll('ion-header > *:not(ion-toolbar),ion-footer > *')); + rootTransition.add(enteringContent); if (backDirection) { - enteringTitle.fromTo(TRANSLATEX, OFF_LEFT, CENTER, true); - - if (canNavGoBack(enteringView.nav)) { - // back direction, entering page has a back button - enteringBackButton.beforeAddClass(SHOW_BACK_BTN_CSS).fromTo(OPACITY, 0.01, 1, true); - } + enteringContent + .beforeClearStyles([OPACITY]) + .fromTo(TRANSLATEX, OFF_LEFT, CENTER, true) + .fromTo(OPACITY, OFF_OPACITY, 1, true); } else { - // entering toolbar, forward direction - enteringTitle.fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true); + // entering content, forward direction + enteringContent + .beforeClearStyles([OPACITY]) + .fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true); - enteringToolBarBg.beforeClearStyles([OPACITY]).fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true); + } - if (canNavGoBack(enteringView.nav)) { - // forward direction, entering page has a back button - enteringBackButton.beforeAddClass(SHOW_BACK_BTN_CSS).fromTo(OPACITY, 0.01, 1, true); + const enteringToolBarEle = enteringView.element.querySelector('ion-toolbar'); + if (enteringToolBarEle) { + const enteringToolBar = rootTransition.create(); + enteringToolBar.addElement(enteringToolBarEle); + rootTransition.add(enteringToolBar); + const enteringTitle = rootTransition.create(); + enteringTitle.addElement(enteringToolBarEle.querySelector('ion-title')); - const enteringBackBtnText = rootTransition.create(); - enteringBackBtnText.addElement(enteringToolBarEle.querySelector('.back-button-text')); + const enteringToolBarItems = rootTransition.create(); + enteringToolBarItems.addElement(enteringToolBarEle.querySelectorAll('ion-buttons,[menuToggle]')); - enteringBackBtnText.fromTo(TRANSLATEX, (isRTL ? '-100px' : '100px'), '0px'); - enteringToolBar.add(enteringBackBtnText); + const enteringToolBarBg = rootTransition.create(); + enteringToolBarBg.addElement(enteringToolBarEle.querySelector('.toolbar-background')); + const enteringBackButton = rootTransition.create(); + enteringBackButton.addElement(enteringToolBarEle.querySelector('.back-button')); + + enteringToolBar + .add(enteringTitle) + .add(enteringToolBarItems) + .add(enteringToolBarBg) + .add(enteringBackButton); + + enteringTitle.fromTo(OPACITY, 0.01, 1, true); + enteringToolBarItems.fromTo(OPACITY, 0.01, 1, true); + + if (backDirection) { + enteringTitle.fromTo(TRANSLATEX, OFF_LEFT, CENTER, true); + + if (canNavGoBack(enteringView.nav, enteringView)) { + // back direction, entering page has a back button + enteringBackButton.beforeAddClass(SHOW_BACK_BTN_CSS).fromTo(OPACITY, 0.01, 1, true); + } } else { - enteringBackButton.beforeRemoveClass(SHOW_BACK_BTN_CSS); + // entering toolbar, forward direction + enteringTitle.fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true); + + enteringToolBarBg + .beforeClearStyles([OPACITY]) + .fromTo(TRANSLATEX, OFF_RIGHT, CENTER, true); + + if (canNavGoBack(enteringView.nav, enteringView)) { + + // forward direction, entering page has a back button + enteringBackButton + .beforeAddClass(SHOW_BACK_BTN_CSS) + .fromTo(OPACITY, 0.01, 1, true); + + + const enteringBackBtnText = rootTransition.create(); + enteringBackBtnText.addElement(enteringToolBarEle.querySelector('.back-button .button-text')); + + enteringBackBtnText.fromTo(TRANSLATEX, (isRTL ? '-100px' : '100px'), '0px'); + enteringToolBar.add(enteringBackBtnText); + } else { + enteringBackButton.beforeRemoveClass(SHOW_BACK_BTN_CSS); + } } } } - } - // setup leaving view - if (leavingView) { + // setup leaving view + if (leavingView) { - const leavingContent = rootTransition.create(); - leavingContent.addElement(leavingView.element); - leavingContent.addElement(leavingView.element.querySelectorAll('ion-header > *:not(ion-toolbar),ion-footer > *')); - - rootTransition.add(leavingContent); - - if (backDirection) { - // leaving content, back direction - leavingContent.beforeClearStyles([OPACITY]).fromTo(TRANSLATEX, CENTER, (isRTL ? '-100%' : '100%')); - - } else { - // leaving content, forward direction - leavingContent - .fromTo(TRANSLATEX, CENTER, OFF_LEFT) - .fromTo(OPACITY, 1, OFF_OPACITY) - .afterClearStyles([TRANSFORM, OPACITY]); - } - - const leavingToolBarEle = leavingView.element.querySelector('ion-toolbar'); - if (leavingToolBarEle) { - const leavingToolBar = rootTransition.create(); - leavingToolBar.addElement(leavingToolBarEle); - - const leavingTitle = rootTransition.create(); - leavingTitle.addElement(leavingToolBarEle.querySelector('ion-title')); - - const leavingToolBarItems = rootTransition.create(); - leavingToolBarItems.addElement(leavingToolBarEle.querySelectorAll('ion-buttons,[menuToggle]')); - - const leavingToolBarBg = rootTransition.create(); - leavingToolBarBg.addElement(leavingToolBarEle.querySelector('.toolbar-background')); - - const leavingBackButton = rootTransition.create(); - leavingBackButton.addElement(leavingToolBarEle.querySelector('.back-button')); - - leavingToolBar - .add(leavingTitle) - .add(leavingToolBarItems) - .add(leavingBackButton) - .add(leavingToolBarBg); - - rootTransition.add(leavingToolBar); - - // fade out leaving toolbar items - leavingBackButton.fromTo(OPACITY, 0.99, 0); - leavingTitle.fromTo(OPACITY, 0.99, 0); - leavingToolBarItems.fromTo(OPACITY, 0.99, 0); + const leavingContent = rootTransition.create(); + leavingContent.addElement(leavingView.element.querySelector('ion-content')); + leavingContent.addElement(leavingView.element.querySelectorAll('ion-header > *:not(ion-toolbar),ion-footer > *')); + rootTransition.add(leavingContent); if (backDirection) { - // leaving toolbar, back direction - leavingTitle.fromTo(TRANSLATEX, CENTER, (isRTL ? '-100%' : '100%')); - - // leaving toolbar, back direction, and there's no entering toolbar - // should just slide out, no fading out - leavingToolBarBg + // leaving content, back direction + leavingContent .beforeClearStyles([OPACITY]) .fromTo(TRANSLATEX, CENTER, (isRTL ? '-100%' : '100%')); - const leavingBackBtnText = rootTransition.create(); - leavingBackBtnText.addElement(leavingToolBarEle.querySelector('.back-button-text')); - leavingBackBtnText.fromTo(TRANSLATEX, CENTER, (isRTL ? -300 : 300) + 'px'); - leavingToolBar.add(leavingBackBtnText); } else { - // leaving toolbar, forward direction - leavingTitle - .fromTo(TRANSLATEX, CENTER, OFF_LEFT) - .afterClearStyles([TRANSFORM]); + // leaving content, forward direction + leavingContent + .fromTo(TRANSLATEX, CENTER, OFF_LEFT, true) + .fromTo(OPACITY, 1, OFF_OPACITY, true); + } - leavingBackButton.afterClearStyles([OPACITY]); - leavingTitle.afterClearStyles([OPACITY]); - leavingToolBarItems.afterClearStyles([OPACITY]); + const leavingToolBarEle = leavingView.element.querySelector('ion-toolbar'); + if (leavingToolBarEle) { + const leavingToolBar = rootTransition.create(); + leavingToolBar.addElement(leavingToolBarEle); + + const leavingTitle = rootTransition.create(); + leavingTitle.addElement(leavingToolBarEle.querySelector('ion-title')); + + const leavingToolBarItems = rootTransition.create(); + leavingToolBarItems.addElement(leavingToolBarEle.querySelectorAll('ion-buttons,[menuToggle]')); + + const leavingToolBarBg = rootTransition.create(); + leavingToolBarBg.addElement(leavingToolBarEle.querySelector('.toolbar-background')); + + const leavingBackButton = rootTransition.create(); + leavingBackButton.addElement(leavingToolBarEle.querySelector('.back-button')); + + leavingToolBar + .add(leavingTitle) + .add(leavingToolBarItems) + .add(leavingBackButton) + .add(leavingToolBarBg); + + rootTransition.add(leavingToolBar); + + // fade out leaving toolbar items + leavingBackButton.fromTo(OPACITY, 0.99, 0, true); + leavingTitle.fromTo(OPACITY, 0.99, 0, true); + leavingToolBarItems.fromTo(OPACITY, 0.99, 0, true); + + if (backDirection) { + // leaving toolbar, back direction + leavingTitle.fromTo(TRANSLATEX, CENTER, (isRTL ? '-100%' : '100%')); + + // leaving toolbar, back direction, and there's no entering toolbar + // should just slide out, no fading out + leavingToolBarBg + .beforeClearStyles([OPACITY]) + .fromTo(TRANSLATEX, CENTER, (isRTL ? '-100%' : '100%')); + + const leavingBackBtnText = rootTransition.create(); + leavingBackBtnText.addElement(leavingToolBarEle.querySelector('.back-button .button-text')); + leavingBackBtnText.fromTo(TRANSLATEX, CENTER, (isRTL ? -300 : 300) + 'px'); + leavingToolBar.add(leavingBackBtnText); + + } else { + // leaving toolbar, forward direction + leavingTitle + .fromTo(TRANSLATEX, CENTER, OFF_LEFT) + .afterClearStyles([TRANSFORM]); + + leavingBackButton.afterClearStyles([OPACITY]); + leavingTitle.afterClearStyles([OPACITY]); + leavingToolBarItems.afterClearStyles([OPACITY]); + } } } - } - return Promise.resolve(rootTransition); + + // Return the rootTransition promise + return rootTransition; + }); } diff --git a/packages/core/src/components/nav/transitions/transition.md.ts b/packages/core/src/components/nav/transitions/transition.md.ts index cc05c6166f..495cca6539 100644 --- a/packages/core/src/components/nav/transitions/transition.md.ts +++ b/packages/core/src/components/nav/transitions/transition.md.ts @@ -9,6 +9,15 @@ const SHOW_BACK_BTN_CSS = 'show-back-button'; export function buildMdTransition(rootTransition: Transition, enteringView: ViewController, leavingView: ViewController, opts: AnimationOptions): Promise { + const componentReadyPromise: Promise[] = []; + if (enteringView) { + componentReadyPromise.push((enteringView.element as any).componentOnReady()); + } + if (leavingView) { + componentReadyPromise.push((leavingView.element as any).componentOnReady()); + } + + return Promise.all(componentReadyPromise).then(() => { rootTransition.enteringView = enteringView; rootTransition.leavingView = leavingView; @@ -19,9 +28,12 @@ export function buildMdTransition(rootTransition: Transition, enteringView: View const backDirection = (opts.direction === 'back'); if (enteringView) { + + // animate the component itself if (backDirection) { rootTransition.duration(isDef(opts.duration) ? opts.duration : 200).easing('cubic-bezier(0.47,0,0.745,0.715)'); - } else { + } + else { rootTransition.duration(isDef(opts.duration) ? opts.duration : 280).easing('cubic-bezier(0.36,0.66,0.04,1)'); rootTransition @@ -29,8 +41,10 @@ export function buildMdTransition(rootTransition: Transition, enteringView: View .fromTo('opacity', 0.01, 1, true); } + // Animate toolbar if it's there const enteringToolbarEle = ionPageElement.querySelector('ion-toolbar'); if (enteringToolbarEle) { + const enteringToolBar = rootTransition.create(); enteringToolBar.addElement(enteringToolbarEle); rootTransition.add(enteringToolBar); @@ -38,8 +52,7 @@ export function buildMdTransition(rootTransition: Transition, enteringView: View const enteringBackButton = rootTransition.create(); enteringBackButton.addElement(enteringToolbarEle.querySelector('.back-button')); rootTransition.add(enteringBackButton); - - if (canNavGoBack(enteringView.nav)) { + if (canNavGoBack(enteringView.nav, enteringView)) { enteringBackButton.beforeAddClass(SHOW_BACK_BTN_CSS); } else { enteringBackButton.beforeRemoveClass(SHOW_BACK_BTN_CSS); @@ -56,7 +69,10 @@ export function buildMdTransition(rootTransition: Transition, enteringView: View rootTransition.add(leavingPage.fromTo(TRANSLATEY, CENTER, OFF_BOTTOM).fromTo('opacity', 1, 0)); } - return Promise.resolve(rootTransition); + return rootTransition; + + }); + } function getIonPageElement(element: HTMLElement) { diff --git a/packages/core/src/components/toolbar/toolbar.ios.scss b/packages/core/src/components/toolbar/toolbar.ios.scss index 4ea4784911..33d14b4bd7 100644 --- a/packages/core/src/components/toolbar/toolbar.ios.scss +++ b/packages/core/src/components/toolbar/toolbar.ios.scss @@ -299,33 +299,33 @@ // iOS Toolbar Back Button // -------------------------------------------------- -.back-button-ios { - @include margin(0); - - z-index: $z-index-toolbar-buttons; - overflow: visible; - - order: map-get($toolbar-order-ios, back-button); - - min-height: 32px; - - line-height: 1; - transform: translateZ(0); -} - -.back-button-icon-ios { - @include margin(-1px, 0, 0, 0); - - display: inherit; - - min-width: 18px; - - font-size: 34px; -} - -.back-button-text-ios { - letter-spacing: -.01em; -} +// .back-button-ios { +// @include margin(0); +// +// z-index: $z-index-toolbar-buttons; +// overflow: visible; +// +// order: map-get($toolbar-order-ios, back-button); +// +// min-height: 32px; +// +// line-height: 1; +// transform: translateZ(0); +// } +// +// .back-button-icon-ios { +// @include margin(-1px, 0, 0, 0); +// +// display: inherit; +// +// min-width: 18px; +// +// font-size: 34px; +// } +// +// .back-button-text-ios { +// letter-spacing: -.01em; +// } // iOS Toolbar Menu Toggle diff --git a/packages/core/src/components/toolbar/toolbar.scss b/packages/core/src/components/toolbar/toolbar.scss index eb3cf4f5f4..bb6d2daf31 100644 --- a/packages/core/src/components/toolbar/toolbar.scss +++ b/packages/core/src/components/toolbar/toolbar.scss @@ -130,20 +130,3 @@ ion-buttons, align-items: center; } - -// Back Button -// -------------------------------------------------- - -.back-button { - display: none; -} - -.back-button.show-back-button { - display: inline-block; -} - -.back-button-text { - display: flex; - - align-items: center; -} diff --git a/packages/core/src/global/platform-utils.ts b/packages/core/src/global/platform-utils.ts index 2efc0ae4e4..af851ccea2 100644 --- a/packages/core/src/global/platform-utils.ts +++ b/packages/core/src/global/platform-utils.ts @@ -1,5 +1,5 @@ export function isCordova(): boolean { const win = window as any; - return !!(win['cordova'] || win['PhoneGap'] || win['phonegap']); + return !!(win['cordova'] || win['PhoneGap'] || win['phonegap'] || win['Capacitor']); }