Explorar el Código

Add option, add close animation, move ESC and TAB event listener, improve FOCUSABLE_ELEMENTS, docs

Artur Paikin hace 7 años
padre
commit
339640f493

+ 3 - 1
src/plugins/Dashboard/Dashboard.js

@@ -23,7 +23,7 @@ const renderInnerPanel = (props) => {
 }
 
 const poweredByUppy = (props) => {
-  return <a href="https://uppy.io" rel="noreferrer noopener" target="_blank" class="uppy-Dashboard-poweredBy">Powered by <svg aria-hidden="true" class="UppyIcon uppy-Dashboard-poweredByIcon" width="11" height="11" viewBox="0 0 11 11" xmlns="http://www.w3.org/2000/svg">
+  return <a tabindex="-1" href="https://uppy.io" rel="noreferrer noopener" target="_blank" class="uppy-Dashboard-poweredBy">Powered by <svg aria-hidden="true" class="UppyIcon uppy-Dashboard-poweredByIcon" width="11" height="11" viewBox="0 0 11 11" xmlns="http://www.w3.org/2000/svg">
     <path d="M7.365 10.5l-.01-4.045h2.612L5.5.806l-4.467 5.65h2.604l.01 4.044h3.718z" fill-rule="evenodd" />
   </svg><span class="uppy-Dashboard-poweredByUppy">Uppy</span></a>
 }
@@ -33,6 +33,8 @@ module.exports = function Dashboard (props) {
     { 'uppy-Root': props.isTargetDOMEl },
     'uppy-Dashboard',
     { 'Uppy--isTouchDevice': isTouchDevice() },
+    { 'uppy-Dashboard--animateOpenClose': props.animateOpenClose },
+    { 'uppy-Dashboard--isClosing': props.isClosing },
     { 'uppy-Dashboard--modal': !props.inline },
     { 'uppy-Dashboard--wide': props.isWide }
   )

+ 45 - 27
src/plugins/Dashboard/index.js

@@ -13,19 +13,22 @@ const { defaultTabIcon } = require('./icons')
 // MIT licence, https://github.com/ghosh/micromodal/blob/master/LICENSE.md
 // Copyright (c) 2017 Indrashish Ghosh
 const FOCUSABLE_ELEMENTS = [
-  'a[href]',
-  'area[href]',
-  'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',
-  'select:not([disabled]):not([aria-hidden])',
-  'textarea:not([disabled]):not([aria-hidden])',
-  'button:not([disabled]):not([aria-hidden])',
-  'iframe',
-  'object',
-  'embed',
-  '[contenteditable]',
-  '[tabindex]:not([tabindex^="-"])'
+  'a[href]:not([tabindex^="-"]):not([inert]):not([aria-hidden])',
+  'area[href]:not([tabindex^="-"]):not([inert]):not([aria-hidden])',
+  'input:not([disabled]):not([inert]):not([aria-hidden])',
+  'select:not([disabled]):not([inert]):not([aria-hidden])',
+  'textarea:not([disabled]):not([inert]):not([aria-hidden])',
+  'button:not([disabled]):not([inert]):not([aria-hidden])',
+  'iframe:not([tabindex^="-"]):not([inert]):not([aria-hidden])',
+  'object:not([tabindex^="-"]):not([inert]):not([aria-hidden])',
+  'embed:not([tabindex^="-"]):not([inert]):not([aria-hidden])',
+  '[contenteditable]:not([tabindex^="-"]):not([inert]):not([aria-hidden])',
+  '[tabindex]:not([tabindex^="-"]):not([inert]):not([aria-hidden])'
 ]
 
+const TAB_KEY = 9
+const ESC_KEY = 27
+
 /**
  * Dashboard UI with previews, metadata editing, tabs for various services and more
  */
