feat(): add backdrop and update action-sheet animations

This commit is contained in:
mhartington
2017-08-07 15:33:03 -04:00
parent ea95cc0947
commit abdf9ff320
14 changed files with 311 additions and 209 deletions

View File

@ -28,11 +28,14 @@
console.log('Destructive clicked'); console.log('Destructive clicked');
} }
}, { }, {
icon: 'trash',
text: 'Archive', text: 'Archive',
handler: () => { handler: () => {
console.log('Archive clicked'); console.log('Archive clicked');
return false
} }
}, { }, {
icon: 'close',
text: 'Cancel', text: 'Cancel',
role: 'cancel', role: 'cancel',
handler: () => { handler: () => {

View File

@ -0,0 +1,158 @@
@import "../../themes/ionic.globals.md";
@import "./action-sheet";
// Material Design Action Sheet
// --------------------------------------------------
/// @prop - Text align of the action sheet
$action-sheet-md-text-align: start !default;
/// @prop - Background color of the action sheet
$action-sheet-md-background: #fafafa !default;
/// @prop - Bottom margin of the action sheet button group
$action-sheet-md-group-margin-bottom: 8px !default;
/// @prop - Color of the action sheet title
$action-sheet-md-title-color: #757575 !default;
/// @prop - Font size of the action sheet title
$action-sheet-md-title-font-size: 1.6rem !default;
// deprecated
$action-sheet-md-title-padding: null !default;
/// @prop - Padding top of the action sheet title
$action-sheet-md-title-padding-top: 11px !default;
/// @prop - Padding end of the action sheet title
$action-sheet-md-title-padding-end: 16px !default;
/// @prop - Padding bottom of the action sheet title
$action-sheet-md-title-padding-bottom: 17px !default;
/// @prop - Padding start of the action sheet title
$action-sheet-md-title-padding-start: $action-sheet-md-title-padding-end !default;
/// @prop - Minimum height of the action sheet button
$action-sheet-md-button-min-height: 4.8rem !default;
/// @prop - Text color of the action sheet button
$action-sheet-md-button-text-color: #222 !default;
/// @prop - Font size of the action sheet button
$action-sheet-md-button-font-size: 1.6rem !default;
// deprecated
$action-sheet-md-button-padding: null !default;
/// @prop - Padding top of the action sheet button
$action-sheet-md-button-padding-top: 0 !default;
/// @prop - Padding end of the action sheet button
$action-sheet-md-button-padding-end: 16px !default;
/// @prop - Padding bottom of the action sheet button
$action-sheet-md-button-padding-bottom: $action-sheet-md-button-padding-top !default;
/// @prop - Padding start of the action sheet button
$action-sheet-md-button-padding-start: $action-sheet-md-button-padding-end !default;
/// @prop - Background color of the action sheet button
$action-sheet-md-button-background: transparent !default;
/// @prop - Background color of the action sheet activated button
$action-sheet-md-button-background-activated: #f1f1f1 !default;
/// @prop - Font size of the icon in the action sheet button
$action-sheet-md-icon-font-size: 2.4rem !default;
/// @prop - Width of the icon in the action sheet button
$action-sheet-md-icon-width: 2.3rem !default;
/// @prop - Text align of the icon in the action sheet button
$action-sheet-md-icon-text-align: center !default;
/// @prop - Vertical align of the icon in the action sheet button
$action-sheet-md-icon-vertical-align: middle !default;
// deprecated
$action-sheet-md-icon-margin: null !default;
/// @prop - Margin top of the icon in the action sheet button
$action-sheet-md-icon-margin-top: 0 !default;
/// @prop - Margin end of the icon in the action sheet button
$action-sheet-md-icon-margin-end: 32px !default;
/// @prop - Margin bottom of the icon in the action sheet button
$action-sheet-md-icon-margin-bottom: 0 !default;
/// @prop - Margin start of the icon in the action sheet button
$action-sheet-md-icon-margin-start: 0 !default;
.action-sheet-md .action-sheet-container {
@include padding(.8rem, 0);
background: $action-sheet-md-background;
}
.action-sheet-md .action-sheet-title,
.action-sheet-md .action-sheet-sub-title {
@include text-align($action-sheet-md-text-align);
font-size: $action-sheet-md-title-font-size;
color: $action-sheet-md-title-color;
@include deprecated-variable(padding, $action-sheet-md-title-padding) {
@include padding($action-sheet-md-title-padding-top, $action-sheet-md-title-padding-end, $action-sheet-md-title-padding-bottom, $action-sheet-md-title-padding-start);
}
}
.action-sheet-md .action-sheet-button {
@include text-align($action-sheet-md-text-align);
position: relative;
overflow: hidden;
min-height: $action-sheet-md-button-min-height;
font-size: $action-sheet-md-button-font-size;
color: $action-sheet-md-button-text-color;
background: $action-sheet-md-button-background;
@include deprecated-variable(padding, $action-sheet-md-button-padding) {
@include padding($action-sheet-md-button-padding-top, $action-sheet-md-button-padding-end, $action-sheet-md-button-padding-bottom, $action-sheet-md-button-padding-start);
}
}
.action-sheet-md .action-sheet-button.activated {
background: $action-sheet-md-button-background-activated;
}
.action-sheet-md .action-sheet-icon {
@include padding(0);
@include text-align($action-sheet-md-icon-text-align);
width: $action-sheet-md-icon-width;
font-size: $action-sheet-md-icon-font-size;
vertical-align: $action-sheet-md-icon-vertical-align;
@include deprecated-variable(margin, $action-sheet-md-icon-margin) {
@include margin($action-sheet-md-icon-margin-top, $action-sheet-md-icon-margin-end, $action-sheet-md-icon-margin-bottom, $action-sheet-md-icon-margin-start);
}
}
.action-sheet-md .action-sheet-group {
overflow: hidden;
}
.action-sheet-md .action-sheet-group .button-inner {
justify-content: flex-start;
}
.action-sheet-md .action-sheet-selected {
font-weight: bold;
}

View File

@ -0,0 +1,38 @@
@import "../../themes/ionic.globals";
// Action Sheet
// --------------------------------------------------
/// @prop - Width of the action sheet
$action-sheet-width: 100% !default;
/// @prop - Maximum width of the action sheet
$action-sheet-max-width: 500px !default;
ion-action-sheet {
@include position(0, null, null, 0);
position: absolute;
z-index: $z-index-overlay;
display: block;
width: $action-sheet-width;
height: $action-sheet-width;
}
.action-sheet-wrapper {
@include position(null, 0, 0, 0);
@include margin(auto);
@include transform(translate3d(0, 100%, 0));
position: absolute;
z-index: $z-index-overlay-wrapper;
display: block;
width: $action-sheet-width;
max-width: $action-sheet-max-width;
}
.action-sheet-button {
width: $action-sheet-width;
}

View File

@ -7,18 +7,18 @@ import {
Prop, Prop,
State State
} from '@stencil/core'; } from '@stencil/core';
import { AnimationBuilder, Animation } from '../../index'; import { AnimationBuilder, Animation, Ionic } from '../../index';
import iOSEnterAnimation from './animations/ios.enter'; import iOSEnterAnimation from './animations/ios.enter';
import iOSLeaveAnimation from './animations/ios.leave'; import iOSLeaveAnimation from './animations/ios.leave';
@Component({ @Component({
tag: 'ion-action-sheet', tag: 'ion-action-sheet',
// styleUrls: { styleUrls: {
// ios: 'action-sheet.ios.scss', // ios: 'action-sheet.ios.scss',
// md: 'action-sheet.md.scss', md: 'action-sheet.md.scss'
// wp: 'action-sheet.wp.scss' // wp: 'action-sheet.wp.scss'
// }, },
host: { host: {
theme: 'action-sheet' theme: 'action-sheet'
} }
@ -66,53 +66,54 @@ export class ActionSheet {
} }
private _present(resolve: Function) { private _present(resolve: Function) {
// if (this.animation) { if (this.animation) {
// this.animation.destroy(); this.animation.destroy();
// this.animation = null; this.animation = null;
// } }
this.ionActionSheetWillPresent.emit({ actionsheet: this }); this.ionActionSheetWillPresent.emit({ actionsheet: this });
// let animationBuilder = this.enterAnimation let animationBuilder = this.enterAnimation
// ? this.enterAnimation ? this.enterAnimation
// : iOSEnterAnimation; : iOSEnterAnimation;
// build the animation and kick it off // build the animation and kick it off
// this.animation = animationBuilder(this.el); Ionic.controller('animation').then(Animation => {
this.animation = animationBuilder(Animation, this.el);
// this.animation.onFinish((a: any) => { this.animation
// a.destroy(); .onFinish((a: any) => {
// this.ionViewDidLoad(); a.destroy();
resolve(); this.ionActionSheetDidLoad.emit({ actionsheet: this });
// }).play(); resolve();
})
.play();
});
} }
dismiss() { dismiss() {
// if (this.animation) {
// if (this.animation) { this.animation.destroy();
// this.animation.destroy(); this.animation = null;
// this.animation = null; }
// }
return new Promise<void>(resolve => { return new Promise<void>(resolve => {
this.ionActionSheetWillDismiss.emit({ actionsheet: this }); this.ionActionSheetWillDismiss.emit({ actionsheet: this });
let animationBuilder = this.exitAnimation
? this.exitAnimation
// let animationBuilder = this.exitAnimation : iOSLeaveAnimation;
// ? this.exitAnimation
// : iOSLeaveAnimation;
// build the animation and kick it off // build the animation and kick it off
// this.animation = animationBuilder(this.el); Ionic.controller('animation').then(Animation => {
// this.animation.onFinish((a: any) => { this.animation = animationBuilder(Animation, this.el);
// a.destroy(); this.animation
this.ionActionSheetDidDismiss.emit({ actionsheet: this }); .onFinish((a: any) => {
a.destroy();
Core.dom.write(() => { this.ionActionSheetDidDismiss.emit({ actionsheet: this });
this.el.parentNode.removeChild(this.el); Core.dom.write(() => {
this.el.parentNode.removeChild(this.el);
});
resolve();
})
.play();
}); });
resolve();
// }).play();
}); });
} }
@ -129,18 +130,27 @@ export class ActionSheet {
} }
} }
click(button: ActionSheetButtons) {
let shouldDismiss = true;
if (button.handler) {
if (button.handler() === false) {
shouldDismiss = false;
}
}
if (shouldDismiss) {
this.dismiss();
}
}
render() { render() {
let userCssClass = 'action-sheet-content'; let userCssClass = 'action-sheet-content';
if (this.cssClass) { if (this.cssClass) {
userCssClass += ' ' + this.cssClass; userCssClass += ' ' + this.cssClass;
} }
return [ return [
<div <ion-backdrop
onClick={this.backdropClick.bind(this)} onClick={this.backdropClick.bind(this)}
class={{ class="action-sheet-backdrop"
'action-sheet-backdrop': true,
'hide-backdrop': !this.showBackdrop
}}
/>, />,
<div class="action-sheet-wrapper" role="dialog"> <div class="action-sheet-wrapper" role="dialog">
<div class="action-sheet-container"> <div class="action-sheet-container">
@ -152,7 +162,12 @@ export class ActionSheet {
? <div class="action-sheet-sub-title">{this.subTitle}</div> ? <div class="action-sheet-sub-title">{this.subTitle}</div>
: null} : null}
{this.buttons.map(b => {this.buttons.map(b =>
<ion-button onClick={() => b.handler()}>{b.text}</ion-button> <button class="action-sheet-button" onClick={() => this.click(b)}>
{b.icon
? <ion-icon name={b.icon} class="action-sheet-icon" />
: null}
{b.text}
</button>
)} )}
</div> </div>
</div> </div>

View File

@ -1,110 +0,0 @@
@import "../../themes/ionic.globals.md";
@import "./loading";
// Material Design Loading Indicator
// --------------------------------------------------
// deprecated
$loading-md-padding: null !default;
/// @prop - Padding top of the loading wrapper
$loading-md-padding-top: 24px !default;
/// @prop - Padding end of the loading wrapper
$loading-md-padding-end: $loading-md-padding-top !default;
/// @prop - Padding bottom of the loading wrapper
$loading-md-padding-bottom: $loading-md-padding-top !default;
/// @prop - Padding start of the loading wrapper
$loading-md-padding-start: $loading-md-padding-end !default;
/// @prop - Max width of the loading wrapper
$loading-md-max-width: 280px !default;
/// @prop - Maximum height of the loading wrapper
$loading-md-max-height: 90% !default;
/// @prop - Border radius of the loading wrapper
$loading-md-border-radius: 2px !default;
/// @prop - Text color of the loading wrapper
$loading-md-text-color: rgba(0, 0, 0, .5) !default;
/// @prop - Background of the loading wrapper
$loading-md-background: #fafafa !default;
/// @prop - Box shadow color of the loading wrapper
$loading-md-box-shadow-color: rgba(0, 0, 0, .4) !default;
/// @prop - Box shadow of the loading wrapper
$loading-md-box-shadow: 0 16px 20px $loading-md-box-shadow-color !default;
/// @prop - Color of the loading spinner
$loading-md-spinner-color: color($colors-md, primary) !default;
/// @prop - Color of the ios loading spinner
$loading-md-spinner-ios-color: $loading-md-spinner-color !default;
/// @prop - Color of the bubbles loading spinner
$loading-md-spinner-bubbles-color: $loading-md-spinner-color !default;
/// @prop - Color of the circles loading spinner
$loading-md-spinner-circles-color: $loading-md-spinner-color !default;
/// @prop - Color of the crescent loading spinner
$loading-md-spinner-crescent-color: $loading-md-spinner-color !default;
/// @prop - Color of the dots loading spinner
$loading-md-spinner-dots-color: $loading-md-spinner-color !default;
.loading-md .loading-wrapper {
@include border-radius($loading-md-border-radius);
max-width: $loading-md-max-width;
max-height: $loading-md-max-height;
color: $loading-md-text-color;
background: $loading-md-background;
box-shadow: $loading-md-box-shadow;
@include deprecated-variable(padding, $loading-md-padding) {
@include padding($loading-md-padding-top, $loading-md-padding-end, $loading-md-padding-bottom, $loading-md-padding-start);
}
}
// Material Design Loading Content
// -----------------------------------------
.loading-md .loading-spinner + .loading-content {
@include margin-horizontal(16px, null);
}
// Material Design Loading Spinner fill colors
// -----------------------------------------
.loading-md .spinner-ios line,
.loading-md .spinner-ios-small line {
stroke: $loading-md-spinner-ios-color;
}
.loading-md .spinner-bubbles circle {
fill: $loading-md-spinner-bubbles-color;
}
.loading-md .spinner-circles circle {
fill: $loading-md-spinner-circles-color;
}
.loading-md .spinner-crescent circle {
stroke: $loading-md-spinner-crescent-color;
}
.loading-md .spinner-dots circle {
fill: $loading-md-spinner-dots-color;
}

View File

@ -1,37 +0,0 @@
@import "../../themes/ionic.globals";
// Loading Indicator
// --------------------------------------------------
ion-loading {
@include position(0, 0, 0, 0);
position: absolute;
z-index: $z-index-overlay;
display: flex;
align-items: center;
justify-content: center;
contain: strict;
}
ion-loading ion-gesture {
display: block;
width: 100%;
height: 100%;
visibility: inherit;
}
.loading-wrapper {
z-index: $z-index-overlay-wrapper;
display: flex;
align-items: center;
opacity: 0;
}

View File

@ -7,20 +7,19 @@ export default function(Animation: Animation, baseElm: HTMLElement) {
const baseAnimation = new Animation(); const baseAnimation = new Animation();
const backdropAnimation = new Animation(); const backdropAnimation = new Animation();
backdropAnimation.addElement(baseElm.querySelector('.loading-backdrop')); backdropAnimation.addElement(baseElm.querySelector('.action-sheet-backdrop'));
const wrapperAnimation = new Animation(); const wrapperAnimation = new Animation();
wrapperAnimation.addElement(baseElm.querySelector('.loading-wrapper')); wrapperAnimation.addElement(baseElm.querySelector('.action-sheet-wrapper'));
backdropAnimation.fromTo('opacity', 0.01, 0.3); backdropAnimation.fromTo('opacity', 0.01, 0.26);
wrapperAnimation.fromTo('opacity', 0.01, 1) wrapperAnimation.fromTo('translateY', '100%', '0%');
.fromTo('scale', 1.1, 1);
return baseAnimation return baseAnimation
.addElement(baseElm) .addElement(baseElm)
.easing('ease-in-out') .easing('cubic-bezier(.36,.66,.04,1)')
.duration(200) .duration(400)
.add(backdropAnimation) .add(backdropAnimation)
.add(wrapperAnimation); .add(wrapperAnimation);
} }

View File

@ -7,21 +7,19 @@ export default function(Animation: Animation, baseElm: HTMLElement) {
const baseAnimation = new Animation(); const baseAnimation = new Animation();
const backdropAnimation = new Animation(); const backdropAnimation = new Animation();
backdropAnimation.addElement(baseElm.querySelector('.loading-backdrop')); backdropAnimation.addElement(baseElm.querySelector('.action-sheet-backdrop'));
const wrapperAnimation = new Animation(); const wrapperAnimation = new Animation();
wrapperAnimation.addElement(baseElm.querySelector('.loading-wrapper')); wrapperAnimation.addElement(baseElm.querySelector('.action-sheet-wrapper'));
backdropAnimation.fromTo('opacity', 0.3, 0); backdropAnimation.fromTo('opacity', 0.26, 0);
wrapperAnimation.fromTo('opacity', 0.99, 0)
.fromTo('scale', 1, 0.9);
wrapperAnimation.fromTo('translateY', '0%', '100%');
return baseAnimation return baseAnimation
.addElement(baseElm) .addElement(baseElm)
.easing('ease-in-out') .easing('cubic-bezier(.36,.66,.04,1)')
.duration(200) .duration(450)
.add(backdropAnimation) .add(backdropAnimation)
.add(wrapperAnimation); .add(wrapperAnimation);
} }

View File

@ -0,0 +1,26 @@
@import "../../themes/ionic.globals";
// Backdrop
// --------------------------------------------------
/// @prop - Color of the backdrop
$backdrop-color: #000 !default;
ion-backdrop {
@include position(0, null, null, 0);
position: absolute;
z-index: $z-index-backdrop;
display: block;
width: 100%;
height: 100%;
background-color: $backdrop-color;
opacity: .01;
transform: translateZ(0);
}
ion-backdrop.backdrop-no-tappable {
cursor: auto;
}

View File

@ -0,0 +1,9 @@
import { Component } from '@stencil/core';
@Component({
tag: 'ion-backdrop',
styleUrl: 'backdrop.scss'
})
export class Backdrop {
}

View File

@ -2,6 +2,7 @@ import { AnimationController } from './components/animation/animation';
import { Animation, AnimationBuilder } from './components/animation/animation-interface'; import { Animation, AnimationBuilder } from './components/animation/animation-interface';
import { ActionSheet, ActionSheetButtons, ActionSheetEvent, ActionSheetOptions } from './components/action-sheet/action-sheet'; import { ActionSheet, ActionSheetButtons, ActionSheetEvent, ActionSheetOptions } from './components/action-sheet/action-sheet';
import { ActionSheetController } from './components/action-sheet-controller/action-sheet-controller'; import { ActionSheetController } from './components/action-sheet-controller/action-sheet-controller';
import { Backdrop } from './components/backdrop/backdrop'
import { Loading, LoadingEvent, LoadingOptions } from './components/loading/loading'; import { Loading, LoadingEvent, LoadingOptions } from './components/loading/loading';
import { LoadingController } from './components/loading-controller/loading-controller'; import { LoadingController } from './components/loading-controller/loading-controller';
import { GestureDetail, GestureCallback } from './components/gesture/gesture'; import { GestureDetail, GestureCallback } from './components/gesture/gesture';
@ -55,6 +56,7 @@ export {
Animation, Animation,
AnimationBuilder, AnimationBuilder,
AnimationController, AnimationController,
Backdrop,
GestureCallback, GestureCallback,
GestureDetail, GestureDetail,
Loading, Loading,

View File

@ -8,6 +8,7 @@ exports.config = {
{ components: ['ion-app', 'ion-content', 'ion-fixed', 'ion-footer', 'ion-header', 'ion-navbar', 'ion-page', 'ion-title', 'ion-toolbar'] }, { components: ['ion-app', 'ion-content', 'ion-fixed', 'ion-footer', 'ion-header', 'ion-navbar', 'ion-page', 'ion-title', 'ion-toolbar'] },
{ components: ['ion-action-sheet', 'ion-action-sheet-controller'] }, { components: ['ion-action-sheet', 'ion-action-sheet-controller'] },
{ components: ['ion-avatar', 'ion-badge', 'ion-thumbnail'] }, { components: ['ion-avatar', 'ion-badge', 'ion-thumbnail'] },
{ components: ['ion-backdrop'] },
{ components: ['ion-button', 'ion-buttons', 'ion-icon'] }, { components: ['ion-button', 'ion-buttons', 'ion-icon'] },
{ components: ['ion-card', 'ion-card-content', 'ion-card-header', 'ion-card-title'] }, { components: ['ion-card', 'ion-card-content', 'ion-card-header', 'ion-card-title'] },
{ components: ['ion-chip', 'ion-chip-button'] }, { components: ['ion-chip', 'ion-chip-button'] },