From e79e213c5afa87533672bca0791ee3b08d7598ac Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Tue, 27 Feb 2018 08:44:20 +1300 Subject: [PATCH] Notifications have customisable duration and CSS animation in-and-out --- src/js/App.js | 22 ++++++------ src/js/components/Notifications.js | 4 +-- src/js/services/ui/actions.js | 1 + src/js/services/ui/middleware.js | 2 +- src/scss/components/_notifications.scss | 11 ++++-- src/scss/global/_variables.scss | 48 +++++++++++++++++++------ 6 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/js/App.js b/src/js/App.js index 3ccd708d..93790a5a 100755 --- a/src/js/App.js +++ b/src/js/App.js @@ -157,13 +157,13 @@ class App extends React.Component{ case 32: // spacebar if (e.ctrlKey || e.metaKey){ this.props.mopidyActions.stop(); - this.props.uiActions.createNotification({content: 'stop', type: 'shortcut', key: 'shortcut'}); + this.props.uiActions.createNotification({content: 'stop', type: 'shortcut', key: 'shortcut', duration: 1}); } else if (this.props.play_state == 'playing'){ this.props.mopidyActions.pause(); - this.props.uiActions.createNotification({content: 'pause', type: 'shortcut', key: 'shortcut'}); + this.props.uiActions.createNotification({content: 'pause', type: 'shortcut', key: 'shortcut', duration: 1}); } else { this.props.mopidyActions.play(); - this.props.uiActions.createNotification({content: 'play', type: 'shortcut', key: 'shortcut'}); + this.props.uiActions.createNotification({content: 'play', type: 'shortcut', key: 'shortcut', duration: 1}); } break; @@ -179,7 +179,7 @@ class App extends React.Component{ case 40: // down if ((e.ctrlKey || e.metaKey) && e.shiftKey){ this.props.mopidyActions.setMute(true); - this.props.uiActions.createNotification({content: 'volume-off', type: 'shortcut', key: 'shortcut'}); + this.props.uiActions.createNotification({content: 'volume-off', type: 'shortcut', key: 'shortcut', duration: 1}); } else if (e.ctrlKey){ var volume = this.props.volume; if (volume !== 'false'){ @@ -191,7 +191,7 @@ class App extends React.Component{ if (this.props.mute){ this.props.mopidyActions.setMute(false); } - this.props.uiActions.createNotification({content: 'volume-down', type: 'shortcut', key: 'shortcut'}); + this.props.uiActions.createNotification({content: 'volume-down', type: 'shortcut', key: 'shortcut', duration: 1}); } } break; @@ -202,7 +202,7 @@ class App extends React.Component{ if (this.props.mute){ this.props.mopidyActions.setMute(false); } - this.props.uiActions.createNotification({content: 'volume-up', type: 'shortcut', key: 'shortcut'}); + this.props.uiActions.createNotification({content: 'volume-up', type: 'shortcut', key: 'shortcut', duration: 1}); } else if (e.ctrlKey || e.metaKey){ var volume = this.props.volume if (volume !== 'false'){ @@ -214,7 +214,7 @@ class App extends React.Component{ if (this.props.mute){ this.props.mopidyActions.setMute(false); } - this.props.uiActions.createNotification({content: 'volume-up', type: 'shortcut', key: 'shortcut'}); + this.props.uiActions.createNotification({content: 'volume-up', type: 'shortcut', key: 'shortcut', duration: 1}); } } break; @@ -226,20 +226,20 @@ class App extends React.Component{ new_position = 0;; } this.props.mopidyActions.seek(new_position); - this.props.uiActions.createNotification({content: 'fast-backward', type: 'shortcut', key: 'shortcut'}); + this.props.uiActions.createNotification({content: 'fast-backward', type: 'shortcut', key: 'shortcut', duration: 1}); } else if (e.ctrlKey || e.metaKey){ this.props.mopidyActions.previous(); - this.props.uiActions.createNotification({content: 'step-backward', type: 'shortcut', key: 'shortcut'}); + this.props.uiActions.createNotification({content: 'step-backward', type: 'shortcut', key: 'shortcut', duration: 1}); } break; case 39: // right if ((e.ctrlKey || e.metaKey) && e.shiftKey){ this.props.mopidyActions.seek(this.props.play_time_position + 30000); - this.props.uiActions.createNotification({content: 'fast-forward', type: 'shortcut', key: 'shortcut'}); + this.props.uiActions.createNotification({content: 'fast-forward', type: 'shortcut', key: 'shortcut', duration: 1}); } else if (e.ctrlKey || e.metaKey){ this.props.mopidyActions.next(); - this.props.uiActions.createNotification({content: 'step-forward', type: 'shortcut', key: 'shortcut'}); + this.props.uiActions.createNotification({content: 'step-forward', type: 'shortcut', key: 'shortcut', duration: 1}); } break; diff --git a/src/js/components/Notifications.js b/src/js/components/Notifications.js index 52e9fdfc..7ae3e742 100755 --- a/src/js/components/Notifications.js +++ b/src/js/components/Notifications.js @@ -18,14 +18,14 @@ export default class Notifications extends React.Component{ switch (notification.type){ case 'shortcut': return ( -
+
) default: return ( -
+
this.props.uiActions.removeNotification(notification.key) } /> {notification.title ?

{notification.title}

: null}

