From ab2a3b0488b32d9a6b45f0d9aa3e349373d566d7 Mon Sep 17 00:00:00 2001 From: Petter Kjelkenes Date: Fri, 31 Jul 2015 00:11:59 +0200 Subject: [PATCH] Toast integration, needs #138. --- addon/components/paper-toast.js | 24 +++ addon/mixins/animate-mixin.js | 41 ++++++ app/components/paper-toast.js | 1 + app/styles/ember-paper.scss | 1 + app/styles/paper-toast.scss | 169 ++++++++++++++++++++++ app/templates/components/paper-toast.hbs | 8 + tests/dummy/app/controllers/toast.js | 26 ++++ tests/dummy/app/router.js | 1 + tests/dummy/app/templates/application.hbs | 1 + tests/dummy/app/templates/toast.hbs | 46 ++++++ 10 files changed, 318 insertions(+) create mode 100644 addon/components/paper-toast.js create mode 100644 addon/mixins/animate-mixin.js create mode 100644 app/components/paper-toast.js create mode 100644 app/styles/paper-toast.scss create mode 100644 app/templates/components/paper-toast.hbs create mode 100644 tests/dummy/app/controllers/toast.js create mode 100644 tests/dummy/app/templates/toast.hbs diff --git a/addon/components/paper-toast.js b/addon/components/paper-toast.js new file mode 100644 index 000000000..9b2b86408 --- /dev/null +++ b/addon/components/paper-toast.js @@ -0,0 +1,24 @@ +import Ember from 'ember'; +import AnimateMixin from 'ember-paper/mixins/animate-mixin'; + +export default Ember.Component.extend(AnimateMixin, { + tagName: 'md-toast', + classNames: ['md-default-theme'], + classNameBindings: ['right:md-right', 'left:md-left', 'bottom:md-bottom', 'top:md-top'], + animated: true, + + didInsertElement () { + if (this.get('hide-delay')) { + Ember.run.later(function () { + this.sendAction('on-close'); + }.bind(this), this.get('hide-delay')); + } + }, + + actions: { + buttonAction: function () { + this.sendAction('on-button'); + } + } + +}); diff --git a/addon/mixins/animate-mixin.js b/addon/mixins/animate-mixin.js new file mode 100644 index 000000000..4b1e78e83 --- /dev/null +++ b/addon/mixins/animate-mixin.js @@ -0,0 +1,41 @@ +import Ember from 'ember'; + +export default Ember.Mixin.create({ + classNameBindings: ['animated:ng-enter'], + + /** + * Wait for redraw so we can add add animation classes + * See CSS redraw / repaint for more details. + */ + reDraw (element) { + return new Ember.RSVP.Promise(function (resolve) { + setTimeout(function() { + // These are just meant to be called so browser to a repaint. + /* jshint ignore:start */ + element[0].offsetHeight; + element[0].getComputedStyle; + /* jshint ignore:end */ + resolve(element); + },0); + }); + }, + + _animateOnInsert: Ember.on('didInsertElement', function () { + var _self = this; + this.reDraw(this.$()).then(function () { + _self.$().addClass('ng-enter-active'); + }); + }), + + _animateOnDestroy: Ember.on('willDestroyElement', function () { + var old = this.$().clone().addClass('ng-leave').removeClass('ng-enter ng-enter-active').appendTo(this.$().parent()); + this.reDraw(old).then(function () { + old.one('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', function () { + old.remove(); + }); + old.addClass('ng-leave-active'); + }); + }) + + +}); diff --git a/app/components/paper-toast.js b/app/components/paper-toast.js new file mode 100644 index 000000000..681fcfab8 --- /dev/null +++ b/app/components/paper-toast.js @@ -0,0 +1 @@ +export { default } from 'ember-paper/components/paper-toast'; \ No newline at end of file diff --git a/app/styles/ember-paper.scss b/app/styles/ember-paper.scss index 6ee9f607c..f961c6801 100644 --- a/app/styles/ember-paper.scss +++ b/app/styles/ember-paper.scss @@ -80,3 +80,4 @@ @import 'paper-sidenav'; @import 'paper-backdrop'; +@import 'paper-toast'; diff --git a/app/styles/paper-toast.scss b/app/styles/paper-toast.scss new file mode 100644 index 000000000..f4a849c4c --- /dev/null +++ b/app/styles/paper-toast.scss @@ -0,0 +1,169 @@ +// See height set globally, depended on by buttons + + +md-toast { + display: flex; + position:absolute; + box-sizing: border-box; + align-items: center; + + min-height: 48px; + padding-left: 24px; + padding-right: 24px; + + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); + border-radius: 2px; + font-size: 14px; + cursor: default; + + max-width: 100%; + max-height: 40px; + + height: $toast-height; + z-index: $z-index-toast; + + &.md-capsule { + border-radius: 24px; + } + + opacity: 1; + transform: translate3d(0,0,0) rotateZ(0deg); + transition: $swift-ease-out; + + &.ng-leave-active { + transition: $swift-ease-in; + } + + /* Transition differently when swiping */ + &.md-swipeleft, + &.md-swiperight, + &.md-swipeup, + &.md-swipedown { + transition: $swift-ease-out; + } + + &.ng-enter { + transform: translate3d(0, 100%, 0); + &.md-top { + transform: translate3d(0, -100%, 0); + } + opacity: 0; + &.ng-enter-active { + transform: translate3d(0, 0, 0); + opacity: 1; + } + } + &.ng-leave.ng-leave-active { + opacity: 0; + transform: translate3d(0, 100%, 0); + &.md-top { + transform: translate3d(0, -100%, 0); + } + &.md-swipeleft { + transform: translate3d(-100%, 0%, 0); + } + &.md-swiperight { + transform: translate3d(100%, 0%, 0); + } + } + + .md-action { + line-height: 19px; + margin-left: 24px; + cursor: pointer; + text-transform: uppercase; + float: right; + + &.md-button { + min-width: 0; + } + } +} + +@media (max-width: $layout-breakpoint-sm) { + md-toast { + left: 0; + right: 0; + width: 100%; + max-width: 100%; + min-width: 0; + border-radius: 0; + bottom: 0; + &.md-top { + bottom: auto; + top: 0; + } + } +} +@media (min-width: $layout-breakpoint-sm) { + md-toast { + min-width: 288px; + &.md-bottom { + bottom: $toast-margin; + } + &.md-left { + left: $toast-margin; + } + &.md-right { + right: $toast-margin; + } + &.md-top { + top: $toast-margin; + } + + /* + * When the toast doesn't take up the whole screen, + * make it rotate when the user swipes it away + */ + &.ng-leave.ng-leave-active { + &.md-swipeleft { + transform: translate3d(-100%, 25%, 0) rotateZ(-15deg); + } + &.md-swiperight { + transform: translate3d(100%, 25%, 0) rotateZ(15deg); + } + &.md-top { + &.md-swipeleft { + transform: translate3d(-100%, 0, 0) rotateZ(-15deg); + } + &.md-swiperight { + transform: translate3d(100%, 0, 0) rotateZ(15deg); + } + } + } + } +} + +@media (min-width: $layout-breakpoint-lg) { + md-toast { + max-width: $baseline-grid * 71; + } +} + + + +@media screen and (-ms-high-contrast: active) { + md-toast { + border: 1px solid #fff; + } +} + + +// Theme +md-toast.md-#{$theme-name}-theme { + background-color: #323232; + color: color($background, '50'); + + .md-button { + color: color($background, '50'); + &.md-highlight { + color: color($primary ,'A200'); + &.md-accent { + color: color($accent ,'A200'); + } + &.md-warn { + color: color($accent ,'A200'); + } + } + } +} diff --git a/app/templates/components/paper-toast.hbs b/app/templates/components/paper-toast.hbs new file mode 100644 index 000000000..eaf9da5a8 --- /dev/null +++ b/app/templates/components/paper-toast.hbs @@ -0,0 +1,8 @@ +{{#if hasBlock}} + {{yield}} +{{else}} + {{message}} + {{#if button}} + {{#paper-button action="buttonAction"}}{{button}}{{/paper-button}} + {{/if}} +{{/if}} diff --git a/tests/dummy/app/controllers/toast.js b/tests/dummy/app/controllers/toast.js new file mode 100644 index 000000000..99e921f3b --- /dev/null +++ b/tests/dummy/app/controllers/toast.js @@ -0,0 +1,26 @@ +import Ember from 'ember'; + +export default Ember.Controller.extend({ + + actions: { + openToast: function () { + this.set('myToastOpen', true); + }, + closeToast: function () { + this.set('myToastOpen', false); + }, + openToastDelayed: function () { + this.set('isDelayedToastOpen', true); + }, + closeToastDelayed: function () { + this.set('isDelayedToastOpen', false); + }, + openToastLeftBottom: function () { + this.set('leftBottomMessage', 'Hello World!'); + this.set('leftBottom', true); + }, + closeToastLeftBottom: function () { + this.set('leftBottom', false); + } + } +}); diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js index 0e0ad962c..92a5bf8dc 100644 --- a/tests/dummy/app/router.js +++ b/tests/dummy/app/router.js @@ -21,6 +21,7 @@ Router.map(function() { this.route('sidenav'); this.route('input'); this.route('toolbar'); + this.route('toast'); this.route('icons'); this.route('slider'); }); diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs index 3f217ecc8..ca9d885cd 100644 --- a/tests/dummy/app/templates/application.hbs +++ b/tests/dummy/app/templates/application.hbs @@ -29,6 +29,7 @@ {{#paper-item action="transitionTo" param="radio"}}Radio{{/paper-item}} {{#paper-item action="transitionTo" param="input"}}Input{{/paper-item}} {{#paper-item action="transitionTo" param="toolbar"}}Toolbar{{/paper-item}} + {{#paper-item action="transitionTo" param="toast"}}Toast{{/paper-item}} {{#paper-item action="transitionTo" param="icons"}}Icons{{/paper-item}} {{/paper-list}} diff --git a/tests/dummy/app/templates/toast.hbs b/tests/dummy/app/templates/toast.hbs new file mode 100644 index 000000000..0999dd14f --- /dev/null +++ b/tests/dummy/app/templates/toast.hbs @@ -0,0 +1,46 @@ +{{#paper-toolbar}} +

+ {{#paper-sidenav-toggle class="menu-sidenav-toggle"}} + {{paper-icon icon="menu"}} + {{/paper-sidenav-toggle}} + Toasts +

+{{/paper-toolbar}} +{{#paper-content classNames="md-padding"}} +
+
+
+ {{#paper-button action="openToastLeftBottom"}} + Open in left bottom + {{/paper-button}} + {{#paper-button action="openToast"}} + Open toast + {{/paper-button}} + {{#paper-button action="openToastDelayed"}} + Delayed hide + {{/paper-button}} +
+ + + {{#if myToastOpen}} + {{#paper-toast top=true right=true as |toast|}} + Custom toast! + {{#paper-button action="closeToast"}}Close{{/paper-button}} + {{/paper-toast}} + {{/if}} + + + {{#if isDelayedToastOpen}} + {{paper-toast hide-delay=4000 on-close="closeToastDelayed" on-button="closeToastDelayed" top=true right=true button="Close this" message="I'm removed within 4 seconds!!"}} + {{/if}} + + + + {{#if leftBottom}} + {{paper-toast on-button="closeToastLeftBottom" left=true bottom=true button="Close this" message=leftBottomMessage}} + {{/if}} + + +
+
+{{/paper-content}}