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
This commit is contained in:
Mike Hartington
2018-02-09 13:03:26 -05:00
committed by Manu MA
parent d7e0f0076e
commit 77e16bbc3f
21 changed files with 356 additions and 292 deletions

View File

@ -312,7 +312,7 @@ declare global {
}
namespace JSXElements {
export interface IonBackButtonAttributes extends HTMLAttributes {
mode?: 'ios' | 'md';
}
}
}

View File

@ -1,5 +0,0 @@
@import "./back-button";
@import "./back-button.ios.vars";
// iOS Back Button
// --------------------------------------------------

View File

@ -1,4 +0,0 @@
@import "../../themes/ionic.globals.ios";
// iOS Back Button
// --------------------------------------------------

View File

@ -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;
}

View File

@ -1,4 +0,0 @@
@import "../../themes/ionic.globals.md";
// Material Design Back Button
// --------------------------------------------------

View File

@ -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 {

View File

@ -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 (
<ion-nav-pop>
<slot />
</ion-nav-pop>
);
} else if (!this.custom) {
return (
<ion-nav-pop>
<ion-button color={buttonColor}>
<ion-icon name={backButtonIcon} slot='start' />
{backButtonText}
</ion-button>
</ion-nav-pop>
);
} else {
return undefined;
}
return (
<ion-nav-pop>
<button>
<span class={iconClass}>
<slot name='icon'>
<ion-icon name={iconName}></ion-icon>
</slot>
</span>
<span class={textClass}>
<slot name='text'>
{text}
</slot>
</span>
</button>
</ion-nav-pop>
);
}
}

View File

@ -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
<ion-page>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
</ion-page>
```
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
<ion-page>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button>
<ion-button>
Button Text
<ion-icon name="add" slot="start"></ion-icon>
</ion-button>
</ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
</ion-page>
```
Or no button text at all:
```html
<ion-page>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button>
<ion-button>
<ion-icon name="add" slot="icon-only"></ion-icon>
</ion-button>
</ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
</ion-page>
```
<!-- Auto Generated Below -->
## 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).
----------------------------------------------

View File

@ -35,6 +35,9 @@
firstPage.innerHTML = `
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Page One</ion-title>
</ion-toolbar>
</ion-header>
@ -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 @@
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button>
</ion-back-button>
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Page Two</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<h1>Page Two</h1>
<p>Just an empty <code>ion-back-button</code></p>
<ion-button class="next">Go to Page Three</ion-button>
</ion-content>
`;
@ -89,6 +92,9 @@
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button>
<ion-button>
<ion-icon name="add" slot="icon-only"></ion-icon>
</ion-button>
</ion-back-button>
</ion-buttons>
<ion-title>Page Three</ion-title>
@ -96,6 +102,7 @@
</ion-header>
<ion-content padding>
<h1>Page Three</h1>
<p>Custom back button</p>
</ion-content>
`;
@ -103,10 +110,10 @@
await nav.push(thirdPage);
}
</script>
<style>
ion-back-button {
height: 50px;
background-color: blue;
}
</style>
<!-- <style> -->
<!-- ion&#45;back&#45;button { -->
<!-- height: 50px; -->
<!-- background&#45;color: blue; -->
<!-- } -->
<!-- </style> -->
</html>

View File

@ -134,7 +134,7 @@ export class Button {
<span class='button-inner'>
<slot name='icon-only'></slot>
<slot name='start'></slot>
<slot></slot>
<span class='button-text'><slot></slot></span>
<slot name='end'></slot>
</span>
{ this.mode === 'md' && <ion-ripple-effect useTapClick={true} /> }

View File

@ -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 {

View File

@ -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 {

View File

@ -13,7 +13,10 @@ ion-nav {
width: 100%;
height: 100%;
background-color: black;
contain: layout size style;
}
.ion-page {

View File

@ -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<void> {
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<any> {
if (nav.destroyed) {
return Promise.resolve();
}
const activeIndex = nav.views.indexOf(activeViewController);
const promises: Promise<any>[] = [];
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();

View File

@ -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<Transition> {
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<any>[] = [];
// 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;
});
}

View File

@ -9,6 +9,15 @@ const SHOW_BACK_BTN_CSS = 'show-back-button';
export function buildMdTransition(rootTransition: Transition, enteringView: ViewController, leavingView: ViewController, opts: AnimationOptions): Promise<Transition> {
const componentReadyPromise: Promise<any>[] = [];
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) {

View File

@ -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

View File

@ -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;
}

View File

@ -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']);
}