Merge "Start a separate documentation page for core plugins"
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index bb4deb3..50b9b3e 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -3594,6 +3594,39 @@
 +
 Default is false.
 
+[[operator-alias]]
+=== Section operator alias
+
+Operator aliasing allows global aliases to be defined for query operators.
+Currently only change queries are supported. The alias name is the git
+config key name, and the operator being aliased is the git config value.
+
+For example:
+
+----
+[operator-alias "change"]
+  oldage = age
+  number = change
+----
+
+This section is particularly useful to alias operator names which may be
+long and clunky because they include a plugin name in them to a shorter
+name without the plugin name.
+
+Aliases are resolved dynamically at invocation time to any currently
+loaded versions of plugins. If the alias points to an operator provided
+by a plugin which is not currently loaded, or the plugin does not define
+the operator, then "unsupported operator" is returned to the user.
+
+Aliases will override existing operators. In the case of multiple aliases
+with the same name, the last one defined will be used.
+
+When the target of an alias doesn't exist, the operator with the name
+of the alias will be used (if present). This enables an admin to config
+the system to override a core operator with an operator provided by a
+plugin when present and otherwise fall back to the operator provided by
+core.
+
 [[pack]]
 === Section pack
 
diff --git a/WORKSPACE b/WORKSPACE
index f99a88b..3db0f99 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1059,18 +1059,18 @@
     sha1 = "0f5a654e4675769c716e5b387830d19b501ca191",
 )
 
