Bug 1490366 - Part 2: Convert about:addons to card UI r=aswan,jaws
authorMark Striemer <mstriemer@mozilla.com>
Sun, 14 Oct 2018 19:22:59 +0000
changeset 489521 cb62a8b8a525d7442d53ee6441fe3f60608b0160
parent 489520 a19f3794f0c9b63868f7e4e028bc6a76fb199930
child 489522 0a45a5634cf18f31b1ab848f4c71b34cabe80ec5
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersaswan, jaws
bugs1490366
milestone64.0a1
Bug 1490366 - Part 2: Convert about:addons to card UI r=aswan,jaws Differential Revision: https://phabricator.services.mozilla.com/D8102
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/content/extensions.xml
toolkit/mozapps/extensions/content/extensions.xul
toolkit/mozapps/extensions/test/browser/browser.ini
toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js
toolkit/mozapps/extensions/test/browser/browser_bug562854.js
toolkit/mozapps/extensions/test/browser/browser_details.js
toolkit/mozapps/extensions/test/browser/browser_legacy_pre57.js
toolkit/mozapps/extensions/test/browser/browser_list.js
toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js
toolkit/mozapps/extensions/test/browser/browser_pluginprefs.js
toolkit/mozapps/extensions/test/browser/browser_uninstalling.js
toolkit/themes/shared/extensions/extensions.inc.css
toolkit/themes/shared/in-content/common.inc.css
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -120,24 +120,16 @@ function initialize(event) {
   let viewCommandSet = document.getElementById("viewCommandSet");
   viewCommandSet.addEventListener("commandupdate", function(event) {
     gViewController.updateCommands();
   });
   viewCommandSet.addEventListener("command", function(event) {
     gViewController.doCommand(event.target.id);
   });
 
-  let detailScreenshot = document.getElementById("detail-screenshot");
-  detailScreenshot.addEventListener("load", function(event) {
-    this.removeAttribute("loading");
-  });
-  detailScreenshot.addEventListener("error", function(event) {
-    this.setAttribute("loading", "error");
-  });
-
   let addonPage = document.getElementById("addons-page");
   addonPage.addEventListener("dragenter", function(event) {
     gDragDrop.onDragOver(event);
   });
   addonPage.addEventListener("dragover", function(event) {
     gDragDrop.onDragOver(event);
   });
   addonPage.addEventListener("drop", function(event) {
@@ -1468,17 +1460,17 @@ function shouldShowVersionNumber(aAddon)
     return !/@personas\.mozilla\.org$/.test(aAddon.id);
 
   return true;
 }
 
 function createItem(aObj, aIsInstall) {
   let item = document.createXULElement("richlistitem");
 
-  item.setAttribute("class", "addon addon-view");
+  item.setAttribute("class", "addon addon-view card");
   item.setAttribute("name", aObj.name);
   item.setAttribute("type", aObj.type);
 
   if (aIsInstall) {
     item.mInstall = aObj;
 
     if (aObj.state != AddonManager.STATE_INSTALLED) {
       item.setAttribute("status", "installing");
@@ -2615,34 +2607,16 @@ var gDetailView = {
     var version = document.getElementById("detail-version");
     if (shouldShowVersionNumber(aAddon)) {
       version.hidden = false;
       version.value = aAddon.version;
     } else {
       version.hidden = true;
     }
 
-    var screenshotbox = document.getElementById("detail-screenshot-box");
-    var screenshot = document.getElementById("detail-screenshot");
-    if (aAddon.screenshots && aAddon.screenshots.length > 0) {
-      if (aAddon.screenshots[0].thumbnailURL) {
-        screenshot.src = aAddon.screenshots[0].thumbnailURL;
-        screenshot.width = aAddon.screenshots[0].thumbnailWidth;
-        screenshot.height = aAddon.screenshots[0].thumbnailHeight;
-      } else {
-        screenshot.src = aAddon.screenshots[0].url;
-        screenshot.width = aAddon.screenshots[0].width;
-        screenshot.height = aAddon.screenshots[0].height;
-      }
-      screenshot.setAttribute("loading", "true");
-      screenshotbox.hidden = false;
-    } else {
-      screenshotbox.hidden = true;
-    }
-
     var desc = document.getElementById("detail-desc");
     desc.textContent = aAddon.description;
 
     var fullDesc = document.getElementById("detail-fulldesc");
     if (aAddon.getFullDescription) {
       fullDesc.textContent = "";
       fullDesc.append(aAddon.getFullDescription(document));
       fullDesc.hidden = false;
--- a/toolkit/mozapps/extensions/content/extensions.xml
+++ b/toolkit/mozapps/extensions/content/extensions.xml
@@ -620,41 +620,33 @@
                 <xul:spacer flex="5000"/> <!-- Necessary to make the name crop -->
               </xul:hbox>
             <xul:label anonid="date-updated" class="date-updated"
                        unknown="&addon.unknownDate;"/>
           </xul:hbox>
 
           <xul:hbox class="advancedinfo-container" flex="1">
             <xul:vbox class="description-outer-container" flex="1">
-              <xul:hbox class="description-container">
-                <xul:label anonid="description" class="description" crop="end" flex="1"/>
-                <xul:button anonid="details-btn" class="details button-link"
-                            label="&addon.details.label;"
-                            tooltiptext="&addon.details.tooltip;"
-                            oncommand="document.getBindingParent(this).showInDetailView();"/>
-                <xul:spacer flex="5000"/> <!-- Necessary to make the description crop -->
-              </xul:hbox>
-              <xul:vbox anonid="relnotes-container" class="relnotes-container">
-                <xul:label class="relnotes-header" value="&addon.releaseNotes.label;"/>
-                <xul:label anonid="relnotes-loading" value="&addon.loadingReleaseNotes.label;"/>
-                <xul:label anonid="relnotes-error" hidden="true"
-                           value="&addon.errorLoadingReleaseNotes.label;"/>
-                <xul:vbox anonid="relnotes" class="relnotes"/>
-              </xul:vbox>
               <xul:hbox class="relnotes-toggle-container">
                 <xul:button anonid="relnotes-toggle-btn" class="relnotes-toggle"
                             hidden="true" label="&cmd.showReleaseNotes.label;"
                             tooltiptext="&cmd.showReleaseNotes.tooltip;"
                             showlabel="&cmd.showReleaseNotes.label;"
                             showtooltip="&cmd.showReleaseNotes.tooltip;"
                             hidelabel="&cmd.hideReleaseNotes.label;"
                             hidetooltip="&cmd.hideReleaseNotes.tooltip;"
                             oncommand="document.getBindingParent(this).toggleReleaseNotes();"/>
               </xul:hbox>
+              <xul:vbox anonid="relnotes-container" class="relnotes-container">
+                <xul:label class="relnotes-header" value="&addon.releaseNotes.label;"/>
+                <xul:label anonid="relnotes-loading" value="&addon.loadingReleaseNotes.label;"/>
+                <xul:label anonid="relnotes-error" hidden="true"
+                           value="&addon.errorLoadingReleaseNotes.label;"/>
+                <xul:vbox anonid="relnotes" class="relnotes"/>
+              </xul:vbox>
             </xul:vbox>
           </xul:hbox>
         </xul:vbox>
         <xul:vbox class="status-control-wrapper">
           <xul:hbox class="status-container">
             <xul:hbox anonid="checking-update" hidden="true">
               <xul:image class="spinner"/>
               <xul:label value="&addon.checkingForUpdates.label;"/>
@@ -789,20 +781,16 @@
       </field>
       <field name="_icon">
         document.getAnonymousElementByAttribute(this, "anonid", "icon");
       </field>
       <field name="_dateUpdated">
         document.getAnonymousElementByAttribute(this, "anonid",
                                                 "date-updated");
       </field>
-      <field name="_description">
-        document.getAnonymousElementByAttribute(this, "anonid",
-                                                "description");
-      </field>
       <field name="_stateMenulist">
         document.getAnonymousElementByAttribute(this, "anonid",
                                                 "state-menulist");
       </field>
       <field name="_askToActivateMenuitem">
         document.getAnonymousElementByAttribute(this, "anonid",
                                                 "ask-to-activate-menuitem");
       </field>
@@ -914,21 +902,16 @@
           this.setAttribute("name", aAddon.name);
 
           var iconURL = AddonManager.getPreferredIconURL(aAddon, 32, window);
           if (iconURL)
             this._icon.src = iconURL;
           else
             this._icon.src = "";
 
-          if (this.mAddon.description)
-            this._description.value = this.mAddon.description;
-          else
-            this._description.hidden = true;
-
           let legacyWarning = legacyExtensionsEnabled && !this.mAddon.install &&
             isLegacyExtension(this.mAddon);
           this.setAttribute("legacy", legacyWarning);
           document.getAnonymousElementByAttribute(this, "anonid", "legacy").href = SUPPORT_URL + "webextensions";
 
           if (!("applyBackgroundUpdates" in this.mAddon) ||
               (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DISABLE ||
                (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DEFAULT &&
@@ -1500,28 +1483,19 @@
         <body><![CDATA[
             this._updateState();
         ]]></body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="click" button="0"><![CDATA[
-        switch (event.detail) {
-        case 1:
-          // Prevent double-click where the UI changes on the first click
-          this._lastClickTarget = event.originalTarget;
-          break;
-        case 2:
-          if (event.originalTarget.localName != "button" &&
-              !event.originalTarget.classList.contains("text-link") &&
-              event.originalTarget == this._lastClickTarget) {
-            this.showInDetailView();
-          }
-          break;
+        if (!["button", "checkbox"].includes(event.originalTarget.localName) &&
+            !event.originalTarget.classList.contains("text-link")) {
+          this.showInDetailView();
         }
       ]]></handler>
     </handlers>
   </binding>
 
 
   <!-- Addon - uninstalled - An uninstalled addon that can be re-installed. -->
   <binding id="addon-uninstalled"
--- a/toolkit/mozapps/extensions/content/extensions.xul
+++ b/toolkit/mozapps/extensions/content/extensions.xul
@@ -211,80 +211,82 @@
           <browser id="discover-browser" type="content" flex="1"
                    disablehistory="true"/>
         </deck>
 
         <!-- container for views with the search/tools header -->
         <vbox id="headered-views" flex="1">
           <!-- main header -->
           <hbox id="header" align="center">
-            <button id="show-all-extensions" hidden="true"
-                    label="&showAllExtensions.button.label;"
-                    command="cmd_showAllExtensions"/>
-            <spacer flex="1"/>
-            <hbox id="updates-container" align="center">
-              <image class="spinner"/>
-              <label id="updates-noneFound" hidden="true"
-                     value="&updates.noneFound.label;"/>
-              <button id="updates-manualUpdatesFound-btn" class="button-link"
-                      hidden="true" label="&updates.manualUpdatesFound.label;"
-                      command="cmd_goToAvailableUpdates"/>
-              <label id="updates-progress" hidden="true"
-                     value="&updates.updating.label;"/>
-              <label id="updates-installed" hidden="true"
-                     value="&updates.installed.label;"/>
-              <label id="updates-downloaded" hidden="true"
-                     value="&updates.downloaded.label;"/>
-              <button id="updates-restart-btn" class="button-link" hidden="true"
-                      label="&updates.restart.label;"
-                      command="cmd_restartApp"/>
+            <hbox id="header-inner">
+              <button id="show-all-extensions" hidden="true"
+                      label="&showAllExtensions.button.label;"
+                      command="cmd_showAllExtensions"/>
+              <spacer flex="1"/>
+              <hbox id="updates-container" align="center">
+                <image class="spinner"/>
+                <label id="updates-noneFound" hidden="true"
+                       value="&updates.noneFound.label;"/>
+                <button id="updates-manualUpdatesFound-btn" class="button-link"
+                        hidden="true" label="&updates.manualUpdatesFound.label;"
+                        command="cmd_goToAvailableUpdates"/>
+                <label id="updates-progress" hidden="true"
+                       value="&updates.updating.label;"/>
+                <label id="updates-installed" hidden="true"
+                       value="&updates.installed.label;"/>
+                <label id="updates-downloaded" hidden="true"
+                       value="&updates.downloaded.label;"/>
+                <button id="updates-restart-btn" class="button-link" hidden="true"
+                        label="&updates.restart.label;"
+                        command="cmd_restartApp"/>
+              </hbox>
+              <button id="show-disabled-unsigned-extensions" hidden="true"
+                      class="warning"
+                      label="&showUnsignedExtensions.button.label;"
+                      command="cmd_showUnsignedExtensions"/>
+              <toolbarbutton id="header-utils-btn" class="header-button" type="menu"
+                             tooltiptext="&toolsMenu.tooltip;">
+                <menupopup id="utils-menu">
+                  <menuitem id="utils-updateNow"
+                            label="&updates.checkForUpdates.label;"
+                            accesskey="&updates.checkForUpdates.accesskey;"
+                            command="cmd_findAllUpdates"/>
+                  <menuitem id="utils-viewUpdates"
+                            label="&updates.viewUpdates.label;"
+                            accesskey="&updates.viewUpdates.accesskey;"
+                            command="cmd_goToRecentUpdates"/>
+                  <menuseparator id="utils-installFromFile-separator"/>
+                  <menuitem id="utils-installFromFile"
+                            label="&installAddonFromFile.label;"
+                            accesskey="&installAddonFromFile.accesskey;"
+                            command="cmd_installFromFile"/>
+                  <menuitem id="utils-debugAddons"
+                            label="&debugAddons.label;"
+                            accesskey="&debugAddons.accesskey;"
+                            command="cmd_debugAddons"/>
+                  <menuseparator/>
+                  <menuitem id="utils-autoUpdateDefault"
+                            label="&updates.updateAddonsAutomatically.label;"
+                            accesskey="&updates.updateAddonsAutomatically.accesskey;"
+                            type="checkbox" autocheck="false"
+                            command="cmd_toggleAutoUpdateDefault"/>
+                  <menuitem id="utils-resetAddonUpdatesToAutomatic"
+                            label="&updates.resetUpdatesToAutomatic.label;"
+                            accesskey="&updates.resetUpdatesToAutomatic.accesskey;"
+                            command="cmd_resetAddonAutoUpdate"/>
+                  <menuitem id="utils-resetAddonUpdatesToManual"
+                            label="&updates.resetUpdatesToManual.label;"
+                            accesskey="&updates.resetUpdatesToManual.accesskey;"
+                            command="cmd_resetAddonAutoUpdate"/>
+                </menupopup>
+              </toolbarbutton>
+              <textbox id="header-search" type="search" searchbutton="true"
+                       searchbuttonlabel="&search.buttonlabel;"
+                       placeholder="&search.placeholder2;" maxlength="100"/>
             </hbox>
-            <button id="show-disabled-unsigned-extensions" hidden="true"
-                    class="warning"
-                    label="&showUnsignedExtensions.button.label;"
-                    command="cmd_showUnsignedExtensions"/>
-            <toolbarbutton id="header-utils-btn" class="header-button" type="menu"
-                           tooltiptext="&toolsMenu.tooltip;">
-              <menupopup id="utils-menu">
-                <menuitem id="utils-updateNow"
-                          label="&updates.checkForUpdates.label;"
-                          accesskey="&updates.checkForUpdates.accesskey;"
-                          command="cmd_findAllUpdates"/>
-                <menuitem id="utils-viewUpdates"
-                          label="&updates.viewUpdates.label;"
-                          accesskey="&updates.viewUpdates.accesskey;"
-                          command="cmd_goToRecentUpdates"/>
-                <menuseparator id="utils-installFromFile-separator"/>
-                <menuitem id="utils-installFromFile"
-                          label="&installAddonFromFile.label;"
-                          accesskey="&installAddonFromFile.accesskey;"
-                          command="cmd_installFromFile"/>
-                <menuitem id="utils-debugAddons"
-                          label="&debugAddons.label;"
-                          accesskey="&debugAddons.accesskey;"
-                          command="cmd_debugAddons"/>
-                <menuseparator/>
-                <menuitem id="utils-autoUpdateDefault"
-                          label="&updates.updateAddonsAutomatically.label;"
-                          accesskey="&updates.updateAddonsAutomatically.accesskey;"
-                          type="checkbox" autocheck="false"
-                          command="cmd_toggleAutoUpdateDefault"/>
-                <menuitem id="utils-resetAddonUpdatesToAutomatic"
-                          label="&updates.resetUpdatesToAutomatic.label;"
-                          accesskey="&updates.resetUpdatesToAutomatic.accesskey;"
-                          command="cmd_resetAddonAutoUpdate"/>
-                <menuitem id="utils-resetAddonUpdatesToManual"
-                          label="&updates.resetUpdatesToManual.label;"
-                          accesskey="&updates.resetUpdatesToManual.accesskey;"
-                          command="cmd_resetAddonAutoUpdate"/>
-              </menupopup>
-            </toolbarbutton>
-            <textbox id="header-search" type="search" searchbutton="true"
-                     searchbuttonlabel="&search.buttonlabel;"
-                     placeholder="&search.placeholder2;" maxlength="100"/>
           </hbox>
 
           <deck id="headered-views-content" flex="1" selectedIndex="0">
             <!-- list view -->
             <vbox id="list-view" flex="1" class="view-pane" align="stretch" tabindex="0">
               <!-- info UI for add-ons that have been disabled for being unsigned -->
               <vbox id="disabled-unsigned-addons-info" hidden="true">
                 <label id="disabled-unsigned-addons-heading" value="&disabledUnsigned.heading;"/>
@@ -425,17 +427,17 @@
                 <button id="update-selected-btn" hidden="true"
                         label="&updates.updateSelected.label;"
                         tooltiptext="&updates.updateSelected.tooltip;"/>
               </hbox>
               <richlistbox id="updates-list" class="list" flex="1"/>
             </vbox>
 
             <!-- detail view -->
-            <scrollbox id="detail-view" flex="1" class="view-pane addon-view" orient="vertical" tabindex="0"
+            <scrollbox id="detail-view" class="view-pane addon-view" orient="vertical" tabindex="0"
                        role="document">
               <!-- global warnings -->
               <hbox class="global-warning-container global-warning">
                 <hbox class="global-warning-safemode" flex="1" align="center"
                       tooltiptext="&warning.safemode.label;">
                   <image class="warning-icon"/>
                   <label class="global-warning-text" flex="1" crop="end"
                          value="&warning.safemode.label;"/>
@@ -457,29 +459,28 @@
                          value="&warning.updatesecurity.label;"/>
                 </hbox>
                 <button class="button-link global-warning-updatesecurity"
                         label="&warning.updatesecurity.enable.label;"
                         tooltiptext="&warning.updatesecurity.enable.tooltip;"
                         command="cmd_enableUpdateSecurity"/>
                 <spacer flex="5000"/> <!-- Necessary to allow the message to wrap -->
               </hbox>
-              <hbox flex="1">
-                <spacer flex="1"/>
+              <hbox class="detail-view-wrapper">
                 <!-- "loading" splash screen -->
                 <vbox class="alert-container">
                   <spacer class="alert-spacer-before"/>
                   <hbox class="alert loading">
                     <image/>
                     <label value="&loading.label;"/>
                   </hbox>
                   <spacer class="alert-spacer-after"/>
                 </vbox>
                 <!-- actual detail view -->
-                <vbox class="detail-view-container" flex="3" contextmenu="addonitem-popup">
+                <vbox class="detail-view-container" contextmenu="addonitem-popup">
                   <vbox id="detail-notifications">
                     <hbox id="warning-container" align="center" class="warning">
                       <image class="warning-icon"/>
                       <label id="detail-warning" flex="1"/>
                       <label id="detail-warning-link" class="text-link"/>
                       <spacer flex="5000"/> <!-- Necessary to allow the message to wrap -->
                     </hbox>
                     <hbox id="error-container" align="center" class="error">
@@ -496,42 +497,39 @@
                               command="cmd_restartApp"/>
                       <button id="detail-undo-btn" class="button-link"
                               label="&addon.undoAction.label;"
                               tooltipText="&addon.undoAction.tooltip;"
                               command="cmd_cancelOperation"/>
                       <spacer flex="5000"/> <!-- Necessary to allow the message to wrap -->
                     </hbox>
                   </vbox>
-                  <hbox align="start">
-                    <vbox id="detail-icon-container" align="end">
-                      <image id="detail-icon" class="icon"/>
-                    </vbox>
+                  <hbox class="card addon-detail" align="start">
                     <vbox flex="1">
-                      <vbox id="detail-summary">
-                        <hbox id="detail-name-container" class="name-container"
-                              align="start">
-                          <label id="detail-name" flex="1"/>
-                          <label id="detail-version"/>
-                          <label id="detail-legacy-warning" class="legacy-warning text-link" value="&addon.legacy.label;"/>
-                          <label class="disabled-postfix" value="&addon.disabled.postfix;"/>
-                          <label class="update-postfix" value="&addon.update.postfix;"/>
-                          <spacer flex="5000"/> <!-- Necessary to allow the name to wrap -->
-                        </hbox>
-                        <label id="detail-creator" class="creator"/>
-                      </vbox>
-                      <hbox id="detail-desc-container" align="start">
-                        <vbox id="detail-screenshot-box" pack="center" hidden="true"> <!-- Necessary to work around bug 394738 -->
-                          <image id="detail-screenshot"/>
+                      <hbox align="start">
+                        <vbox id="detail-icon-container" align="end">
+                          <image id="detail-icon" class="icon"/>
                         </vbox>
-                        <vbox flex="1">
-                          <description id="detail-desc"/>
-                          <description id="detail-fulldesc"/>
+                        <vbox id="detail-summary">
+                          <hbox id="detail-name-container" class="name-container"
+                                align="start">
+                            <label id="detail-name" flex="1"/>
+                            <label id="detail-version"/>
+                            <label id="detail-legacy-warning" class="legacy-warning text-link" value="&addon.legacy.label;"/>
+                            <label class="disabled-postfix" value="&addon.disabled.postfix;"/>
+                            <label class="update-postfix" value="&addon.update.postfix;"/>
+                            <spacer flex="5000"/> <!-- Necessary to allow the name to wrap -->
+                          </hbox>
+                          <label id="detail-creator" class="creator"/>
                         </vbox>
                       </hbox>
+                      <vbox id="detail-desc-container" align="start" flex="1">
+                        <description id="detail-desc"/>
+                        <description id="detail-fulldesc"/>
+                      </vbox>
                       <vbox id="detail-contributions">
                         <description id="detail-contrib-description">
                           &detail.contributions.description;
                         </description>
                         <hbox align="center">
                           <spacer flex="1"/>
                           <button id="detail-contrib-btn"
                                   label="&cmd.contribute.label;"
--- a/toolkit/mozapps/extensions/test/browser/browser.ini
+++ b/toolkit/mozapps/extensions/test/browser/browser.ini
@@ -26,17 +26,16 @@ support-files =
   !/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/amosigned-restart-required.xpi
 
 [browser_CTP_plugins.js]
 tags = blocklist
 [browser_bug523784.js]
 [browser_bug562797.js]
-[browser_bug562854.js]
 [browser_bug562890.js]
 skip-if = os == 'win' && !debug # Disabled on Windows opt/PGO builds due to intermittent failures (bug 1135866)
 [browser_bug562899.js]
 [browser_bug562992.js]
 [browser_bug567127.js]
 [browser_bug567137.js]
 [browser_bug570760.js]
 skip-if = verify
--- a/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js
@@ -103,19 +103,17 @@ add_task(async function() {
     let testPlugin = content.document.getElementById("test");
     ok(testPlugin, "part7: should have a plugin element in the page");
     let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent);
     ok(!objLoadingContent.activated, "part7: plugin should not be activated");
   });
 
   BrowserTestUtils.removeTab(pluginTab);
 
-  let details = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn");
-  is_element_visible(details, "part7: details link should be visible");
-  EventUtils.synthesizeMouseAtCenter(details, {}, managerWindow);
+  EventUtils.synthesizeMouseAtCenter(pluginEl, {}, managerWindow);
   await BrowserTestUtils.waitForEvent(managerWindow.document, "ViewChanged");
 
   is_element_hidden(enableButton, "part8: detail enable button should be hidden");
   is_element_hidden(disableButton, "part8: detail disable button should be hidden");
   is_element_visible(menu, "part8: detail state menu should be visible");
   is(menu.selectedItem, neverActivateItem, "part8: state menu should have 'Never Activate' selected");
 
   menu.selectedItem = alwaysActivateItem;
@@ -156,17 +154,16 @@ add_task(async function() {
     );
   });
 
   pluginEl = get_addon_element(managerWindow, testPluginId);
   pluginEl.parentNode.ensureElementIsVisible(pluginEl);
   menu = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist");
   is(menu.disabled, true, "part12: state menu should be disabled");
 
-  details = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn");
-  EventUtils.synthesizeMouseAtCenter(details, {}, managerWindow);
+  EventUtils.synthesizeMouseAtCenter(pluginEl, {}, managerWindow);
   await BrowserTestUtils.waitForEvent(managerWindow.document, "ViewChanged");
 
   menu = managerWindow.document.getElementById("detail-state-menulist");
   is(menu.disabled, true, "part13: detail state menu should be disabled");
 
   managerWindow.close();
 });
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/browser/browser_bug562854.js
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-/**
- * Tests that double-click does not go to detail view if the target is a link or button.
- */
-
-function test() {
-  requestLongerTimeout(2);
-
-  waitForExplicitFinish();
-
-  var gProvider = new MockProvider();
-  gProvider.createAddons([{
-    id: "test1@tests.mozilla.org",
-    name: "Test add-on 1",
-    description: "foo",
-    operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE,
-  }]);
-
-  run_next_test();
-}
-
-function end_test() {
-  finish();
-}
-
-function is_in_list(aManager, view) {
-  var doc = aManager.document;
-
-  is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category");
-  is(get_current_view(aManager).id, "list-view", "Should be on the right view");
-}
-
-function is_in_detail(aManager, view) {
-  var doc = aManager.document;
-
-  is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category");
-  is(get_current_view(aManager).id, "detail-view", "Should be on the right view");
-}
-
-// Check that double-click does something.
-add_test(async function() {
-  let aManager = await open_manager("addons://list/extension");
-  info("Part 1");
-  is_in_list(aManager, "addons://list/extension");
-
-  var addon = get_addon_element(aManager, "test1@tests.mozilla.org");
-  addon.parentNode.ensureElementIsVisible(addon);
-  EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 1 }, aManager);
-  EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 2 }, aManager);
-
-  aManager = await wait_for_view_load(aManager);
-  info("Part 2");
-  is_in_detail(aManager, "addons://list/extension");
-
-  close_manager(aManager, run_next_test);
-});
-
-// Check that double-click does nothing when over the disable button.
-add_test(async function() {
-  let aManager = await open_manager("addons://list/extension");
-  info("Part 1");
-  is_in_list(aManager, "addons://list/extension");
-
-  var addon = get_addon_element(aManager, "test1@tests.mozilla.org");
-  addon.parentNode.ensureElementIsVisible(addon);
-  EventUtils.synthesizeMouseAtCenter(
-    aManager.document.getAnonymousElementByAttribute(addon, "anonid", "disable-btn"),
-    { clickCount: 1 },
-    aManager
-  );
-  // The disable button is replaced by the enable button when clicked on.
-  EventUtils.synthesizeMouseAtCenter(
-    aManager.document.getAnonymousElementByAttribute(addon, "anonid", "enable-btn"),
-    { clickCount: 2 },
-    aManager
-  );
-
-  aManager = await wait_for_view_load(aManager);
-  info("Part 2");
-  is_in_list(aManager, "addons://list/extension");
-
-  close_manager(aManager, run_next_test);
-});
-
-// Check that double-click does nothing when over the undo button.
-add_test(async function() {
-  let aManager = await open_manager("addons://list/extension");
-  info("Part 1");
-  is_in_list(aManager, "addons://list/extension");
-
-  var addon = get_addon_element(aManager, "test1@tests.mozilla.org");
-  addon.parentNode.ensureElementIsVisible(addon);
-  EventUtils.synthesizeMouseAtCenter(
-    aManager.document.getAnonymousElementByAttribute(addon, "anonid", "remove-btn"),
-    { clickCount: 1 },
-    aManager
-  );
-
-  // The undo button is removed when clicked on.
-  // We need to wait for the UI to catch up.
-  setTimeout(async function() {
-    var target = aManager.document.getAnonymousElementByAttribute(addon, "anonid", "undo-btn");
-    var rect = target.getBoundingClientRect();
-    var addonRect = addon.getBoundingClientRect();
-
-    EventUtils.synthesizeMouse(target, rect.width / 2, rect.height / 2, { clickCount: 1 }, aManager);
-    EventUtils.synthesizeMouse(addon,
-      rect.left - addonRect.left + rect.width / 2,
-      rect.top - addonRect.top + rect.height / 2,
-      { clickCount: 2 },
-      aManager
-    );
-
-    aManager = await wait_for_view_load(aManager);
-    info("Part 2");
-    is_in_list(aManager, "addons://list/extension");
-
-    close_manager(aManager, run_next_test);
-  }, 0);
-});
--- a/toolkit/mozapps/extensions/test/browser/browser_details.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_details.js
@@ -71,21 +71,16 @@ async function test() {
     description: "Short description",
     creator: { name: "Mozilla", url: null },
     type: "extension",
     iconURL: "chrome://foo/skin/icon.png",
     contributionURL: "http://foo.com",
     contributionAmount: null,
     updateDate: gDate,
     permissions: 0,
-    screenshots: [{
-      url: "chrome://branding/content/about.png",
-      width: 200,
-      height: 150,
-    }],
   }, {
     id: "addon3@tests.mozilla.org",
     name: "Test add-on 3",
     description: "Short description",
     creator: { name: "Mozilla", url: "http://www.mozilla.org" },
     type: "extension",
     sourceURI: Services.io.newURI("http://example.com/foo"),
     updateDate: gDate,
@@ -93,24 +88,16 @@ async function test() {
     reviewURL: "http://example.com/reviews",
     applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE,
     isActive: false,
     isCompatible: false,
     appDisabled: true,
     permissions: AddonManager.PERM_CAN_ENABLE |
                  AddonManager.PERM_CAN_DISABLE |
                  AddonManager.PERM_CAN_UPGRADE,
-    screenshots: [{
-      url: "http://example.com/screenshot",
-      width: 400,
-      height: 300,
-      thumbnailURL: "chrome://branding/content/icon64.png",
-      thumbnailWidth: 160,
-      thumbnailHeight: 120,
-    }],
   }, {
     id: "addon5@tests.mozilla.org",
     blocklistURL: "http://example.com/addon5@tests.mozilla.org",
     name: "Test add-on 5",
     isActive: false,
     blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED,
     appDisabled: true,
   }, {
@@ -164,21 +151,16 @@ add_test(function() {
     is(get("detail-version").value, "2.2", "Version should be correct");
     is(get("detail-icon").src, "chrome://foo/skin/icon.png", "Icon should be correct");
 
     is_element_visible(get("detail-creator"), "Creator should not be hidden");
     is_element_visible(get("detail-creator")._creatorName, "Creator name should not be hidden");
     is(get("detail-creator")._creatorName.value, "Mozilla", "Creator should be correct");
     is_element_hidden(get("detail-creator")._creatorLink, "Creator link should be hidden");
 
-    is_element_visible(get("detail-screenshot-box"), "Screenshot should be visible");
-    is(get("detail-screenshot").src, "chrome://branding/content/about.png", "Should be showing the full sized screenshot");
-    is(get("detail-screenshot").width, 200, "Screenshot dimensions should be set");
-    is(get("detail-screenshot").height, 150, "Screenshot dimensions should be set");
-    is(get("detail-screenshot").hasAttribute("loading"), true, "Screenshot should have loading attribute");
     is(get("detail-desc").textContent, "Short description", "Description should be correct");
     is_element_hidden(get("detail-fulldesc"), "Full description should be hidden");
 
     is_element_visible(get("detail-contributions"), "Contributions section should be visible");
 
     is_element_visible(get("detail-dateUpdated"), "Update date should not be hidden");
     is(get("detail-dateUpdated").value, formatDate(gDate), "Update date should be correct");
 
@@ -195,42 +177,33 @@ add_test(function() {
     is_element_hidden(get("detail-uninstall-btn"), "Remove button should be hidden");
 
     is_element_hidden(get("detail-warning"), "Warning message should be hidden");
     is_element_hidden(get("detail-warning-link"), "Warning link should be hidden");
     is_element_hidden(get("detail-error"), "Error message should be hidden");
     is_element_hidden(get("detail-error-link"), "Error link should be hidden");
     is_element_hidden(get("detail-pending"), "Pending message should be hidden");
 
-    get("detail-screenshot").addEventListener("load", function() {
-      is(this.hasAttribute("loading"), false, "Screenshot should not have loading attribute");
-      run_next_test();
-    }, {once: true});
+    run_next_test();
   });
 });
 
 // Opens and tests the details view for add-on 3
 add_test(function() {
   open_details("addon3@tests.mozilla.org", "extension", function() {
     is(get("detail-name").textContent, "Test add-on 3", "Name should be correct");
     is_element_hidden(get("detail-version"), "Version should be hidden");
     is(get("detail-icon").src, "", "Icon should be correct");
 
     is_element_visible(get("detail-creator"), "Creator should not be hidden");
     is_element_hidden(get("detail-creator")._creatorName, "Creator name should be hidden");
     is_element_visible(get("detail-creator")._creatorLink, "Creator link should not be hidden");
     is(get("detail-creator")._creatorLink.value, "Mozilla", "Creator link should be correct");
     is(get("detail-creator")._creatorLink.href, "http://www.mozilla.org", "Creator link href should be correct");
 
-    is_element_visible(get("detail-screenshot-box"), "Screenshot should be visible");
-    is(get("detail-screenshot").src, "chrome://branding/content/icon64.png", "Should be showing the thumbnail");
-    is(get("detail-screenshot").width, 160, "Screenshot dimensions should be set");
-    is(get("detail-screenshot").height, 120, "Screenshot dimensions should be set");
-    is(get("detail-screenshot").hasAttribute("loading"), true, "Screenshot should have loading attribute");
-
     is_element_hidden(get("detail-contributions"), "Contributions section should be hidden");
 
     is_element_visible(get("detail-updates-row"), "Updates should not be hidden");
     is_element_visible(get("detail-dateUpdated"), "Update date should not be hidden");
     is(get("detail-dateUpdated").value, formatDate(gDate), "Update date should be correct");
 
     is_element_visible(get("detail-rating-row"), "Rating row should not be hidden");
     is_element_hidden(get("detail-rating"), "Rating should be hidden");
@@ -273,20 +246,17 @@ add_test(function() {
 
     is_element_visible(get("detail-warning"), "Warning message should be visible");
     is(get("detail-warning").textContent, "Test add-on 3 is incompatible with " + gApp + " " + gVersion + ".", "Warning message should be correct");
     is_element_hidden(get("detail-warning-link"), "Warning link should be hidden");
     is_element_hidden(get("detail-error"), "Error message should be hidden");
     is_element_hidden(get("detail-error-link"), "Error link should be hidden");
     is_element_hidden(get("detail-pending"), "Pending message should be hidden");
 
-    get("detail-screenshot").addEventListener("load", function() {
-      is(this.hasAttribute("loading"), false, "Screenshot should not have loading attribute");
-      run_next_test();
-    }, {once: true});
+    run_next_test();
   });
 });
 
 // Opens and tests the details view for add-on 5
 add_test(function() {
   open_details("addon5@tests.mozilla.org", "extension", async function() {
     await TestUtils.waitForCondition(() => !BrowserTestUtils.is_hidden(get("detail-error-link")));
     is(get("detail-name").textContent, "Test add-on 5", "Name should be correct");
@@ -552,17 +522,16 @@ add_test(function() {
       operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE,
     }]);
 
     is(get("detail-name").textContent, "Test add-on replacement", "Name should be correct");
     is_element_visible(get("detail-version"), "Version should not be hidden");
     is(get("detail-version").value, "2.5", "Version should be correct");
     is(get("detail-icon").src, "chrome://foo/skin/icon264.png", "Icon should be correct");
     is_element_hidden(get("detail-creator"), "Creator should be hidden");
-    is_element_hidden(get("detail-screenshot-box"), "Screenshot should be hidden");
     is(get("detail-desc").textContent, "Short description replacement", "Description should be correct");
     is(get("detail-fulldesc").textContent, "Longer description replacement", "Full description should be correct");
 
     is_element_hidden(get("detail-contributions"), "Contributions section should be hidden");
 
     is_element_hidden(get("detail-dateUpdated"), "Update date should be hidden");
 
     is_element_visible(get("detail-rating-row"), "Rating row should not be hidden");
--- a/toolkit/mozapps/extensions/test/browser/browser_legacy_pre57.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_legacy_pre57.js
@@ -58,18 +58,17 @@ add_task(async function() {
     if (isLegacy) {
       is_element_visible(badge, `Legacy badge is visible for ${name}`);
       is(badge.href, INFO_URL, "Legacy badge link is correct");
     } else {
       is_element_hidden(badge, `Legacy badge is hidden for ${name}`);
     }
 
     // Click down to the details page.
-    let detailsButton = document.getAnonymousElementByAttribute(item, "anonid", "details-btn");
-    EventUtils.synthesizeMouseAtCenter(detailsButton, {}, mgrWin);
+    EventUtils.synthesizeMouseAtCenter(item, {}, mgrWin);
     await new Promise(resolve => wait_for_view_load(mgrWin, resolve));
 
     // And check the badge
     let elements = document.getElementsByClassName("legacy-warning");
     is(elements.length, 1, "Found the legacy-warning element");
     badge = elements[0];
 
     if (isLegacy) {
--- a/toolkit/mozapps/extensions/test/browser/browser_list.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_list.js
@@ -380,18 +380,16 @@ add_task(async function() {
   is(Object.keys(items).length, EXPECTED_ADDONS, "Should be the right number of add-ons installed");
 
   let addon = items["Test add-on replacement"];
   addon.parentNode.ensureElementIsVisible(addon);
   let { name, version } = await get_tooltip_info(addon);
   is(get_node(addon, "name").value, "Test add-on replacement", "Name should be correct");
   is(name, "Test add-on replacement", "Tooltip name should be correct");
   is(version, "2.0", "Tooltip version should be correct");
-  is_element_visible(get_node(addon, "description"), "Description should be visible");
-  is(get_node(addon, "description").value, "A test add-on with a new description", "Description should be correct");
   is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden");
   is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden");
   is(get_node(addon, "date-updated").value, formatDate(gDate), "Update date should be correct");
 
   is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden");
   is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden");
   is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible");
   is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible");
@@ -419,37 +417,33 @@ add_task(async function() {
   // Ignore the OSX full keyboard access setting
   Services.prefs.setBoolPref("accessibility.tabfocus_applies_to_xul", false);
 
   let items = get_test_items();
   is(Object.keys(items).length, EXPECTED_ADDONS, "Should be the right number of add-ons installed");
 
   let addon = items["Test add-on 6"];
   addon.parentNode.ensureElementIsVisible(addon);
-  EventUtils.synthesizeMouseAtCenter(addon, { }, gManagerWindow);
+  addon.parentNode.focus();
   is(Services.focus.focusedElement, addon.parentNode, "Focus should have moved to the list");
 
   EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow);
-  is(Services.focus.focusedElement, get_node(addon, "details-btn"), "Focus should have moved to the more button");
-
-  EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow);
   is(Services.focus.focusedElement, get_node(addon, "disable-btn"), "Focus should have moved to the disable button");
 
   EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow);
   is(Services.focus.focusedElement, get_node(addon, "remove-btn"), "Focus should have moved to the remove button");
 
   EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow);
   ok(!is_node_in_list(Services.focus.focusedElement), "Focus should be outside the list");
 
   EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow);
   is(Services.focus.focusedElement, get_node(addon, "remove-btn"), "Focus should have moved to the remove button");
 
   EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow);
-  EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow);
-  is(Services.focus.focusedElement, get_node(addon, "details-btn"), "Focus should have moved to the more button");
+  is(Services.focus.focusedElement, get_node(addon, "disable-btn"), "Focus should have moved to the disable button");
 
   EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow);
   is(Services.focus.focusedElement, addon.parentNode, "Focus should have moved to the list");
 
   EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow);
   ok(!is_node_in_list(Services.focus.focusedElement), "Focus should be outside the list");
 
   try {
--- a/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js
@@ -62,19 +62,17 @@ function checkStateMenu(locked) {
   is_element_visible(selectedMenuItem, "State menu's selected item should be visible.");
 }
 
 function checkStateMenuDetail(locked) {
   Assert.equal(Services.prefs.prefIsLocked(getTestPluginPref()), locked,
     "Preference should be " + (locked === true ? "" : "un") + "locked.");
 
   // open details menu
-  let details = gManagerWindow.document.getAnonymousElementByAttribute(gPluginElement, "anonid", "details-btn");
-  is_element_visible(details, "Details link should be visible.");
-  EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow);
+  EventUtils.synthesizeMouseAtCenter(gPluginElement, {}, gManagerWindow);
 
   return new Promise(async resolve => {
     await wait_for_view_load(gManagerWindow);
     let menuList = gManagerWindow.document.getElementById("detail-state-menulist");
     is_element_visible(menuList, "Details state menu should be visible.");
     Assert.equal(menuList.disabled, locked,
       "Details state menu enabled state should be correct.");
     resolve();
--- a/toolkit/mozapps/extensions/test/browser/browser_pluginprefs.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_pluginprefs.js
@@ -34,18 +34,17 @@ add_test(async function() {
   let testPlugin = await AddonManager.getAddonByID(testPluginId);
   let pluginEl = get_addon_element(gManagerWindow, testPluginId);
   is(pluginEl.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE_BROWSER, "Options should be inline type");
   pluginEl.parentNode.ensureElementIsVisible(pluginEl);
 
   let button = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "preferences-btn");
   is_element_visible(button, "Preferences button should be visible");
 
-  button = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn");
-  EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
+  EventUtils.synthesizeMouseAtCenter(pluginEl, { clickCount: 1 }, gManagerWindow);
 
   Services.obs.addObserver(async function observer(subject, topic, data) {
     Services.obs.removeObserver(observer, topic);
 
     // Wait for PluginProvider to do its stuff.
     await new Promise(executeSoon);
 
     let doc = gManagerWindow.document.getElementById("addon-options").contentDocument;
--- a/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js
@@ -235,18 +235,17 @@ add_test(async function() {
   let aAddon = await AddonManager.getAddonByID(ID);
   ok(aAddon.isActive, "Add-on should be active");
   ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall");
   ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall");
 
   var item = get_item_in_list(ID, list);
   isnot(item, null, "Should have found the add-on in the list");
 
-  EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
-  EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
+  item.click();
   await wait_for_view_load(gManagerWindow);
 
   // Test the uninstall.
   return test_uninstall_details(aAddon, ID);
 });
 
 // Tests that uninstalling a restartless add-on from directly loading the
 // details view switches back to the list view and can be undone
@@ -282,18 +281,17 @@ add_test(async function() {
 
   ok(!aAddon.isActive, "Add-on should be inactive");
   ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall");
   ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall");
 
   var item = get_item_in_list(ID, list);
   isnot(item, null, "Should have found the add-on in the list");
 
-  EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
-  EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
+  item.click();
   await wait_for_view_load(gManagerWindow);
   is(get_current_view(gManagerWindow).id, "detail-view", "Should be in the detail view");
 
   var button = gDocument.getElementById("detail-uninstall-btn");
   isnot(button, null, "Should have a remove button");
   ok(!button.disabled, "Button should not be disabled");
 
   EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow);
--- a/toolkit/themes/shared/extensions/extensions.inc.css
+++ b/toolkit/themes/shared/extensions/extensions.inc.css
@@ -9,18 +9,18 @@
   padding: 0;
 }
 
 #nav-header {
   min-height: 39px;
 }
 
 .view-pane > .list > scrollbox {
-  padding-right: 48px;
-  padding-left: 48px;
+  padding-right: 24px;
+  padding-left: 24px;
 }
 
 
 /*** global warnings ***/
 
 .global-warning-container {
   overflow-x: hidden;
 }
@@ -221,34 +221,31 @@ button.warning {
 }
 #category-recentUpdates > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-recent.svg");
 }
 
 
 /*** header ***/
 
-#header {
-  margin-top: 20px;
-  margin-bottom: 20px;
-  margin-right: 48px;
-  margin-left: 48px;
+#header-inner {
+  margin: 20px 4px 30px;
+  width: 692px;
 }
 
+#header-search {
+  margin-top: 0;
+}:
+
 @media (max-width: 600px) {
   #header-search {
     width: 12em;
   }
 }
 
-.view-header {
-  margin: 0 48px;
-  border-bottom: 1px solid var(--in-content-box-border-color);
-}
-
 #header-utils-btn {
   height: 30px;
   line-height: 20px;
   border-color: var(--in-content-box-border-color);
   background-color: var(--in-content-page-background);
   padding-right: 10px;
   padding-left: 10px;
 }
@@ -318,63 +315,41 @@ button.warning {
 
 .list {
   -moz-appearance: none;
   margin: 0;
   border-width: 0 !important;
   background-color: transparent;
 }
 
-.list > scrollbox > .scrollbox-innerbox {
-  border: 1px dotted transparent;
-}
-
-.list:-moz-focusring > scrollbox > .scrollbox-innerbox {
-  border-color: var(--in-content-border-focus);
-}
-
 richlistbox.list > richlistitem.addon {
   color: var(--in-content-text-color);
-  border-bottom: 1px solid var(--in-content-box-border-color);
-  padding: 5px;
   background-origin: border-box;
 }
 
-.addon:not(:only-child):last-child {
-  border-bottom-width: 0;
-}
-
-.details {
-  cursor: pointer;
-  margin: 0;
-  margin-inline-start: 10px;
-}
-
-.icon-container {
-  width: 48px;
-  height: 48px;
-  margin: 3px 7px;
-  -moz-box-align: center;
-  -moz-box-pack: center;
-}
-
 .icon {
   list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric.svg");
-  max-width: 32px;
-  max-height: 32px;
+  max-width: 24px;
+  max-height: 24px;
+  margin-inline-end: 16px;
 }
 
 .content-inner-container {
   margin-inline-end: 5px;
 }
 
 .addon[active="false"] .icon {
   filter: grayscale(1);
 }
 
+.addon label,
+.addon {
+  cursor: pointer;
+}
+
 .addon-view[type="theme"] .icon {
   list-style-image: url("chrome://mozapps/skin/extensions/themeGeneric.svg");
 }
 
 .addon-view[type="locale"] .icon {
   list-style-image: url("chrome://mozapps/skin/extensions/localeGeneric.svg");
 }
 
@@ -386,18 +361,17 @@ richlistbox.list > richlistitem.addon {
   list-style-image: url("chrome://mozapps/skin/extensions/dictionaryGeneric.svg");
 }
 
 .addon-view[type="experiment"] .icon {
   list-style-image: url("chrome://mozapps/skin/extensions/experimentGeneric.svg");
 }
 
 .name-container {
-  font-size: 1.3rem;
-  font-weight: bold;
+  font-weight: 600;
   -moz-box-align: end;
   -moz-box-flex: 1;
 }
 
 .legacy-warning {
   background-color: #FFE900;
   color: #3E2800;
   padding: 4px 5px 3px;
@@ -420,17 +394,17 @@ richlistbox.list > richlistitem.addon {
   color: #FFF;
 }
 
 #detail-view .legacy-warning {
   margin-top: 0.78rem;
 }
 
 .creator {
-  font-weight: bold;
+  font-size: 1.2rem;
 }
 
 .description-container {
   margin-inline-start: 6px;
   -moz-box-align: center;
   font-size: 1.25rem;
 }
 
@@ -472,18 +446,17 @@ richlistbox.list > richlistitem.addon {
   -moz-box-pack: center;
 }
 
 .relnotes-toggle-container,
 .icon-outer-container {
   -moz-box-pack: start;
 }
 
-.status-container,
-.control-container {
+.status-container {
   -moz-box-pack: end;
 }
 
 .addon-view .warning {
   color: #d8b826;
 }
 
 .addon-view .error {
@@ -554,20 +527,25 @@ richlistbox.list > richlistitem.addon {
 }
 
 .addon-view[pending="disable"],
 .addon-view[pending="uninstall"] {
   --view-highlight-color: #F2F2F2;
 }
 
 .list > .addon[selected] {
-  background-color: var(--in-content-page-background);
-  color: var(--in-content-page-color);
-  padding-inline-start: 1px; /* compensate the 4px border */
-  border-inline-start: solid 4px var(--in-content-border-focus);
+  background-color: var(--in-content-box-background);
+}
+
+.list:focus > .addon[selected] {
+  box-shadow: var(--card-shadow-focus);
+}
+
+.list > .addon {
+  margin: 8px;
 }
 
 #addon-list .addon[active="false"] > .content-container > .content-inner-container {
   color: #999;
 }
 
 #addon-list .addon[active="false"][selected] > .content-container > .content-inner-container {
   color: #777;
@@ -591,66 +569,67 @@ richlistbox.list > richlistitem.addon {
 .addon[status="uninstalled"][selected] {
   background-color: transparent;
 }
 
 
 /*** detail view ***/
 
 #detail-view > .scrollbox-innerbox {
-  margin-right: 48px;
-  margin-left: 48px;
+  margin: 32px;
 }
 
 #detail-view .loading {
   opacity: 0;
 }
 
 #detail-view[loading-extended] .loading {
   opacity: 1;
   transition-property: opacity;
   transition-duration: 1s;
 }
 
 .detail-view-container {
-  padding-inline-end: 2em;
-  padding-bottom: 2em;
-  font-size: 1.25rem;
-  color: #333;
+  width: 664px;
 }
 
 #detail-notifications {
   margin-top: 1em;
   margin-bottom: 2em;
 }
 
+#detail-view:not([notification="warning"]):not([notification="error"]):not([pending]) #detail-notifications {
+  display: none;
+}
+
 #detail-notifications .warning,
 #detail-notifications .pending,
 #detail-notifications .error {
   margin-inline-start: 0;
 }
 
 #detail-icon-container {
   width: 64px;
-  margin-inline-end: 10px;
   margin-top: 6px;
 }
 
 #detail-icon {
-  max-width: 64px;
-  max-height: 64px;
+  max-width: 32px;
+  max-height: 32px;
 }
 
-#detail-summary {
-  margin-bottom: 2em;
+.name-container > label,
+#detail-creator,
+#detail-name-container > label {
+  margin-inline-start: 0;
 }
 
-#detail-name-container {
-  font-size: 2.5rem;
-  font-weight: normal;
+#detail-controls {
+  margin-inline-start: -4px;
+  margin-inline-end: -4px;
 }
 
 #detail-screenshot-box {
   margin-inline-end: 2em;
   background-image: linear-gradient(rgba(255,255,255,.5), transparent);
   background-color: white;
   box-shadow: 0 1px 2px #666;
   border-radius: 2px;
@@ -674,21 +653,37 @@ richlistbox.list > richlistitem.addon {
   }
 }
 
 #detail-screenshot[loading="error"] {
   background-image: url("chrome://global/skin/media/error.png");
 }
 
 #detail-desc-container {
