Upgrade gr-dropdown with additional capabilities

The shared dropdown component is made more-configurable, so it can be
reused in more contexts.
* The down-arrow is an flag that can be enabled on the dropdown, instead
  of added (and styled) at the use site.
* Items no longer need to be links to new URLs. They can be buttons with
  declared handlers.
* The dropdown trigger can be a link or a button, as configured by the
  link flag.

Change-Id: Ia9db3b66bf30bc56bf2ab4ce1f2292f51ab4754d
diff --git a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
index cead416..07c922a 100644
--- a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
+++ b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
@@ -34,7 +34,10 @@
         vertical-align: middle;
       }
     </style>
-    <gr-dropdown items=[[links]] top-content=[[topContent]]
+    <gr-dropdown
+        link
+        items=[[links]]
+        top-content=[[topContent]]
         horizontal-align="right">
         <span hidden$="[[_hasAvatars]]" hidden>[[account.name]]</span>
         <gr-avatar account="[[account]]" hidden$="[[!_hasAvatars]]" hidden
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html
index c3d9b16..74dc9e7 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html
@@ -52,23 +52,8 @@
       .linksTitle {
         color: black;
         display: inline-block;
-        padding-right: 1em;
         position: relative;
       }
-      .downArrow {
-        border-left: .36em solid transparent;
-        border-right: .36em solid transparent;
-        border-top: .36em solid #ccc;
-        height: 0;
-        position: absolute;
-        right: 0;
-        top: calc(50% - .05em);
-        transition: border-top-color 200ms;
-        width: 0;
-      }
-      .links li:hover .downArrow {
-        border-top-color: #666;
-      }
       .rightItems {
         align-items: center;
         display: flex;
@@ -119,10 +104,12 @@
         <template is="dom-repeat" items="[[_links]]" as="linkGroup">
           <li>
           <gr-dropdown
+              link
+              down-arrow
               items = [[linkGroup.links]]
               horizontal-align="left">
             <span class="linksTitle" id="[[linkGroup.title]]">
-              [[linkGroup.title]] <i class="downArrow"></i>
+              [[linkGroup.title]]
             </span>
           </gr-dropdown>
           </li>
diff --git a/polygerrit-ui/app/elements/shared/gr-button/gr-button.js b/polygerrit-ui/app/elements/shared/gr-button/gr-button.js
index 7e91b0e..800b1df 100644
--- a/polygerrit-ui/app/elements/shared/gr-button/gr-button.js
+++ b/polygerrit-ui/app/elements/shared/gr-button/gr-button.js
@@ -18,6 +18,10 @@
     is: 'gr-button',
 
     properties: {
+      link: {
+        type: Boolean,
+        reflectToAttribute: true,
+      },
       disabled: {
         type: Boolean,
         observer: '_disabledChanged',
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.html b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.html
index 95b03fc..1882500 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.html
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.html
@@ -38,6 +38,9 @@
         font: inherit;
         padding: .3em 0;
       }
+      :host[down-arrow] .dropdown-trigger {
+        padding-right: 1.4em;
+      }
       gr-avatar {
         height: 2em;
         width: 2em;
@@ -58,16 +61,17 @@
         font-weight: bold;
       }
       li .accountInfo,
-      li a {
+      li .itemAction {
+        cursor: pointer;
         display: block;
         padding: .85em 1em;
       }
-      li a:link,
-      li a:visited {
+      li .itemAction:link,
+      li .itemAction:visited {
         color: #00e;
         text-decoration: none;
       }
-      li a:hover {
+      li .itemAction:hover {
         background-color: #6B82D6;
         color: #fff;
       }
@@ -78,14 +82,30 @@
       .bold-text {
         font-weight: bold;
       }
+      :host:not([down-arrow]) .downArrow { display: none; }
+      :host[down-arrow] .downArrow {
+        border-left: .36em solid transparent;
+        border-right: .36em solid transparent;
+        border-top: .36em solid #ccc;
+        height: 0;
+        position: absolute;
+        right: .3em;
+        top: calc(50% - .05em);
+        transition: border-top-color 200ms;
+        width: 0;
+      }
+      .dropdown-trigger:hover .downArrow {
+        border-top-color: #666;
+      }
     </style>
-    <gr-button link class="dropdown-trigger" id="trigger"
+    <gr-button link="[[link]]" class="dropdown-trigger" id="trigger"
         on-tap="_showDropdownTapHandler">
       <content></content>
+       <i class="downArrow"></i>
     </gr-button>
     <iron-dropdown id="dropdown"
         vertical-align="top"
-        vertical-offset="40"
+        vertical-offset="[[verticalOffset]]"
         allow-outside-scroll="true"
         horizontal-align="[[horizontalAlign]]"
         on-tap="_handleDropdownTap">
@@ -109,7 +129,16 @@
               items="[[items]]"
               as="link"
               initial-count="75">
-            <li><a href$="[[_computeRelativeURL(link.url)]]">[[link.name]]</a>
+            <li>
+              <span
+                  class="itemAction"
+                  data-id$="[[link.id]]"
+                  on-tap="_handleItemTap"
+                  hidden$="[[link.url]]">[[link.name]]</span>
+              <a
+                  class="itemAction"
+                  href$="[[_computeRelativeURL(link.url)]]"
+                  hidden$="[[!link.url]]">[[link.name]]</a>
             </li>
           </template>
         </ul>
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js
index d10d219..d1fae7f 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js
@@ -17,6 +17,12 @@
   Polymer({
     is: 'gr-dropdown',
 
+    /**
+     * Fired when a non-link dropdown item with the given ID is tapped.
+     *
+     * @event tap-item-<id>
+     */
+
     properties: {
       items: Array,
       topContent: Object,
@@ -24,6 +30,20 @@
         type: String,
         value: 'left',
       },
+
+      /**
+       * Style the dropdown trigger as a link (rather than a button).
+       */
+      link: {
+        type: Boolean,
+        value: false,
+      },
+
+      verticalOffset: {
+        type: Number,
+        value: 40,
+      },
+
       _hasAvatars: String,
     },
 
@@ -53,5 +73,10 @@
       var host = window.location.host;
       return this._computeURLHelper(host, path);
     },
+
+    _handleItemTap: function(e) {
+      var id = e.target.getAttribute('data-id');
+      if (id) { this.dispatchEvent(new CustomEvent('tap-item-' + id)); }
+    },
   });
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html
index b2f2d21..2794caf 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html
@@ -70,5 +70,15 @@
       assert.isTrue(topItems[0].classList.contains('bold-text'));
       assert.isFalse(topItems[1].classList.contains('bold-text'));
     });
+
+    test('non link items', function() {
+      element.items = [
+          {name: 'item one', id: 'foo'}, {name: 'item two', id: 'bar'}];
+      var stub = sinon.stub();
+      element.addEventListener('tap-item-foo', stub);
+      flushAsynchronousOperations();
+      MockInteractions.tap(element.$$('.itemAction'));
+      assert.isTrue(stub.called);
+    });
   });
 </script>