@@ -104,6 +107,7 @@ module.exports = class Dashboard extends Plugin {
       disableInformer: false,
       disableThumbnailGenerator: false,
       disablePageScrollWhenModalOpen: true,
+      animateOpenClose: true,
       proudlyDisplayPoweredByUppy: true,
       onRequestCloseModal: () => this.closeModal(),
       locale: defaultLocale
@@ -239,23 +243,43 @@ module.exports = class Dashboard extends Plugin {
     this.savedActiveElement = document.activeElement
 
     if (this.opts.disablePageScrollWhenModalOpen) {
-      document.body.classList.add('uppy-Dashboard-isOpen')
+      document.body.classList.add('uppy-Dashboard-isFixed')
     }
 
+    // handle ESC and TAB keys in modal dialog
+    document.addEventListener('keydown', this.onKeydown)
+
     this.rerender(this.uppy.getState())
     this.updateDashboardElWidth()
     this.setFocusToBrowse()
   }
 
   closeModal () {
-    this.setPluginState({
-      isHidden: true
-    })
-
     if (this.opts.disablePageScrollWhenModalOpen) {
-      document.body.classList.remove('uppy-Dashboard-isOpen')
+      document.body.classList.remove('uppy-Dashboard-isFixed')
+    }
+
+    if (this.opts.animateOpenClose) {
+      this.setPluginState({
+        isClosing: true
+      })
+      const handler = () => {
+        this.setPluginState({
+          isHidden: true,
+          isClosing: false
+        })
+        this.el.removeEventListener('animationend', handler, false)
+      }
+      this.el.addEventListener('animationend', handler, false)
+    } else {
+      this.setPluginState({
+        isHidden: true
+      })
     }
 
+    // handle ESC and TAB keys in modal dialog
+    document.removeEventListener('keydown', this.onKeydown)
+
     this.savedActiveElement.focus()
   }
 
@@ -265,9 +289,9 @@ module.exports = class Dashboard extends Plugin {
 
   onKeydown (event) {
     // close modal on esc key press
-    if (event.keyCode === 27) this.requestCloseModal(event)
+    if (event.keyCode === ESC_KEY) this.requestCloseModal(event)
     // maintainFocus on tab key press
-    if (event.keyCode === 9) this.maintainFocus(event)
+    if (event.keyCode === TAB_KEY) this.maintainFocus(event)
   }
 
   handleClickOutside () {
@@ -320,10 +344,6 @@ module.exports = class Dashboard extends Plugin {
       this.uppy.log('Dashboard modal trigger not found. Make sure `trigger` is set in Dashboard options unless you are planning to call openModal() method yourself')
     }
 
-    if (!this.opts.inline) {
-      document.addEventListener('keydown', this.onKeydown)
-    }
-
     // Drag Drop
     this.removeDragDropListener = dragDrop(this.el, (files) => {
       this.handleDrop(files)
@@ -339,10 +359,6 @@ module.exports = class Dashboard extends Plugin {
       showModalTrigger.forEach(trigger => trigger.removeEventListener('click', this.openModal))
     }
 
-    if (!this.opts.inline) {
-      document.removeEventListener('keydown', this.onKeydown)
-    }
-
     this.removeDragDropListener()
     window.removeEventListener('resize', this.updateDashboardElWidth)
   }
@@ -453,6 +469,8 @@ module.exports = class Dashboard extends Plugin {
       totalProgress: state.totalProgress,
       acquirers: acquirers,
       activePanel: pluginState.activePanel,
+      animateOpenClose: this.opts.animateOpenClose,
+      isClosing: pluginState.isClosing,
       getPlugin: this.uppy.getPlugin,
       progressindicators: progressindicators,
       autoProceed: this.uppy.opts.autoProceed,

+ 0 - 9
src/scss/_animation.scss

@@ -1,9 +0,0 @@
-@keyframes fadeIn {
-  from { opacity: 0;  }
-  to { opacity: 1;  }
-}
-
-@keyframes appear {
-  from { transform: translate3d(-50%, -70%, 0); opacity: 0; }
-  to { transform: translate3d(-50%, -50%, 0); opacity: 1; }
-}

+ 41 - 9
src/scss/_dashboard.scss

@@ -1,20 +1,51 @@
 .uppy-Dashboard--modal {
   z-index: $zIndex-2;
-  // transition: transform 0.2s ease-in-out;
-  // transform: none;
-  // -webkit-overflow-scrolling: touch;
 }
 
-.uppy-Dashboard--modal[aria-hidden=true] {
-  display: none;
-}
+  .uppy-Dashboard--modal[aria-hidden=true] {
+    display: none;
+  }
+
+  // Modal open/close animations
+
+  @keyframes uppy-Dashboard-fadeIn {
+    from { opacity: 0;  }
+    to { opacity: 1;  }
+  }
+
+  @keyframes uppy-Dashboard-fadeOut {
+    from { opacity: 1;  }
+    to { opacity: 0;  }
+  }
+
+  @keyframes uppy-Dashboard-slideDownAndFadeIn {
+    from { transform: translate3d(-50%, -70%, 0); opacity: 0; }
+    to { transform: translate3d(-50%, -50%, 0); opacity: 1; }
+  }
+
+  @keyframes uppy-Dashboard-slideUpFadeOut {
+    from { transform: translate3d(-50%, -50%, 0); opacity: 1; }
+    to { transform: translate3d(-50%, -70%, 0); opacity: 0; }
+  }
+
+  .uppy-Dashboard--modal.uppy-Dashboard--animateOpenClose > .uppy-Dashboard-inner {
+    animation: uppy-Dashboard-slideDownAndFadeIn 300ms cubic-bezier(0, 0, .2, 1);
+  }
 
-  .uppy-Dashboard--modal:not([aria-hidden='true']) > .uppy-Dashboard-inner {
-    animation: appear 300ms both;
+  .uppy-Dashboard--modal.uppy-Dashboard--animateOpenClose > .uppy-Dashboard-overlay {
+    animation: uppy-Dashboard-fadeIn 300ms cubic-bezier(0, 0, .2, 1);
+  }
+
+  .uppy-Dashboard--modal.uppy-Dashboard--animateOpenClose.uppy-Dashboard--isClosing > .uppy-Dashboard-inner {
+    animation: uppy-Dashboard-slideUpFadeOut 300ms cubic-bezier(0, 0, .2, 1);
+  }
+
+  .uppy-Dashboard--modal.uppy-Dashboard--animateOpenClose.uppy-Dashboard--isClosing > .uppy-Dashboard-overlay {
+    animation: uppy-Dashboard-fadeOut 300ms cubic-bezier(0, 0, .2, 1);
   }
 
 // Added to body to prevent the page from scrolling when Modal is open
-.uppy-Dashboard-isOpen {
+.uppy-Dashboard-isFixed {
   overflow: hidden;
   height: 100vh;
 }
@@ -42,6 +73,7 @@
   outline: none;
   border: 1px solid rgba($color-gray, 0.2);
   margin-bottom: 30px;
+  will-change: transform;
 
   .uppy-Dashboard--modal & {
     z-index: $zIndex-3;

+ 4 - 0
website/src/docs/dashboard.md

@@ -169,6 +169,10 @@ Set to true to automatically close the modal when the user clicks outside of it.
 
 By default when Dashboard modal is open, it will disable page scrolling, so when you scroll a list of files in Uppy the website in the background stays still. Set to false to override this behaviour and leave page scrolling intact.
 
+## `animateOpenClose: true`
+
+Add light animations when modal dialog is open or closed, for more satisfying user experience.
+
 ### `proudlyDisplayPoweredByUppy: true`
 
 Uppy is provided for the world for free by the [Transloadit team](https://transloadit.com). In return, we ask that you consider keeping a tiny Uppy logo at the bottom of the Dashboard, so that more people can discover and use Uppy.