From e404b19733bcd5b5e6d995a019911f796977825b Mon Sep 17 00:00:00 2001 From: mhartington Date: Tue, 8 Aug 2017 14:55:27 -0400 Subject: [PATCH] feat(popover): add initial animation --- packages/core/demos/popover/basic.html | 1 + .../popover/animations/ios.enter.ts | 19 +-- .../popover/animations/ios.leave.ts | 15 +- .../src/components/popover/popover.ios.scss | 85 ++++++++++-- .../src/components/popover/popover.md.scss | 14 +- .../core/src/components/popover/popover.scss | 21 +-- .../core/src/components/popover/popover.tsx | 129 +++++++++--------- .../src/components/popover/popover.wp.scss | 49 +++++-- 8 files changed, 209 insertions(+), 124 deletions(-) diff --git a/packages/core/demos/popover/basic.html b/packages/core/demos/popover/basic.html index 6fc0328ea8..641f812e21 100644 --- a/packages/core/demos/popover/basic.html +++ b/packages/core/demos/popover/basic.html @@ -21,6 +21,7 @@ component: 'profile-page', ev: clickEvt }).then(popover => { + console.log(popover) popover.present() }); }); diff --git a/packages/core/src/components/popover/animations/ios.enter.ts b/packages/core/src/components/popover/animations/ios.enter.ts index 81d410085a..d0bd9caf2a 100644 --- a/packages/core/src/components/popover/animations/ios.enter.ts +++ b/packages/core/src/components/popover/animations/ios.enter.ts @@ -1,23 +1,26 @@ -import { Animation } from '../../../index'; +import { Animation, PopoverOptions } from '../../../index'; -export default function(Animation: Animation, baseElm: HTMLElement) { +export default function popoverEnter( + Animation: Animation, + baseElm: HTMLElement, + evtSource: Event +) { const baseAnimation = new Animation(); const backdropAnimation = new Animation(); + backdropAnimation.addElement(baseElm.querySelector('.popover-backdrop')); const wrapperAnimation = new Animation(); wrapperAnimation.addElement(baseElm.querySelector('.popover-wrapper')); - backdropAnimation.fromTo('opacity', 0.01, 0.3); - - wrapperAnimation.fromTo('opacity', 0.01, 1) - .fromTo('scale', 1.1, 1); + wrapperAnimation.fromTo('opacity', 0.01, 1); + backdropAnimation.fromTo('opacity', 0.01, 0.08); return baseAnimation .addElement(baseElm) - .easing('ease-in-out') - .duration(200) + .easing('ease') + .duration(100) .add(backdropAnimation) .add(wrapperAnimation); } diff --git a/packages/core/src/components/popover/animations/ios.leave.ts b/packages/core/src/components/popover/animations/ios.leave.ts index 548f4555c6..000b3422d2 100644 --- a/packages/core/src/components/popover/animations/ios.leave.ts +++ b/packages/core/src/components/popover/animations/ios.leave.ts @@ -7,22 +7,19 @@ export default function(Animation: Animation, baseElm: HTMLElement) { const baseAnimation = new Animation(); const backdropAnimation = new Animation(); - backdropAnimation.addElement(baseElm.querySelector('.modal-backdrop')); + backdropAnimation.addElement(baseElm.querySelector('.popover-backdrop')); const wrapperAnimation = new Animation(); - const wrapperElm = baseElm.querySelector('.modal-wrapper'); - wrapperAnimation.addElement(wrapperElm); - const wrapperElmRect = wrapperElm.getBoundingClientRect(); + const wrapperElm = baseElm.querySelector('.popover-wrapper'); - wrapperAnimation.beforeStyles({ 'opacity': 1 }) - .fromTo('translateY', '0%', `${window.innerHeight - wrapperElmRect.top}px`); + wrapperAnimation.fromTo('opacity', 0.99, 0); + backdropAnimation.fromTo('opacity', 0.08, 0); - backdropAnimation.fromTo('opacity', 0.4, 0.0); return baseAnimation .addElement(baseElm) - .easing('ease-out') - .duration(250) + .easing('ease') + .duration(500) .add(backdropAnimation) .add(wrapperAnimation); } diff --git a/packages/core/src/components/popover/popover.ios.scss b/packages/core/src/components/popover/popover.ios.scss index 30a48e7da9..5e07da496f 100644 --- a/packages/core/src/components/popover/popover.ios.scss +++ b/packages/core/src/components/popover/popover.ios.scss @@ -1,24 +1,81 @@ @import "../../themes/ionic.globals.ios"; -@import "./modal"; +@import "./popover"; - -// iOS Modals +// iOS Popover // -------------------------------------------------- -/// @prop - Background color for the modal -$modal-ios-background-color: $background-ios-color !default; +/// @prop - Width of the popover content +$popover-ios-width: 200px !default; -/// @prop - Border radius for the modal -$modal-ios-border-radius: 10px !default; +/// @prop - Min width of the popover content +$popover-ios-min-width: 0 !default; + +/// @prop - Minimum height of the popover content +$popover-ios-min-height: 0 !default; + +/// @prop - Maximum height of the popover content +$popover-ios-max-height: 90% !default; + +/// @prop - Border radius of the popover content +$popover-ios-border-radius: 10px !default; + +/// @prop - Text color of the popover content +$popover-ios-text-color: $text-ios-color !default; + +/// @prop - Background of the popover content +$popover-ios-background: $background-ios-color !default; + +/// @prop - Background of the popover arrow +$popover-ios-arrow-background: $popover-ios-background !default; -.modal-wrapper-ios { - // hidden by default to prevent flickers, the animation will show it - @include transform(translate3d(0, 100%, 0)); +.popover-ios .popover-content { + @include border-radius($popover-ios-border-radius); - @media only screen and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-small) { - @include border-radius($modal-ios-border-radius); + width: $popover-ios-width; + min-width: $popover-ios-min-width; + min-height: $popover-ios-min-height; + max-height: $popover-ios-max-height; - overflow: hidden; - } + color: $popover-ios-text-color; + background: $popover-ios-background; } + + +// Popover Arrow +// ----------------------------------------- + +.popover-ios .popover-arrow { + position: absolute; + display: block; + + overflow: hidden; + + width: 20px; + height: 10px; +} + +.popover-ios .popover-arrow::after { + @include position(3px, null, null, 3px); + @include border-radius(3px); + + position: absolute; + + z-index: $z-index-overlay-wrapper; + + width: 14px; + height: 14px; + + background-color: $popover-ios-arrow-background; + content: ""; + transform: rotate(45deg); +} + +.popover-ios.popover-bottom .popover-arrow { + top: auto; + bottom: -10px; +} + +.popover-ios.popover-bottom .popover-arrow::after { + top: -6px; +} \ No newline at end of file diff --git a/packages/core/src/components/popover/popover.md.scss b/packages/core/src/components/popover/popover.md.scss index aaeb75a9de..572f5405ea 100644 --- a/packages/core/src/components/popover/popover.md.scss +++ b/packages/core/src/components/popover/popover.md.scss @@ -1,5 +1,6 @@ -@import "../../themes/ionic.globals"; +@import "../../themes/ionic.globals.md"; @import "./popover"; + // Material Design Popover // -------------------------------------------------- @@ -19,12 +20,10 @@ $popover-md-max-height: 90% !default; $popover-md-border-radius: 2px !default; /// @prop - Text color of the popover content -// $popover-md-text-color: $text-md-color !default; -$popover-md-text-color: black !default; +$popover-md-text-color: $text-md-color !default; /// @prop - Background of the popover content -// $popover-md-background: $background-md-color !default; -$popover-md-background: black !default; +$popover-md-background: $background-md-color !default; /// @prop - Box shadow color of the popover content $popover-md-box-shadow-color: rgba(0, 0, 0, .3) !default; @@ -43,12 +42,11 @@ $popover-md-box-shadow: 0 3px 12px 2px $popover-md-box-shadow-col max-height: $popover-md-max-height; color: $popover-md-text-color; - // background: $popover-md-background; - background: #ffffff; + background: $popover-md-background; box-shadow: $popover-md-box-shadow; } .popover-md .popover-viewport { opacity: 0; transition-delay: 100ms; -} +} \ No newline at end of file diff --git a/packages/core/src/components/popover/popover.scss b/packages/core/src/components/popover/popover.scss index 721af8564d..8785d6967a 100644 --- a/packages/core/src/components/popover/popover.scss +++ b/packages/core/src/components/popover/popover.scss @@ -3,6 +3,7 @@ // Popover // -------------------------------------------------- + ion-popover { @include position(0, 0, 0, 0); @@ -14,25 +15,12 @@ ion-popover { align-items: center; justify-content: center; - - .popover-backdrop { - left: 0; - top: 0; - position: absolute; - bottom: 0px; - z-index: 2; - display: block; - width: 100%; - background-color: #000; - opacity: 0.3; - } } .popover-wrapper { z-index: $z-index-overlay-wrapper; - // opacity: 0; - opacity: 1; + opacity: 0; } .popover-content { @@ -46,10 +34,11 @@ ion-popover { flex-direction: column; } -.popover-content ion-content, .popover-content .scroll-content { +.popover-content ion-content, +.popover-content .scroll-content { contain: none; } .popover-content .scroll-content { position: relative; -} +} \ No newline at end of file diff --git a/packages/core/src/components/popover/popover.tsx b/packages/core/src/components/popover/popover.tsx index 03d0a108f8..eb0efe7e56 100644 --- a/packages/core/src/components/popover/popover.tsx +++ b/packages/core/src/components/popover/popover.tsx @@ -1,17 +1,23 @@ -import { Component, Element, Event, EventEmitter, Listen, Prop } from '@stencil/core'; -import { AnimationBuilder, Animation } from '../../index'; +import { + Component, + Element, + Event, + EventEmitter, + Listen, + Prop +} from '@stencil/core'; +import { AnimationBuilder, Animation, Ionic } from '../../index'; import { createThemedClasses } from '../../utils/theme'; import iOSEnterAnimation from './animations/ios.enter'; import iOSLeaveAnimation from './animations/ios.leave'; - @Component({ tag: 'ion-popover', styleUrls: { - // ios: 'popover.ios.scss', + ios: 'popover.ios.scss', md: 'popover.md.scss', - // wp: 'popover.wp.scss' + wp: 'popover.wp.scss' }, host: { theme: 'popover' @@ -39,8 +45,6 @@ export class Popover { @Prop() id: string; @Prop() showBackdrop: boolean = true; - - private animation: Animation; @Listen('ionDismiss') @@ -69,50 +73,49 @@ export class Popover { this.ionPopoverWillPresent.emit({ popover: this }); // get the user's animation fn if one was provided - // let animationBuilder = this.enterAnimation - // ? this.enterAnimation - // : iOSEnterAnimation; + let animationBuilder = this.enterAnimation + ? this.enterAnimation + : iOSEnterAnimation; // // build the animation and kick it off - // this.animation = animationBuilder(this.el); - - // this.animation.onFinish((a: any) => { - // a.destroy(); - // this.ionPopoverDidPresent.emit({ popover: this }); - resolve(); - // }).play(); + Ionic.controller('animation').then(Animation => { + this.animation = animationBuilder(Animation, this.el, this.ev); + this.animation + .onFinish((a: any) => { + a.destroy(); + this.ionPopoverDidPresent.emit({ popover: this }); + resolve(); + }) + .play(); + }); } dismiss() { - // if (this.animation) { - // this.animation.destroy(); - // this.animation = null; - // } - + if (this.animation) { + this.animation.destroy(); + this.animation = null; + } return new Promise(resolve => { this.ionPopoverWillDismiss.emit({ popover: this }); - // get the user's animation fn if one was provided - // let animationBuilder = this.exitAnimation; - // - // if (!animationBuilder) { - // // user did not provide a custom animation fn - // // decide from the config which animation to use - // // TODO!! - // animationBuilder = iOSLeaveAnimation; - // } + let animationBuilder = this.exitAnimation + ? this.exitAnimation + : iOSLeaveAnimation; // build the animation and kick it off - // this.animation = animationBuilder(this.el); - // this.animation.onFinish((a: any) => { - // a.destroy(); - this.ionPopoverDidDismiss.emit({ popover: this }); - - Core.dom.write(() => { - this.el.parentNode.removeChild(this.el); - }); - resolve(); - // }).play(); + Ionic.controller('animation').then(Animation => { + this.animation = animationBuilder(Animation, this.el); + this.animation + .onFinish((a: any) => { + a.destroy(); + this.ionPopoverDidDismiss.emit({ popover: this }); + Core.dom.write(() => { + this.el.parentNode.removeChild(this.el); + }); + resolve(); + }) + .play(); + }); }); } @@ -137,32 +140,37 @@ export class Popover { userCssClasses += ` ${this.cssClass}`; } - const dialogClasses = createThemedClasses(this.mode, this.color, 'popover-wrapper'); - const thisComponentClasses = createThemedClasses(this.mode, this.color, userCssClasses); + const dialogClasses = createThemedClasses( + this.mode, + this.color, + 'popover-wrapper' + ); + const thisComponentClasses = createThemedClasses( + this.mode, + this.color, + userCssClasses + ); return [ -
, -