diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -415,8 +415,8 @@
     'rsrc/js/application/phortune/phortune-credit-card-form.js' => '2290aeef',
     'rsrc/js/application/policy/behavior-policy-control.js' => 'd0c516d5',
     'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '5e9f347c',
-    'rsrc/js/application/projects/Workboard.js' => '761753ee',
-    'rsrc/js/application/projects/behavior-project-boards.js' => 'a1b41573',
+    'rsrc/js/application/projects/Workboard.js' => '555f521a',
+    'rsrc/js/application/projects/behavior-project-boards.js' => '9ed304e5',
     'rsrc/js/application/projects/behavior-project-create.js' => '065227cc',
     'rsrc/js/application/projects/behavior-reorder-columns.js' => 'e1d25dfb',
     'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf',
@@ -656,7 +656,7 @@
     'javelin-behavior-phui-profile-menu' => '12884df9',
     'javelin-behavior-policy-control' => 'd0c516d5',
     'javelin-behavior-policy-rule-editor' => '5e9f347c',
-    'javelin-behavior-project-boards' => 'a1b41573',
+    'javelin-behavior-project-boards' => '9ed304e5',
     'javelin-behavior-project-create' => '065227cc',
     'javelin-behavior-quicksand-blacklist' => '7927a7d3',
     'javelin-behavior-recurring-edit' => '5f1c4d5f',
@@ -723,7 +723,7 @@
     'javelin-view-renderer' => '6c2b09a2',
     'javelin-view-visitor' => 'efe49472',
     'javelin-websocket' => 'e292eaf4',
-    'javelin-workboard' => '761753ee',
+    'javelin-workboard' => '555f521a',
     'javelin-workflow' => '5b2e3e2b',
     'lightbox-attachment-css' => '7acac05d',
     'maniphest-batch-editor' => 'b0f0b6d5',
@@ -1223,6 +1223,16 @@
       'javelin-request',
       'javelin-typeahead-source',
     ),
+    '555f521a' => array(
+      'javelin-install',
+      'javelin-dom',
+      'javelin-util',
+      'javelin-vector',
+      'javelin-stratcom',
+      'javelin-workflow',
+      'phabricator-draggable-list',
+      'phabricator-drag-and-drop-file-upload',
+    ),
     '558829c2' => array(
       'javelin-stratcom',
       'javelin-behavior',
@@ -1395,16 +1405,6 @@
       'javelin-json',
       'phabricator-prefab',
     ),
-    '761753ee' => array(
-      'javelin-install',
-      'javelin-dom',
-      'javelin-util',
-      'javelin-vector',
-      'javelin-stratcom',
-      'javelin-workflow',
-      'phabricator-draggable-list',
-      'phabricator-drag-and-drop-file-upload',
-    ),
     '76b9fc3e' => array(
       'javelin-behavior',
       'javelin-stratcom',
@@ -1597,6 +1597,17 @@
       'javelin-dom',
       'javelin-vector',
     ),
+    '9ed304e5' => array(
+      'javelin-behavior',
+      'javelin-dom',
+      'javelin-util',
+      'javelin-vector',
+      'javelin-stratcom',
+      'javelin-workflow',
+      'phabricator-draggable-list',
+      'phabricator-drag-and-drop-file-upload',
+      'javelin-workboard',
+    ),
     '9f36c42d' => array(
       'javelin-behavior',
       'javelin-stratcom',
@@ -1616,17 +1627,6 @@
       'javelin-dom',
       'javelin-reactor-dom',
     ),
-    'a1b41573' => array(
-      'javelin-behavior',
-      'javelin-dom',
-      'javelin-util',
-      'javelin-vector',
-      'javelin-stratcom',
-      'javelin-workflow',
-      'phabricator-draggable-list',
-      'phabricator-drag-and-drop-file-upload',
-      'javelin-workboard',
-    ),
     'a2828756' => array(
       'javelin-dom',
       'javelin-util',
diff --git a/webroot/rsrc/js/application/projects/Workboard.js b/webroot/rsrc/js/application/projects/Workboard.js
--- a/webroot/rsrc/js/application/projects/Workboard.js
+++ b/webroot/rsrc/js/application/projects/Workboard.js
@@ -19,6 +19,7 @@
     this._boardNodes = {};
 
     this._setupCoverImageHandlers();
+    this._setupPanHandlers();
   },
 
   members: {
@@ -26,6 +27,10 @@
     _boardNodes: null,
     _currentBoard: null,
 
+    _panOrigin: null,
+    _panNode: null,
+    _panX: null,
+
     addBoard: function(board_phid, board_node) {
       this._currentBoard = board_phid;
       this._boardNodes[board_phid] = board_node;
@@ -73,7 +78,51 @@
       });
 
       drop.start();
+    },
+
+    _setupPanHandlers: function() {
+      var mousedown = JX.bind(this, this._onpanmousedown);
+      var mousemove = JX.bind(this, this._onpanmousemove);
+      var mouseup = JX.bind(this, this._onpanmouseup);
+
+      JX.Stratcom.listen('mousedown', 'workboard-shadow', mousedown);
+      JX.Stratcom.listen('mousemove', null, mousemove);
+      JX.Stratcom.listen('mouseup', null, mouseup);
+    },
+
+    _onpanmousedown: function(e) {
+      if (!JX.Device.isDesktop()) {
+        return;
+      }
+
+      if (e.getNode('workpanel')) {
+        return;
+      }
+
+      if (JX.Stratcom.pass()) {
+        return;
+      }
+
+      e.kill();
+
+      this._panOrigin = JX.$V(e);
+      this._panNode = e.getNode('workboard-shadow');
+      this._panX = this._panNode.scrollLeft;
+    },
+
+    _onpanmousemove: function(e) {
+      if (!this._panOrigin) {
+        return;
+      }
+
+      var cursor = JX.$V(e);
+      this._panNode.scrollLeft = this._panX + (this._panOrigin.x - cursor.x);
+    },
+
+    _onpanmouseup: function() {
+      this._panOrigin = null;
     }
+
   }
 
 });
diff --git a/webroot/rsrc/js/application/projects/behavior-project-boards.js b/webroot/rsrc/js/application/projects/behavior-project-boards.js
--- a/webroot/rsrc/js/application/projects/behavior-project-boards.js
+++ b/webroot/rsrc/js/application/projects/behavior-project-boards.js
@@ -351,47 +351,6 @@
         }
       });
 
-    // When the user drags the workboard background, pan the workboard
-    // horizontally. This allows you to scroll across cards with only the
-    // mouse, without shift + scrollwheel or using the scrollbar.
-
-    var pan_origin = null;
-    var pan_node = null;
-    var pan_x = null;
-
-    JX.Stratcom.listen('mousedown', 'workboard-shadow', function(e) {
-      if (!JX.Device.isDesktop()) {
-        return;
-      }
-
-      if (e.getNode('workpanel')) {
-        return;
-      }
-
-      if (JX.Stratcom.pass()) {
-        return;
-      }
-
-      e.kill();
-
-      pan_origin = JX.$V(e);
-      pan_node = e.getNode('workboard-shadow');
-      pan_x = pan_node.scrollLeft;
-    });
-
-    JX.Stratcom.listen('mousemove', null, function(e) {
-      if (!pan_origin) {
-        return;
-      }
-
-      var cursor = JX.$V(e);
-      pan_node.scrollLeft = pan_x + (pan_origin.x - cursor.x);
-    });
-
-    JX.Stratcom.listen('mouseup', null, function() {
-      pan_origin = null;
-    });
-
     return true;
   }