瀏覽代碼

Implement a modal system

I decided to create my own and not to use a community package, because
1. it's straightforward
2. it's better integrated with our others libs such as EscapeActions
3. monitoring third-party packages evolutions (eg, CSS changes) is a
   lot of work.

This is basically the same rationale than for our other generic UI
components such as the Popup/Popover.

This commit also slightly modify the general layout to remove
unnecessary wrapper DOM nodes.
Maxime Quandalle 9 年之前
父節點
當前提交
9faaf07e02

+ 1 - 0
.jshintrc

@@ -76,6 +76,7 @@
     "Filter": true,
     "Filter": true,
     "Mixins": true,
+    "Modal": true,
     "MultiSelection": true,
     "Popup": true,
     "Sidebar": true,

+ 1 - 1
client/components/lists/main.js

@@ -30,7 +30,7 @@ BlazeComponent.extendComponent({
     $cards.sortable({
       connectWith: '.js-minicards',
       tolerance: 'pointer',
-      appendTo: '#surface',
+      appendTo: 'body',
       helper: function(evt, item) {
         var helper = item.clone();
         if (MultiSelection.isActive()) {

+ 10 - 4
client/components/main/layouts.jade

@@ -11,10 +11,16 @@ template(name="userFormsLayout")
     +Template.dynamic(template=content)
 
 template(name="defaultLayout")
-  #surface
-    +header
-    #content
-      +Template.dynamic(template=content)
+  +header
+  #content
+    +Template.dynamic(template=content)
+  if (Modal.isOpen)
+    #modal
+      .overlay
+      .modal-content
+        a.modal-close-btn.js-close-modal
+          i.fa.fa-times-thin
+        +Template.dynamic(template=Modal.getTemplateName)
 
 template(name="notFound")
   +message(label='page-not-found')

+ 11 - 3
client/components/main/layouts.js

@@ -1,5 +1,13 @@
-Meteor.subscribe('boards');
+Meteor.subscribe('boards')
+
+BlazeLayout.setRoot('body')
 
 Template.userFormsLayout.onRendered(function() {
-  EscapeActions.executeAll();
-});
+  EscapeActions.executeAll()
+})
+
+Template.defaultLayout.events({
+  'click .js-close-modal': () => {
+    Modal.close()
+  }
+})

+ 24 - 2
client/components/main/layouts.styl

@@ -19,8 +19,6 @@ body
   position: relative
   z-index: 0
   overflow-y: auto
-
-#surface
   display: flex
   flex-direction: column
   min-height: 100vh
@@ -30,6 +28,30 @@ body
   position: relative
   flex: 1
 
+#modal
+  position: absolute
+  top: 0
+  bottom: 0
+  left: 0
+  right: 0
+  background: rgba(0, 0, 0, 0.6)
+  z-index: 100
+  overflow-y: auto
+
+  .modal-content
+    width: 660px
+    min-height: 160px
+    margin: 42px auto
+    border-radius: 4px
+    background: darken(white, 13%)
+    z-index: 110
+
+    .modal-close-btn
+      display: block
+      float: right
+      margin: 12px
+      font-size: 24px
+
 h1
   font-size: 22px
   line-height: 1.2em

+ 1 - 0
client/lib/escapeActions.js

@@ -13,6 +13,7 @@ EscapeActions = {
     'popup-close',
     'inlinedForm',
     'detailsPane',
+    'modalWindow',
     'multiselection',
     'sidebarView'
   ],

+ 31 - 0
client/lib/modal.js

@@ -0,0 +1,31 @@
+const closedValue = null
+
+Modal = new class {
+  constructor() {
+    this._currentModal = new ReactiveVar(closedValue)
+  }
+
+  getTemplateName() {
+    return this._currentModal.get()
+  }
+
+  isOpen() {
+    return this.getTemplateName() !== closedValue
+  }
+
+  close() {
+    this._currentModal.set(closedValue)
+  }
+
+  open(modalName) {
+    this._currentModal.set(modalName)
+  }
+};
+
+Blaze.registerHelper('Modal', Modal)
+
+EscapeActions.register('modalWindow',
+  () => Modal.close(),
+  () => Modal.isOpen(),
+  { noClickEscapeOn: '.modal-content' }
+);