Browse Source

Modal: use aria, classes for panels instead of ids, hide/show modal methods, icons

Artur Paikin 9 years ago
parent
commit
329fc51e37
6 changed files with 118 additions and 84 deletions
  1. 0 2
      src/core/Core.js
  2. 8 6
      src/plugins/DragDrop.js
  3. 1 3
      src/plugins/Dummy.js
  4. 60 34
      src/plugins/Modal.js
  5. 48 38
      src/scss/_modal.scss
  6. 1 1
      website/src/examples/modal/app.es6

+ 0 - 2
src/core/Core.js

@@ -154,8 +154,6 @@ export default class Core {
       method: 'run'
     })
 
-    console.log('yo')
-
     // Forse set `autoProceed` option to false if there are multiple selector Plugins active
     if (this.plugins.selecter && this.plugins.selecter.length > 1) {
       this.opts.autoProceed = false

+ 8 - 6
src/plugins/DragDrop.js

@@ -9,7 +9,14 @@ export default class DragDrop extends Plugin {
   constructor (core, opts) {
     super(core, opts)
     this.type = 'selecter'
-
+    this.name = 'Drag & Drop'
+    this.icon = `
+      <svg class="UppyModalTab-icon" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+        <path d="M15.982 2.97c0-.02 0-.02-.018-.037 0-.017-.017-.035-.035-.053 0 0 0-.018-.02-.018-.017-.018-.034-.053-.052-.07L13.19.123c-.017-.017-.034-.035-.07-.053h-.018c-.018-.017-.035-.017-.053-.034h-.02c-.017 0-.034-.018-.052-.018h-6.31a.415.415 0 0 0-.446.426V11.11c0 .25.196.446.445.446h8.89A.44.44 0 0 0 16 11.11V3.023c-.018-.018-.018-.035-.018-.053zm-2.65-1.46l1.157 1.157h-1.157V1.51zm1.78 9.157h-8V.89h5.332v2.22c0 .25.196.446.445.446h2.22v7.11z"/>
+        <path d="M9.778 12.89H4V2.666a.44.44 0 0 0-.444-.445.44.44 0 0 0-.445.445v10.666c0 .25.197.445.446.445h6.222a.44.44 0 0 0 .444-.445.44.44 0 0 0-.444-.444z"/>
+        <path d="M.444 16h6.223a.44.44 0 0 0 .444-.444.44.44 0 0 0-.443-.445H.89V4.89a.44.44 0 0 0-.446-.446A.44.44 0 0 0 0 4.89v10.666c0 .248.196.444.444.444z"/>
+      </svg>
+    `
     // Default options
     const defaultOptions = {
       target: '.UppyDragDrop'
@@ -102,11 +109,6 @@ export default class DragDrop extends Plugin {
       })
     })
 
-    // this.container.addEventListener('progress', (e) => {
-    //   const percentage = e.detail
-    //   this.setProgress(percentage)
-    // })
-
     // document.addEventListener('dragover', (e) => {
     //   console.log('ну пиздец')
     // })

+ 1 - 3
src/plugins/Dummy.js

@@ -8,6 +8,7 @@ export default class Dummy extends Plugin {
   constructor (core, opts) {
     super(core, opts)
     this.type = 'selecter'
+    this.name = 'Dummy'
 
     // set default options
     const defaultOptions = {}
@@ -25,9 +26,6 @@ export default class Dummy extends Plugin {
   }
 
   install () {
-    // this.core.log('the spinner target is... ' +
-    //   this.getTarget(this.opts.target).spinner
-    // )
     const caller = this
     this.target = this.getTarget(this.opts.target, caller)
     this.targetEl = document.querySelector(this.target)

+ 60 - 34
src/plugins/Modal.js

@@ -11,16 +11,30 @@ export default class Modal extends Plugin {
     this.type = 'view'
 
     // set default options
-    const defaultOptions = {}
+    const defaultOptions = {
+      defaultTabIcon: `
+        <svg class="UppyModalTab-icon" viewBox="0 0 101 58" xmlns="http://www.w3.org/2000/svg">
+          <path d="M17.582.3L.915 41.713l32.94 13.295L17.582.3zm83.333 41.414L67.975 55.01 84.25.3l16.665 41.414zm-48.998 5.403L63.443 35.59H38.386l11.527 11.526v5.905l-3.063 3.32 1.474 1.36 2.59-2.806 2.59 2.807 1.475-1.357-3.064-3.32v-5.906zm16.06-26.702c-3.973 0-7.194-3.22-7.194-7.193 0-3.973 3.222-7.193 7.193-7.193 3.974 0 7.193 3.22 7.193 7.19 0 3.974-3.22 7.194-7.195 7.194zM70.48 8.682c-.737 0-1.336.6-1.336 1.337 0 .736.6 1.335 1.337 1.335.738 0 1.338-.598 1.338-1.336 0-.74-.6-1.338-1.338-1.338zM33.855 20.415c-3.973 0-7.193-3.22-7.193-7.193 0-3.973 3.22-7.193 7.195-7.193 3.973 0 7.192 3.22 7.192 7.19 0 3.974-3.22 7.194-7.192 7.194zM36.36 8.682c-.737 0-1.336.6-1.336 1.337 0 .736.6 1.335 1.337 1.335.738 0 1.338-.598 1.338-1.336 0-.74-.598-1.338-1.337-1.338z"/>
+        </svg>
+      `,
+      panelSelectorPrefix: 'UppyModalContent-panel'
+    }
+
+    this.isModalVisible = false
 
     // merge default options with the ones set by user
     this.opts = Object.assign({}, defaultOptions, opts)
 
-    this.container = document.body
+    this.initEvents = this.initEvents.bind(this)
+    this.hideModal = this.hideModal.bind(this)
+    this.showModal = this.showModal.bind(this)
+    this.install = this.install.bind(this)
   }
 
   prepareTarget (callerPlugin) {
-    const callerPluginName = callerPlugin.constructor.name
+    const callerPluginId = callerPlugin.constructor.name
+    const callerPluginName = callerPlugin.name || callerPluginId
+    const callerPluginIcon = callerPlugin.icon || this.opts.defaultTabIcon
 
     switch (callerPlugin.type) {
       case 'progress':
@@ -28,15 +42,14 @@ export default class Modal extends Plugin {
       case 'selecter':
 
         // add tab panel, where plugin will render
-        const modalContent = document.querySelector('.UppyModalСontent')
+        const modalContent = document.querySelector('.UppyModalContent')
         const nodeForPlugin = document.createElement('div')
 
         modalContent.appendChild(nodeForPlugin)
         nodeForPlugin.outerHTML = `
-          <div class="UppyModalContent-panel"
-               role="tabpanel"
-               id="${callerPluginName}">
-          </div>
+        <div class="UppyModalContent-panel ${this.opts.panelSelectorPrefix}--${callerPluginId}"
+             role="tabpanel">
+        </div>
         `
 
         // add tab switch button
@@ -47,12 +60,10 @@ export default class Modal extends Plugin {
         modalTab.outerHTML = `
           <li class="UppyModalTab">
             <button class="UppyModalTab-btn"
-               role="tab"
-               aria-controls="${callerPluginName}"
-               href="#${callerPluginName}">
-               <svg class="UppyModalTab-icon" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414">
-                 <path d="M2.955 14.93l2.667-4.62H16l-2.667 4.62H2.955zm2.378-4.62l-2.666 4.62L0 10.31l5.19-8.99 2.666 4.62-2.523 4.37zm10.523-.25h-5.333l-5.19-8.99h5.334l5.19 8.99z"></path>
-               </svg>
+                    role="tab"
+                    aria-controls="${callerPluginId}"
+                    data-open="${this.opts.panelSelectorPrefix}--${callerPluginId}">
+              ${callerPluginIcon}
               <span class="UppyModalTab-name">${callerPluginName}</span>
             </button>
           </li>
@@ -60,7 +71,7 @@ export default class Modal extends Plugin {
 
         this.initEvents()
 
-        return `#${callerPluginName}`
+        return `.${this.opts.panelSelectorPrefix}--${callerPluginId}`
       default:
         let msg = 'Error: Modal can only be used by plugins of types: selecter, progress'
         this.core.log(msg)
@@ -72,27 +83,33 @@ export default class Modal extends Plugin {
     // http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog
 
     return `
-      <div class="UppyModal">
-        <div class="UppyModal-inner"
-             aria-hidden="true"
-             aria-labelledby="modalTitle"
-             aria-describedby="modalDescription"
-             role="dialog">
-
-          <button class="UppyModal-close" title="Close uploader modal" data-modal-hide>×</button>
+      <div class="UppyModal"
+           aria-hidden="true"
+           aria-labelledby="modalTitle"
+           aria-describedby="modalDescription"
+           role="dialog">
+        <div class="UppyModal-overlay js-UppyModal-close" tabindex="-1"></div>
+        <div class="UppyModal-inner">
+          <button class="UppyModal-close js-UppyModal-close" title="Close uploader modal" data-modal-hide>×</button>
 
           <ul class="UppyModalTabs" role="tablist"></ul>
-
-          <div class="UppyModalСontent"></div>
-
-          <div class="UppyModal-progressContainer">
-            progress here
-          </div>
+          <div class="UppyModalContent"></div>
+          <div class="UppyModal-progressContainer">progress here</div>
         </div>
       </div>
     `
   }
 
+  hideModal () {
+    this.isModalVisible = false
+    this.modalEl.setAttribute('aria-hidden', 'true')
+  }
+
+  showModal () {
+    this.isModalVisible = true
+    this.modalEl.removeAttribute('aria-hidden')
+  }
+
   hideAllTabPanels () {
     this.tabPanels.forEach(tabPanel => {
       tabPanel.style.display = 'none'
@@ -100,7 +117,7 @@ export default class Modal extends Plugin {
   }
 
   showTabPanel (id) {
-    const tabPanel = document.querySelector(id)
+    const tabPanel = document.querySelector(`.${id}`)
     tabPanel.style.display = 'block'
   }
 
@@ -108,8 +125,8 @@ export default class Modal extends Plugin {
     const tabs = Utils.qsa('.UppyModalTab-btn')
     this.tabPanels = []
     tabs.forEach(tab => {
-      const tabId = tab.getAttribute('href')
-      const tabPanel = document.querySelector(tabId)
+      const tabId = tab.getAttribute('data-open')
+      const tabPanel = document.querySelector(`.${tabId}`)
       this.tabPanels.push(tabPanel)
 
       tab.addEventListener('click', event => {
@@ -126,8 +143,17 @@ export default class Modal extends Plugin {
 
   install () {
     const node = document.createElement('div')
-    node.innerHTML = this.render()
-    this.container.appendChild(node)
+    document.body.appendChild(node)
+    node.outerHTML = this.render()
+    this.modalEl = document.querySelector('.UppyModal')
+
+    // Add events for opening and closing the modal
+    const hideModalTrigger = Utils.qsa('.js-UppyModal-close')
+    const showModalTrigger = document.querySelector(this.opts.trigger)
+
+    hideModalTrigger.forEach(trigger => trigger.addEventListener('click', this.hideModal))
+    showModalTrigger.addEventListener('click', this.showModal)
+
     this.initEvents()
   }
 }

+ 48 - 38
src/scss/_modal.scss

@@ -1,11 +1,7 @@
-body {
-  margin: 0;
-  font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
-  font-weight: 300;
-}
-
-* {
+.UppyModal * {
   box-sizing: border-box;
+  // margin: 0;
+  // padding: 0;
 }
 
 .UppyModal {
@@ -20,18 +16,38 @@ body {
   top: 0;
   left: 0;
   z-index: 1000;
+  font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
+  font-weight: 300;
 }
 
+.UppyModal[aria-hidden] {
+  display: none;
+}
+
+.UppyModal-overlay {}
+
 .UppyModal-inner {
   background-color: #EBEBEB;
   display: flex;
   flex-direction: row;
   height: 80vh;
   width: 75%;
+  position: relative;
 }
 
 .UppyModal-close {
-  display: none;
+  position: absolute;
+  top: 10px;
+  right: 10px;
+  padding: 0;
+  border: 0;
+  cursor: pointer;
+  background-color: transparent;
+  outline: none;
+  -webkit-appearance: none;
+  font-size: 30px;
+  line-height: 15px;
+  color: #525252;
 }
 
 .UppyModalContent {
@@ -47,18 +63,18 @@ body {
   display: none;
 }
 
-.UppyModalContent p,
-.UppyModalContent svg {
-  display: block;
-  margin: 0 auto;
-  text-align: center;
-}
+// .UppyModalContent p,
+// .UppyModalContent svg {
+//   display: block;
+//   margin: 0 auto;
+//   text-align: center;
+// }
 
-.UppyModalContent svg {
-  width: 200px;
-  height: 200px;
-  fill: rgba(120,110,60,0.055);
-}
+// .UppyModalContent svg {
+//   width: 200px;
+//   height: 200px;
+//   fill: rgba(120,110,60,0.055);
+// }
 
 .UppyModalTabs {
   list-style-type: none;
@@ -84,34 +100,25 @@ body {
   }
 }
 
-.UppyModalTab {
-
-}
-
-.UppyModalHeader {
-  background-color: #fff;
-  padding: 11px 0;
-  width: 100%;
-}
-
 .UppyModalTab-name {
+  display: inline-block;
+  vertical-align: middle;
   color: #eee;
   font-size: 14px;
   opacity: 0;
   transition: opacity 400ms 40ms;
-  vertical-align: middle;
 }
 
 .UppyModalTab-btn {
   width: 100%;
-  background-color: transparent;
-  border: 0;
-  cursor: pointer;
-  outline: none;
-  padding: 0;
   text-align: left;
   margin-bottom: 8px;
   padding: 12px;
+  cursor: pointer;
+  border: 0;
+  background-color: transparent;
+  outline: none;
+  -webkit-appearance: none;
 
   &:hover {
     background-color: #78bdf2;
@@ -122,12 +129,15 @@ body {
   fill: #eee;
   margin-right: 8px;
   width: 28px;
+  height: 28px;
   vertical-align: middle;
 }
 
-.UppyModalTab-name {
-  display: inline-block;
-}
+// .UppyModalHeader {
+//   background-color: #fff;
+//   padding: 11px 0;
+//   width: 100%;
+// }
 
 // .UppyModalHeader-logo svg {
 //   fill: #eee;

+ 1 - 1
website/src/examples/modal/app.es6

@@ -8,7 +8,7 @@ import Tus10 from '../../../../src/plugins/Tus10.js'
 
 const uppy = new Uppy({debug: true})
 uppy
-  .use(Modal)
+  .use(Modal, {trigger: '#uppyModalOpener'})
   .use(Dummy, {target: Modal})
   .use(ProgressBar, {target: Modal})
   .use(DragDrop, {target: Modal})