diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -9,7 +9,7 @@
   'names' => array(
     'conpherence.pkg.css' => 'ff161f2d',
     'conpherence.pkg.js' => 'b5b51108',
-    'core.pkg.css' => 'c56695d0',
+    'core.pkg.css' => '0c6e11ed',
     'core.pkg.js' => '1475bd91',
     'darkconsole.pkg.js' => '1f9a31bc',
     'differential.pkg.css' => 'a2755617',
@@ -114,7 +114,7 @@
     'rsrc/css/application/slowvote/slowvote.css' => 'a94b7230',
     'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
     'rsrc/css/application/uiexample/example.css' => '528b19de',
-    'rsrc/css/core/core.css' => '9f4cb463',
+    'rsrc/css/core/core.css' => '23beb330',
     'rsrc/css/core/remarkup.css' => 'd1a5e11e',
     'rsrc/css/core/syntax.css' => 'cae95e89',
     'rsrc/css/core/z-index.css' => '9d8f7c4b',
@@ -474,6 +474,7 @@
     'rsrc/js/core/behavior-autofocus.js' => '7319e029',
     'rsrc/js/core/behavior-badge-view.js' => '8ff5e24c',
     'rsrc/js/core/behavior-choose-control.js' => '327a00d1',
+    'rsrc/js/core/behavior-copy.js' => 'b0b8f86d',
     'rsrc/js/core/behavior-detect-timezone.js' => '4c193c96',
     'rsrc/js/core/behavior-device.js' => 'bb1dd507',
     'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '484a6e22',
@@ -644,6 +645,7 @@
     'javelin-behavior-passphrase-credential-control' => '3cb0b2fc',
     'javelin-behavior-phabricator-active-nav' => 'e379b58e',
     'javelin-behavior-phabricator-autofocus' => '7319e029',
+    'javelin-behavior-phabricator-clipboard-copy' => 'b0b8f86d',
     'javelin-behavior-phabricator-file-tree' => '88236f00',
     'javelin-behavior-phabricator-gesture' => '3ab51e2c',
     'javelin-behavior-phabricator-gesture-example' => '558829c2',
@@ -763,7 +765,7 @@
     'phabricator-busy' => '59a7976a',
     'phabricator-chatlog-css' => 'd295b020',
     'phabricator-content-source-view-css' => '4b8b05d4',
-    'phabricator-core-css' => '9f4cb463',
+    'phabricator-core-css' => '23beb330',
     'phabricator-countdown-css' => '16c52f5c',
     'phabricator-darklog' => 'c8e1ffe3',
     'phabricator-darkmessage' => 'c48cccdd',
@@ -1738,6 +1740,11 @@
       'javelin-dom',
       'phuix-dropdown-menu',
     ),
+    'b0b8f86d' => array(
+      'javelin-behavior',
+      'javelin-dom',
+      'javelin-stratcom',
+    ),
     'b23b49e6' => array(
       'javelin-behavior',
       'javelin-dom',
diff --git a/src/applications/uiexample/examples/PHUIButtonExample.php b/src/applications/uiexample/examples/PHUIButtonExample.php
--- a/src/applications/uiexample/examples/PHUIButtonExample.php
+++ b/src/applications/uiexample/examples/PHUIButtonExample.php
@@ -106,18 +106,49 @@
 
     $column = array();
     $icons = array(
-      'Comment' => 'fa-comment',
-      'Give Token' => 'fa-trophy',
-      'Reverse Time' => 'fa-clock-o',
-      'Implode Earth' => 'fa-exclamation-triangle red',
+      array(
+        'text' => pht('Comment'),
+        'icon' => 'fa-comment',
+      ),
+      array(
+        'text' => pht('Give Token'),
+        'icon' => 'fa-trophy',
+      ),
+      array(
+        'text' => pht('Reverse Time'),
+        'icon' => 'fa-clock-o',
+      ),
+      array(
+        'text' => pht('Implode Earth'),
+        'icon' => 'fa-exclamation-triangle',
+      ),
+      array(
+        'text' => pht('Copy "Quack" to Clipboard'),
+        'icon' => 'fa-clipboard',
+        'copy' => pht('Quack'),
+      ),
     );
-    foreach ($icons as $text => $icon) {
-      $column[] = id(new PHUIButtonView())
+    foreach ($icons as $text => $spec) {
+      $button = id(new PHUIButtonView())
         ->setTag('a')
         ->setColor(PHUIButtonView::GREY)
-        ->setIcon($icon)
-        ->setText($text)
+        ->setIcon(idx($spec, 'icon'))
+        ->setText(idx($spec, 'text'))
         ->addClass(PHUI::MARGIN_SMALL_RIGHT);
+
+      $copy = idx($spec, 'copy');
+      if ($copy !== null) {
+        Javelin::initBehavior('phabricator-clipboard-copy');
+
+        $button->addClass('clipboard-copy');
+        $button->addSigil('clipboard-copy');
+        $button->setMetadata(
+          array(
+            'text' => $copy,
+          ));
+      }
+
+      $column[] = $button;
     }
 
     $layout3 = id(new AphrontMultiColumnView())
diff --git a/webroot/rsrc/css/core/core.css b/webroot/rsrc/css/core/core.css
--- a/webroot/rsrc/css/core/core.css
+++ b/webroot/rsrc/css/core/core.css
@@ -173,3 +173,16 @@
   height: 2px;
   background: {$sky};
 }
+
+.clipboard-copy {
+  visibility: hidden;
+}
+
+.supports-clipboard .clipboard-copy {
+  visibility: visible;
+}
+
+.clipboard-buffer {
+  position: absolute;
+  left: -9999px;
+}
diff --git a/webroot/rsrc/js/core/behavior-copy.js b/webroot/rsrc/js/core/behavior-copy.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/core/behavior-copy.js
@@ -0,0 +1,43 @@
+/**
+ * @provides javelin-behavior-phabricator-clipboard-copy
+ * @requires javelin-behavior
+ *           javelin-dom
+ *           javelin-stratcom
+ * @javelin
+ */
+
+JX.behavior('phabricator-clipboard-copy', function() {
+
+  if (!document.queryCommandSupported) {
+    return;
+  }
+
+  if (!document.queryCommandSupported('copy')) {
+    return;
+  }
+
+  JX.DOM.alterClass(document.body, 'supports-clipboard', true);
+
+  JX.Stratcom.listen('click', 'clipboard-copy', function(e) {
+    e.kill();
+
+    var data = e.getNodeData('clipboard-copy');
+    var attr = {
+      value: data.text || '',
+      className: 'clipboard-buffer'
+    };
+
+    var node = JX.$N('textarea', attr);
+    document.body.appendChild(node);
+
+    try {
+      node.select();
+      document.execCommand('copy');
+    } catch (ignored) {
+      // Ignore any errors we hit.
+    }
+
+   JX.DOM.remove(node);
+  });
+
+});