diff --git a/src/js/services/ui/actions.js b/src/js/services/ui/actions.js index 1234aa07..01f80722 100755 --- a/src/js/services/ui/actions.js +++ b/src/js/services/ui/actions.js @@ -183,6 +183,7 @@ export function createNotification(data){ notification: Object.assign( { key: helpers.generateGuid(), + duration: 3, type: 'default', title: null, content: null, diff --git a/src/js/services/ui/middleware.js b/src/js/services/ui/middleware.js index fbc7224f..216d7c2f 100755 --- a/src/js/services/ui/middleware.js +++ b/src/js/services/ui/middleware.js @@ -76,7 +76,7 @@ const UIMiddleware = (function(){ function(){ store.dispatch(uiActions.removeNotification(action.notification.key)) }, - (action.notification.type == 'shortcut' ? 1000 : 3000) + action.notification.duration * 1000 ) } diff --git a/src/scss/components/_notifications.scss b/src/scss/components/_notifications.scss index 0f3577c2..90187315 100755 --- a/src/scss/components/_notifications.scss +++ b/src/scss/components/_notifications.scss @@ -9,15 +9,22 @@ width: 300px; .notification { - @include fadein(); display: block; position: relative; background: $blue; padding: 16px 40px 16px 22px; margin: 10px 0 0 0; color: $white; - pointer-events: all; + pointer-events: all; border-radius: 3px; + + &[data-duration="1"]{ + @include fadeinout(1s); + } + + &[data-duration="3"]{ + @include fadeinout(3s); + } h4 { padding-top: 0; diff --git a/src/scss/global/_variables.scss b/src/scss/global/_variables.scss index d0c8f159..eb8d432b 100755 --- a/src/scss/global/_variables.scss +++ b/src/scss/global/_variables.scss @@ -104,19 +104,45 @@ $bp_shallow: 650px; animation-iteration-count: infinite; } -@keyframes fadein { - 0% { - opacity: 0; - transform: translateY(5px); - } - 100% { - opacity: 1; - transform: translateY(0px); - } +@mixin fadein($duration: 0.2s){ + @keyframes fadein { + 0% { + opacity: 0; + transform: translateY(5px); + } + 100% { + opacity: 1; + transform: translateY(0px); + } + } + + animation-name: fadein; + animation-duration: $duration; + animation-timing-function: linear; + animation-iteration-count: 1; } -@mixin fadein($duration: 0.2s){ - animation-name: fadein; +@mixin fadeinout($duration: 3s){ + @keyframes fadeinout { + 0% { + opacity: 0; + transform: translateY(5px); + } + 6% { + opacity: 1; + transform: translateY(0px); + } + 94% { + opacity: 1; + transform: translateY(0px); + } + 100% { + opacity: 0; + transform: translateY(5px); + } + } + + animation-name: fadeinout; animation-duration: $duration; animation-timing-function: linear; animation-iteration-count: 1;