-  margin-bottom: 2em;
+  line-height: 1.3;
+  margin: 1em 0;
+}
+
+#detail-controls > button {
+  margin-bottom: 0;
+}
+
+.addon.card {
+  max-width: 664px;
+  /* The .addon-control element on the end has 4px of margin, remove it
+   * from the padding to stay balanced. */
+  padding-inline-end: 12px;
+}
+
+.addon-detail.card:hover {
+  box-shadow: none;
 }
 
 #detail-desc, #detail-fulldesc {
-  margin-inline-start: 6px;
+  margin-inline-start: 0;
   /* This is necessary to fix layout issues with multi-line descriptions, see
      bug 592712*/
   outline: solid transparent;
   white-space: pre-wrap;
   min-width: 10em;
 }
 
 #detail-fulldesc {
@@ -752,20 +747,16 @@ richlistbox.list > richlistitem.addon {
 .detail-row-complex {
   border-top: 1px solid var(--in-content-box-border-color);
   -moz-box-align: center;
   min-height: 35px;
   line-height: 20px;
   text-shadow: 0 1px 1px #fefffe;
 }
 
-#detail-controls {
-  margin-bottom: 1em;
-}
-
 .inline-options-browser {
   margin-top: 2em;
 }
 
 .preferences-alignment {
   min-height: 30px;
   -moz-box-align: center;
 }