-TESTCONTAINERS_VERSION = "1.12.2"
+TESTCONTAINERS_VERSION = "1.12.3"
 
 maven_jar(
     name = "testcontainers",
     artifact = "org.testcontainers:testcontainers:" + TESTCONTAINERS_VERSION,
-    sha1 = "660d2fab2021154b98ce91d3104ff673a7ab9348",
+    sha1 = "e424a4549640e120acceac641ac909fcda58bf62",
 )
 
 maven_jar(
     name = "testcontainers-elasticsearch",
     artifact = "org.testcontainers:elasticsearch:" + TESTCONTAINERS_VERSION,
-    sha1 = "88c751b2d787dfc19a91a7ee6fb623b881ffba5a",
+    sha1 = "c0796de5032070b8768ce78c78949b48f13c30db",
 )
 
 maven_jar(
diff --git a/java/com/google/gerrit/index/query/QueryBuilder.java b/java/com/google/gerrit/index/query/QueryBuilder.java
index d24cfeb..85dcf3e 100644
--- a/java/com/google/gerrit/index/query/QueryBuilder.java
+++ b/java/com/google/gerrit/index/query/QueryBuilder.java
@@ -29,6 +29,7 @@
 
 import com.google.common.base.Ascii;
 import com.google.common.base.CharMatcher;
+import com.google.common.base.MoreObjects;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.common.Nullable;
@@ -42,7 +43,9 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import org.antlr.runtime.tree.Tree;
 
 /**
@@ -184,6 +187,7 @@
 
   protected final Definition<T, Q> builderDef;
   private final ImmutableMap<String, OperatorFactory<T, Q>> opFactories;
+  protected Map<String, String> opAliases = Collections.emptyMap();
 
   protected QueryBuilder(
       Definition<T, Q> def,
@@ -220,6 +224,10 @@
     return toPredicate(QueryParser.parse(query));
   }
 
+  public void setOperatorAliases(Map<String, String> opAliases) {
+    this.opAliases = opAliases;
+  }
+
   /**
    * Parse multiple user-supplied query strings into a list of predicates.
    *
@@ -290,8 +298,12 @@
 
   @SuppressWarnings("unchecked")
   private Predicate<T> operator(String name, String value) throws QueryParseException {
+    String opName = MoreObjects.firstNonNull(opAliases.get(name), name);
     @SuppressWarnings("rawtypes")
-    OperatorFactory f = opFactories.get(name);
+    OperatorFactory f = opFactories.get(opName);
+    if (f == null && !opName.equals(name)) {
+      f = opFactories.get(name);
+    }
     if (f == null) {
       throw error("Unsupported operator " + name + ":" + value);
     }
diff --git a/java/com/google/gerrit/server/config/OperatorAliasConfig.java b/java/com/google/gerrit/server/config/OperatorAliasConfig.java
new file mode 100644
index 0000000..0c5fc6e
--- /dev/null
+++ b/java/com/google/gerrit/server/config/OperatorAliasConfig.java
@@ -0,0 +1,46 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.config;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.jgit.lib.Config;
+
+@Singleton
+public class OperatorAliasConfig {
+  private static final String SECTION = "operator-alias";
+  private static final String SUBSECTION_CHANGE = "change";
+  private final Config cfg;
+  private final Map<String, String> changeQueryOperatorAliases;
+
+  @Inject
+  OperatorAliasConfig(@GerritServerConfig Config cfg) {
+    this.cfg = cfg;
+    changeQueryOperatorAliases = new HashMap<>();
+    loadChangeOperatorAliases();
+  }
+
+  public Map<String, String> getChangeQueryOperatorAliases() {
+    return changeQueryOperatorAliases;
+  }
+
+  private void loadChangeOperatorAliases() {
+    for (String name : cfg.getNames(SECTION, SUBSECTION_CHANGE)) {
+      changeQueryOperatorAliases.put(name, cfg.getString(SECTION, SUBSECTION_CHANGE, name));
+    }
+  }
+}
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index d2fc77d..5d4edc9 100644
--- a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -63,6 +63,7 @@
 import com.google.gerrit.server.change.ChangeTriplet;
 import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.config.AllUsersName;
+import com.google.gerrit.server.config.OperatorAliasConfig;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.index.change.ChangeField;
 import com.google.gerrit.server.index.change.ChangeIndex;
@@ -219,6 +220,7 @@
     final SubmitDryRun submitDryRun;
     final GroupMembers groupMembers;
     final Provider<AnonymousUser> anonymousUserProvider;
+    final OperatorAliasConfig operatorAliasConfig;
 
     private final Provider<CurrentUser> self;
 
@@ -250,7 +252,8 @@
         StarredChangesUtil starredChangesUtil,
         AccountCache accountCache,
         GroupMembers groupMembers,
-        Provider<AnonymousUser> anonymousUserProvider) {
+        Provider<AnonymousUser> anonymousUserProvider,
+        OperatorAliasConfig operatorAliasConfig) {
       this(
           queryProvider,
           rewriter,
@@ -277,7 +280,8 @@
           starredChangesUtil,
           accountCache,
           groupMembers,
-          anonymousUserProvider);
+          anonymousUserProvider,
+          operatorAliasConfig);
     }
 
     private Arguments(
@@ -306,7 +310,8 @@
         StarredChangesUtil starredChangesUtil,
         AccountCache accountCache,
         GroupMembers groupMembers,
-        Provider<AnonymousUser> anonymousUserProvider) {
+        Provider<AnonymousUser> anonymousUserProvider,
+        OperatorAliasConfig operatorAliasConfig) {
       this.queryProvider = queryProvider;
       this.rewriter = rewriter;
       this.opFactories = opFactories;
@@ -333,6 +338,7 @@
       this.hasOperands = hasOperands;
       this.groupMembers = groupMembers;
       this.anonymousUserProvider = anonymousUserProvider;
+      this.operatorAliasConfig = operatorAliasConfig;
     }
 
     Arguments asUser(CurrentUser otherUser) {
@@ -362,7 +368,8 @@
           starredChangesUtil,
           accountCache,
           groupMembers,
-          anonymousUserProvider);
+          anonymousUserProvider,
+          operatorAliasConfig);
     }
 
     Arguments asUser(Account.Id otherId) {
@@ -407,6 +414,7 @@
   @Inject
   ChangeQueryBuilder(Arguments args) {
     this(mydef, args);
+    setupAliases();
   }
 
   @VisibleForTesting
@@ -415,6 +423,10 @@
     this.args = args;
   }
 
+  private void setupAliases() {
+    setOperatorAliases(args.operatorAliasConfig.getChangeQueryOperatorAliases());
+  }
+
   public Arguments getArgs() {
     return args;
   }
diff --git a/javatests/com/google/gerrit/acceptance/api/change/QueryChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/QueryChangeIT.java
index 92f914b..d73bab0 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/QueryChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/QueryChangeIT.java
@@ -18,6 +18,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.restapi.TopLevelResource;
@@ -97,6 +98,31 @@
     assertThat(result2.get(1).get(0)._moreChanges).isTrue();
   }
 
+  @Test
+  @SuppressWarnings("unchecked")
+  @GerritConfig(name = "operator-alias.change.numberaliastest", value = "change")
+  public void aliasQuery() throws Exception {
+    String cId1 = createChange().getChangeId();
+    String cId2 = createChange().getChangeId();
+    int numericId1 = gApi.changes().id(cId1).get()._number;
+    int numericId2 = gApi.changes().id(cId2).get()._number;
+
+    QueryChanges queryChanges = queryChangesProvider.get();
+    queryChanges.addQuery("numberaliastest:12345");
+    queryChanges.addQuery("numberaliastest:" + numericId1);
+    queryChanges.addQuery("numberaliastest:" + numericId2);
+
+    List<List<ChangeInfo>> result =
+        (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
+    assertThat(result).hasSize(3);
+    assertThat(result.get(0)).hasSize(0);
+    assertThat(result.get(1)).hasSize(1);
+    assertThat(result.get(2)).hasSize(1);
+
+    assertThat(result.get(1).get(0)._number).isEqualTo(numericId1);
+    assertThat(result.get(2).get(0)._number).isEqualTo(numericId2);
+  }
+
   private static void assertNoChangeHasMoreChangesSet(List<ChangeInfo> results) {
     for (ChangeInfo info : results) {
       assertThat(info._moreChanges).isNull();
diff --git a/javatests/com/google/gerrit/server/index/change/FakeQueryBuilder.java b/javatests/com/google/gerrit/server/index/change/FakeQueryBuilder.java
index 0753127..9a48a68 100644
--- a/javatests/com/google/gerrit/server/index/change/FakeQueryBuilder.java
+++ b/javatests/com/google/gerrit/server/index/change/FakeQueryBuilder.java
@@ -27,7 +27,7 @@
         new ChangeQueryBuilder.Definition<>(FakeQueryBuilder.class),
         new ChangeQueryBuilder.Arguments(
             null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-            null, null, null, null, indexes, null, null, null, null, null, null, null));
+            null, null, null, null, indexes, null, null, null, null, null, null, null, null));
   }
 
   @Operator
diff --git a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
index e766571..e9fcf65 100644
--- a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
+++ b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
@@ -180,6 +180,7 @@
 
     SEARCH: 'SEARCH',
     SEND_REPLY: 'SEND_REPLY',
+    EMOJI_DROPDOWN: 'EMOJI_DROPDOWN',
   };
 
   const _help = new Map();
@@ -292,6 +293,8 @@
       'Show/hide selected inline diff');
 
   _describe(Shortcut.SEND_REPLY, ShortcutSection.REPLY_DIALOG, 'Send reply');
+  _describe(Shortcut.EMOJI_DROPDOWN, ShortcutSection.REPLY_DIALOG,
+      'Emoji dropdown');
 
   // Must be declared outside behavior implementation to be accessed inside
   // behavior functions.
@@ -423,6 +426,9 @@
     }
 
     describeBinding(binding) {
+      if (binding.length === 1) {
+        return [binding];
+      }
       return binding.split(':')[0].split('+').map(part => {
         switch (part) {
           case 'shift':
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html
index 29f97ce..7e6739d 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html
@@ -105,10 +105,6 @@
       .u-red {
         color: var(--vote-text-color-disliked);
       }
-      .label.u-green:not(.u-monospace),
-      .label.u-red:not(.u-monospace) {
-        font-size: var(--font-size-h3);
-      }
       .u-gray-background {
         background-color: var(--table-header-background-color);
       }
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
index 1c0edfc..cdad618 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
@@ -54,7 +54,7 @@
         max-width: 20ch;
         overflow: hidden;
         text-overflow: ellipsis;
-        vertical-align: middle;
+        vertical-align: top;
         white-space: nowrap;
       }
       gr-editable-label {
diff --git a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements.html b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements.html
index 1e0be09..614d2f6 100644
--- a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements.html
+++ b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements.html
@@ -46,8 +46,8 @@
       iron-icon {
         color: inherit;
       }
-      .name {
-        font-weight: var(--font-weight-bold);
+      .status iron-icon {
+        vertical-align: top;
       }
       section {
         display: table-row;
@@ -57,16 +57,15 @@
       }
       .title {
         min-width: 10em;
-        padding: var(--spacing-m) var(--spacing-m) 0 var(--requirements-horizontal-padding);
-        vertical-align: top;
+        padding: var(--spacing-s) var(--spacing-m) 0 var(--requirements-horizontal-padding);
       }
       .value {
-        padding: var(--spacing-m) var(--spacing-m) 0 0;
-        vertical-align: middle;
+        padding: var(--spacing-s) var(--spacing-m) 0 0;
       }
       .title,
       .value {
         display: table-cell;
+        vertical-align: top;
       }
       .hidden {
         display: none;
@@ -89,7 +88,7 @@
         float: right;
       }
       .spacer {
-        height: .5em;
+        height: var(--spacing-m);
       }
     </style>
     <template
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
index 258e516..bb87473 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
@@ -70,7 +70,7 @@
         background-color: var(--table-header-background-color);
         border-bottom: 1px solid var(--border-color);
         display: flex;
-        padding: var(--spacing-m) var(--spacing-l);
+        padding: var(--spacing-s) var(--spacing-l);
         z-index: 99;  /* Less than gr-overlay's backdrop */
       }
       .header.editMode {
@@ -230,7 +230,7 @@
       paper-tabs {
         background-color: var(--table-header-background-color);
         border-top: 1px solid var(--border-color);
-        height: 3rem;
+        height: calc(var(--line-height-normal) + 2*var(--spacing-m));
         --paper-tabs-selection-bar-color: var(--link-color);
       }
       paper-tab {
@@ -292,7 +292,7 @@
           align-items: flex-start;
           flex-direction: column;
           flex: 1;
-          padding: var(--spacing-m) var(--spacing-l);
+          padding: var(--spacing-s) var(--spacing-l);
         }
         gr-change-star {
           vertical-align: middle;
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
index 94f60b1..2a6c18a 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
@@ -312,6 +312,7 @@
     keyboardShortcuts() {
       return {
         [this.Shortcut.SEND_REPLY]: null, // DOC_ONLY binding
+        [this.Shortcut.EMOJI_DROPDOWN]: null, // DOC_ONLY binding
         [this.Shortcut.REFRESH_CHANGE]: '_handleRefreshChange',
         [this.Shortcut.OPEN_REPLY_DIALOG]: '_handleOpenReplyDialog',
         [this.Shortcut.OPEN_DOWNLOAD_DIALOG]:
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
index 480e3a0..e31ce26 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
@@ -48,7 +48,7 @@
         background-color: var(--table-header-background-color);
         border-top: 1px solid var(--border-color);
         display: flex;
-        padding: 6px var(--spacing-l);
+        padding: var(--spacing-s) var(--spacing-l);
       }
       .patchInfo-left {
         align-items: baseline;
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
index 5708ff3..a17c8a5 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
@@ -48,7 +48,7 @@
         align-items: center;
         border-top: 1px solid var(--border-color);
         display: flex;
-        min-height: 2.25em;
+        min-height: calc(var(--line-height-normal) + 2*var(--spacing-s));
         padding: var(--spacing-xs) var(--spacing-l) var(--spacing-xs) calc(var(--spacing-l) - .35rem);
       }
       :host(.loading) .row {
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.html b/polygerrit-ui/app/elements/change/gr-message/gr-message.html
index 3b0165e..9457ed0 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.html
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.html
@@ -57,7 +57,7 @@
       }
       .contentContainer {
         margin-left: calc(var(--spacing-l) + 2.5em);
-        padding: 10px 0;
+        padding: var(--spacing-m) 0;
       }
       .showAvatar.collapsed .contentContainer {
         margin-left: calc(var(--spacing-l) + 1.75em);
@@ -73,13 +73,13 @@
       }
       .collapsed gr-avatar {
         top: var(--spacing-m);
-        height: 1.75em;
-        width: 1.75em;
+        height: var(--line-height-normal);
+        width: var(--line-height-normal);
       }
       .expanded gr-avatar {
-        top: 12px;
-        height: 2.5em;
-        width: 2.5em;
+        top: var(--spacing-l);
+        height: var(--line-height-h1);
+        width: var(--line-height-h1);
       }
       .name {
         font-weight: var(--font-weight-bold);
@@ -143,6 +143,7 @@
       }
       .dateContainer iron-icon {
         cursor: pointer;
+        vertical-align: top;
       }
       .replyContainer {
         padding: var(--spacing-m) 0 0 0;
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.html b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.html
index 91d970e..d71beb4 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.html
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.html
@@ -38,7 +38,7 @@
         display: flex;
         justify-content: space-between;
         min-height: 3.2em;
-        padding: var(--spacing-m) var(--spacing-l);
+        padding: var(--spacing-s) var(--spacing-l);
       }
       #messageControlsContainer {
         padding: 0 var(--spacing-l);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
index 06ee4dc..40a02a3 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
@@ -72,7 +72,7 @@
         justify-content: space-between;
       }
       header {
-        padding: var(--spacing-m) var(--spacing-l);
+        padding: var(--spacing-s) var(--spacing-l);
       }
       .patchRangeLeft {
         align-items: center;
@@ -113,10 +113,7 @@
       }
       .subHeader {
         flex-wrap: wrap;
-        padding: 0 var(--spacing-l) var(--spacing-m);
-      }
-      .subHeader > div {
-        margin-top: var(--spacing-xs);
+        padding: 0 var(--spacing-l) var(--spacing-s);
       }
       .prefsButton {
         text-align: right;
@@ -158,7 +155,7 @@
       }
       @media screen and (max-width: 50em) {
         header {
-          padding: var(--spacing-m) var(--spacing-l);
+          padding: var(--spacing-s) var(--spacing-l);
         }
         .dash {
           display: none;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index c99b8ab..f63a679 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -44,8 +44,8 @@
       }
       :host {
         font-family: var(--monospace-font-family, ''), 'Roboto Mono';
-        font-size: var(--font-size, 12px);
-        line-height: var(--line-height-mono, 16px);
+        font-size: var(--font-size, var(--font-size-mono, 12px));
+        line-height: var(--line-height-mono, 1.334);
       }
 
       .thread-group {
diff --git a/polygerrit-ui/app/elements/gr-app-element.js b/polygerrit-ui/app/elements/gr-app-element.js
index fc2ec20..2a73be3 100644
--- a/polygerrit-ui/app/elements/gr-app-element.js
+++ b/polygerrit-ui/app/elements/gr-app-element.js
@@ -170,6 +170,8 @@
     _bindKeyboardShortcuts() {
       this.bindShortcut(this.Shortcut.SEND_REPLY,
           this.DOC_ONLY, 'ctrl+enter', 'meta+enter');
+      this.bindShortcut(this.Shortcut.EMOJI_DROPDOWN,
+          this.DOC_ONLY, ':');
 
       this.bindShortcut(
           this.Shortcut.OPEN_SHORTCUT_HELP_DIALOG, '?');
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html
index 17de8b1..070f94f 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html
@@ -39,14 +39,18 @@
         border: 1px solid var(--border-color);
       }
       paper-input {
-        height: 100%;
+        height: var(--line-height-normal);
         width: 100%;
         @apply --gr-autocomplete;
         --paper-input-container: {
           padding: 0;
         }
         --paper-input-container-input: {
-          font-size: inherit;
+          font-size: var(--font-size-normal);
+          /* paper-input insists on adding 1px above and below such that we have
+             to substract that to get a line height that is consistent with
+             normal text. */
+          line-height: calc(var(--line-height-normal) - 2px);
         }
         --paper-input-container-underline: {
           display: none;
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
index d834776..559603d 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
@@ -28,6 +28,12 @@
 <dom-module id="gr-comment-thread">
   <template>
     <style include="shared-styles">
+      :host {
+        font-family: var(--font-family);
+        font-size: var(--font-size-normal);
+        font-weight: var(--font-weight-normal);
+        line-height: var(--line-height-normal);
+      }
       gr-button {
         margin-left: var(--spacing-m);
       }
@@ -37,12 +43,12 @@
       }
       #container {
         background-color: var(--comment-background-color);
-        border: 1px solid var(--border-color);
         color: var(--comment-text-color);
         display: block;
-        margin-bottom: 1px;
+        margin: 0 4px 4px 4px;
         white-space: normal;
-
+        box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
+        border-radius: 4px;
         /** This is required for firefox to continue the inheritance */
         -webkit-user-select: inherit;
         -moz-user-select: inherit;
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.html b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.html
index 7c9b441..f77e35b 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.html
@@ -74,11 +74,6 @@
         flex: 1;
         overflow: hidden;
       }
-      .authorName,
-      .draftLabel,
-      .draftTooltip {
-        font-weight: var(--font-weight-bold);
-      }
       .draftLabel,
       .draftTooltip {
         color: var(--deemphasized-text-color);
@@ -119,6 +114,13 @@
         display: flex;
         justify-content: flex-end;
       }
+      .rightActions gr-button {
+        --gr-button: {
+          height: 20px;
+          padding: 0 var(--spacing-s);
+          color: var(--default-button-text-color);
+        }
+      }
       .editMessage {
         display: none;
         margin: var(--spacing-m) 0;
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.html b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.html
index 330f880..3273b3d 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.html
+++ b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.html
@@ -39,7 +39,6 @@
       label {
         color: var(--deemphasized-text-color);
         display: inline-block;
-        font-weight: var(--font-weight-bold);
         overflow: hidden;
         text-overflow: ellipsis;
         white-space: nowrap;
diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html
index 4ff031a..5461469 100644
--- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html
+++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html
@@ -40,8 +40,9 @@
         display: flex;
         justify-content: center;
         margin-right: var(--spacing-s);
-        padding: var(--spacing-xxs) var(--spacing-m);
+        padding: 0;
         @apply --vote-chip-styles;
+        border-width: 0;
       }
       .max {
         background-color: var(--vote-color-approved);
@@ -59,16 +60,17 @@
         display: none;
       }
       td {
-        vertical-align: middle;
+        vertical-align: top;
       }
       tr {
-        min-height: 2.25em;
+        min-height: var(--line-height-normal);
       }
       gr-button {
+        vertical-align: top;
         --gr-button: {
-          height: 2em;
+          height: var(--line-height-normal);
+          width: var(--line-height-normal);
           padding: 0;
-          width: 2em;
         }
       }
       gr-button[disabled] iron-icon {
@@ -78,8 +80,8 @@
         margin-right: var(--spacing-xs);
       }
       iron-icon {
-        height: 1.2em;
-        width: 1.2em;
+        height: calc(var(--line-height-normal) - 2px);
+        width: calc(var(--line-height-normal) - 2px);
       }
       .labelValueContainer:not(:first-of-type) td {
         padding-top: var(--spacing-s);
diff --git a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.html b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.html
index ad1a039..2df4988 100644
--- a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.html
+++ b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.html
@@ -35,6 +35,9 @@
       }
       :host(.monospace) {
         font-family: var(--monospace-font-family);
+        font-size: var(--font-size-mono);
+        font-weight: var(--font-weight-normal);
+        line-height: var(--line-height-mono);
       }
       #emojiSuggestions {
         font-family: var(--font-family);
@@ -59,6 +62,10 @@
 
         /** This is needed for firefox */
         --iron-autogrow-textarea_-_white-space: pre-wrap;
+
+        /* iron-autogrow-textarea has a "-webkit-appearance: textarea" :host
+           css rule, which prevents overriding the border color. Clear that. */
+        -webkit-appearance: none;
       }
       #textarea.noBorder {
         border: none;
@@ -88,15 +95,17 @@
         on-dropdown-closed="_resetEmojiDropdown"
         on-item-selected="_handleEmojiSelect">
     </gr-autocomplete-dropdown>
-    <iron-autogrow-textarea
-        id="textarea"
-        autocomplete="[[autocomplete]]"
-        placeholder=[[placeholder]]
-        disabled="[[disabled]]"
-        rows="[[rows]]"
-        max-rows="[[maxRows]]"
-        value="{{text}}"
-        on-bind-value-changed="_onValueChanged"></iron-autogrow-textarea>
+    <div id="borderWrapper">
+      <iron-autogrow-textarea
+          id="textarea"
+          autocomplete="[[autocomplete]]"
+          placeholder=[[placeholder]]
+          disabled="[[disabled]]"
+          rows="[[rows]]"
+          max-rows="[[maxRows]]"
+          value="{{text}}"
+          on-bind-value-changed="_onValueChanged"></iron-autogrow-textarea>
+    </div>
     <gr-reporting id="reporting"></gr-reporting>
   </template>
   <script src="gr-textarea.js"></script>
diff --git a/polygerrit-ui/app/styles/gr-change-list-styles.html b/polygerrit-ui/app/styles/gr-change-list-styles.html
index a6b2497..345363b 100644
--- a/polygerrit-ui/app/styles/gr-change-list-styles.html
+++ b/polygerrit-ui/app/styles/gr-change-list-styles.html
@@ -96,7 +96,7 @@
         text-decoration: underline;
       }
       .cell {
-        height: 2.25rem;
+        padding: var(--spacing-s) 0;
       }
       .star {
         padding: 0;
diff --git a/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.html b/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.html
index d7bf975..ae14976 100644
--- a/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.html
+++ b/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.html
@@ -33,10 +33,9 @@
 
       .title {
         color: var(--deemphasized-text-color);
-        font-weight: var(--font-weight-bold);
         max-width: 20em;
         padding-left: var(--metadata-horizontal-padding);
-        padding-right: var(--spacing-m);
+        padding-right: var(--metadata-horizontal-padding);
         word-break: break-word;
       }
 
diff --git a/polygerrit-ui/app/styles/main.css b/polygerrit-ui/app/styles/main.css
index 0d61b8a..4c85176 100644
--- a/polygerrit-ui/app/styles/main.css
+++ b/polygerrit-ui/app/styles/main.css
@@ -26,10 +26,10 @@
   -webkit-text-size-adjust: none;
   /*
    * Default browser fonts are 16px. We want users with default settings to see
-   * a base font of 13px. 13/16 = .8125. This needs to be in html because
+   * a base font of 14px. 14/16 = .875. This needs to be in html because
    * can use rems based on this font-size throughout the app.
    */
-  font-size: .8125em;
+  font-size: .875em;
 }
 html,
 body {
diff --git a/polygerrit-ui/app/styles/themes/app-theme.html b/polygerrit-ui/app/styles/themes/app-theme.html
index 6369096..7ae639a 100644
--- a/polygerrit-ui/app/styles/themes/app-theme.html
+++ b/polygerrit-ui/app/styles/themes/app-theme.html
@@ -75,17 +75,18 @@
   /* fonts */
   --font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
   --monospace-font-family: 'Roboto Mono', Menlo, 'Lucida Console', Monaco, monospace;
-  --font-size-small: .92rem; /* 12px */
-  --font-size-normal: 1rem;  /* 13px */
-  --font-size-h3: 1.154rem;  /* 15px */
-  --font-size-h2: 1.5rem;    /* 19.5px */
-  --font-size-h1: 2rem;      /* 26px */
-  --line-height-mono: 16px;
-  --line-height-small: 1.4;  /* 16.8px */
-  --line-height-normal: 1.4; /* 18.2px */
-  --line-height-h3: 1.4;     /* 21.0px */
-  --line-height-h2: 1.4;     /* 27.3px */
-  --line-height-h1: 1.4;     /* 36.4px */
+  --font-size-mono: 12px;     /* 12px */
+  --font-size-small: .857rem; /* 12px */
+  --font-size-normal: 1rem;   /* 14px */
+  --font-size-h3: 1.143rem;   /* 16px */
+  --font-size-h2: 1.429rem;   /* 20px */
+  --font-size-h1: 1.714rem;   /* 24px */
+  --line-height-mono: 1.334;      /* 16px */
+  --line-height-small: 1.143rem;  /* 16px */
+  --line-height-normal: 1.429rem; /* 20px */
+  --line-height-h3: 1.714rem;     /* 24px */
+  --line-height-h2: 2rem;         /* 28px */
+  --line-height-h1: 2.286rem;     /* 32px */
   --font-weight-normal: 400;
   --font-weight-bold: 500;