@@ -919,16 +910,25 @@ richlistbox.list > richlistitem.addon {
 
 
 /*** buttons ***/
 
 .addon-control[disabled="true"]:not(.no-auto-hide) {
   display: none;
 }
 
+.addon-control {
+  cursor: default;
+  margin-top: 0;
+  margin-bottom: 0;
+  min-height: auto;
+  min-width: auto;
+  padding: 2px 4px;
+}
+
 .no-auto-hide .addon-control {
   display: block !important;
 }
 
 button.button-link {
   -moz-appearance: none;
   background: transparent;
   border: none;
--- a/toolkit/themes/shared/in-content/common.inc.css
+++ b/toolkit/themes/shared/in-content/common.inc.css
@@ -35,23 +35,34 @@
   --in-content-link-color-active: #003eaa;
   --in-content-link-color-visited: #0a8dff;
   --in-content-primary-button-background: #0a84ff;
   --in-content-primary-button-background-hover: #0060df;
   --in-content-primary-button-background-active: #003EAA;
   --in-content-table-background: #ebebeb;
   --in-content-table-border-dark-color: #d1d1d1;
   --in-content-table-header-background: #0a84ff;
+
+  --blue-50: #0a84ff;
+  --blue-50-a30: rgba(10, 132, 255, 0.3);
   --grey-20: #ededf0;
+  --grey-30: #d7d7db;
+  --grey-60: #4a4a4f;
   --grey-90: #0c0c0d;
   --grey-90-a10: rgba(12, 12, 13, 0.1);
   --grey-90-a20: rgba(12, 12, 13, 0.2);
   --grey-90-a30: rgba(12, 12, 13, 0.3);
   --yellow-50: #ffe900;
   --yellow-90: #3e2800;
+
+  --shadow-10: 0 1px 4px var(--grey-90-a10);
+  --card-shadow: var(--shadow-10);
+  --card-outline-color: var(--grey-30);
+  --card-shadow-hover: var(--card-shadow), 0 0 0 5px var(--card-outline-color);
+  --card-shadow-focus: 0 0 0 2px var(--blue-50), 0 0 0 6px var(--blue-50-a30);
 }
 
 html|html,
 xul|page,
 xul|window {
   font: message-box;
   -moz-appearance: none;
   background-color: var(--in-content-page-background);
@@ -842,25 +853,26 @@ xul|treechildren::-moz-tree-image(select
   color: var(--yellow-90);
 }
 
 .message-bar-warning > .message-bar-icon {
   list-style-image: url("chrome://browser/skin/warning.svg");
 }
 
 .card {
-  background: #fff;
-  box-shadow: 0 0 1px rgba(0, 0, 0, 0.12);
+  background: var(--in-content-box-background);
+  border-radius: 4px;
+  box-shadow: var(--card-shadow);
   margin: 0 0 8px;
   padding: 16px;
   transition: box-shadow 150ms;
 }
 
 .card:hover {
-  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.24);
+  box-shadow: var(--card-shadow-hover);
 }
 
 .sidebar-footer-button {
   padding: 1px; /* Adding padding around help label in order to make entire keyboard focusing outline visible */
 }
 
 .sidebar-footer-button > .text-link {
   -moz-box-flex: 1;