Bug 1355324 - Create a popup to switch between sidebars from the sidebar header;r=Gijs
authorBrian Grinstead <bgrinstead@mozilla.com>
Tue, 16 May 2017 10:31:00 -0700
changeset 409093 e589d6b01b8d7b23c8807064b93a24144fa8ce31
parent 409092 6a25c340d83401d253b04b9c15c40ed5039c4132
child 409094 be8ef91f497cee68ec2a12fc734f5316c9bb9c42
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1355324
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1355324 - Create a popup to switch between sidebars from the sidebar header;r=Gijs MozReview-Commit-ID: HBwIfmtKybi
addon-sdk/source/test/test-ui-sidebar.js
browser/base/content/browser-sidebar.js
browser/base/content/browser.xul
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_bug409481.js
browser/base/content/test/sidebar/.eslintrc.js
browser/base/content/test/sidebar/browser.ini
browser/base/content/test/sidebar/browser_bug409481.js
browser/base/content/test/sidebar/browser_sidebar_switcher.js
browser/base/moz.build
browser/components/places/tests/browser/browser_sidebarpanels_click.js
browser/themes/linux/browser.css
browser/themes/osx/browser.css
browser/themes/shared/customizableui/panelUI.inc.css
browser/themes/shared/jar.inc.mn
browser/themes/shared/sidebar.inc.css
browser/themes/shared/sidebar/arrow-dropdown.svg
browser/themes/shared/sidebar/bookmark-filled.svg
browser/themes/shared/sidebar/close.svg
browser/themes/shared/sidebar/history.svg
browser/themes/shared/sidebar/sync.svg
browser/themes/windows/browser-aero.css
browser/themes/windows/browser.css
--- a/addon-sdk/source/test/test-ui-sidebar.js
+++ b/addon-sdk/source/test/test-ui-sidebar.js
@@ -1239,17 +1239,17 @@ exports.testShowToOpenXToClose = functio
   assert.ok(!isChecked(menuitem), 'menuitem is not checked');
 
   sidebar.show();
 
   yield shown.promise;
 
   assert.ok(isChecked(menuitem), 'menuitem is checked');
 
-  let closeButton = window.document.querySelector('#sidebar-header > toolbarbutton.close-icon');
+  let closeButton = window.document.querySelector('#sidebar-close');
   simulateCommand(closeButton);
 
   yield hidden.promise;
 
   assert.ok(!isChecked(menuitem), 'menuitem is not checked');
 
   sidebar.destroy();
 }
--- a/browser/base/content/browser-sidebar.js
+++ b/browser/base/content/browser-sidebar.js
@@ -26,30 +26,79 @@ var SidebarUI = {
   _title: null,
   _splitter: null,
 
   init() {
     this._box = document.getElementById("sidebar-box");
     this.browser = document.getElementById("sidebar");
     this._title = document.getElementById("sidebar-title");
     this._splitter = document.getElementById("sidebar-splitter");
+    this._icon = document.getElementById("sidebar-icon");
+    this._switcherPanel = document.getElementById("sidebarMenu-popup");
+    this._switcherTarget = document.getElementById("sidebar-switcher-target");
+    this._switcherArrow = document.getElementById("sidebar-switcher-arrow");
+
+    this._switcherTarget.addEventListener("command", () => {
+      this.toggleSwitcherPanel();
+    });
   },
 
   uninit() {
     let enumerator = Services.wm.getEnumerator(null);
     enumerator.getNext();
     if (!enumerator.hasMoreElements()) {
       document.persist("sidebar-box", "sidebarcommand");
       document.persist("sidebar-box", "width");
       document.persist("sidebar-box", "src");
       document.persist("sidebar-title", "value");
     }
   },
 
   /**
+   * Opens the switcher panel if it's closed, or closes it if it's open.
+   */
+  toggleSwitcherPanel() {
+    if (this._switcherPanel.state == "open" || this._switcherPanel.state == "showing") {
+      this.hideSwitcherPanel();
+    } else {
+      this.showSwitcherPanel();
+    }
+  },
+
+  hideSwitcherPanel() {
+    this._switcherPanel.hidePopup();
+  },
+
+  showSwitcherPanel() {
+    this._ensureShortcutsShown();
+    this._switcherPanel.addEventListener("popuphiding", () => {
+      this._switcherTarget.classList.remove("active");
+    }, {once: true});
+    this._switcherPanel.hidden = false;
+    this._switcherPanel.openPopup(this._icon);
+    this._switcherTarget.classList.add("active");
+  },
+
+  _addedShortcuts: false,
+  _ensureShortcutsShown() {
+    if (this._addedShortcuts) {
+      return;
+    }
+    this._addedShortcuts = true;
+    for (let button of this._switcherPanel.querySelectorAll("toolbarbutton[key]")) {
+      let keyId = button.getAttribute("key");
+      let key = document.getElementById(keyId);
+      if (!key) {
+        continue;
+      }
+      button.setAttribute("shortcut", ShortcutUtils.prettifyShortcut(key));
+    }
+  },
+
+  /**
    * Try and adopt the status of the sidebar from another window.
    * @param {Window} sourceWindow - Window to use as a source for sidebar status.
    * @return true if we adopted the state, or false if the caller should
    * initialize the state itself.
    */
   adoptFromWindow(sourceWindow) {
     // If the opener had a sidebar, open the same sidebar in our window.
     // The opener can be the hidden window too, if we're coming from the state
@@ -217,16 +266,18 @@ var SidebarUI = {
         } else {
           sidebarBroadcaster.setAttribute("checked", "true");
         }
       }
 
       this._box.hidden = false;
       this._splitter.hidden = false;
 
+      this.hideSwitcherPanel();
+
       this._box.setAttribute("sidebarcommand", sidebarBroadcaster.id);
       this.lastOpenedId = sidebarBroadcaster.id;
 
       let title = sidebarBroadcaster.getAttribute("sidebartitle");
       if (!title) {
         title = sidebarBroadcaster.getAttribute("label");
       }
       this._title.value = title;
@@ -271,16 +322,18 @@ var SidebarUI = {
   /**
    * Hide the sidebar.
    */
   hide() {
     if (!this.isOpen) {
       return;
     }
 
+    this.hideSwitcherPanel();
+
     let commandID = this._box.getAttribute("sidebarcommand");
     let sidebarBroadcaster = document.getElementById(commandID);
 
     if (sidebarBroadcaster.getAttribute("checked") != "true") {
       return;
     }
 
     // Replace the document currently displayed in the sidebar with about:blank
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -284,16 +284,51 @@
         <arrowscrollbox id="social-share-provider-buttons" orient="horizontal" flex="1" pack="end">
           <toolbarbutton id="add-share-provider" class="share-provider-button" type="radio"
                          group="share-providers" tooltiptext="&findShareServices.label;"
                          oncommand="SocialShare.showDirectory()"/>
         </arrowscrollbox>
       </hbox>
       <hbox id="share-container" flex="1"/>
     </panel>
+    <panel id="sidebarMenu-popup"
+           class="cui-widget-panel"
+           role="group"
+           type="arrow"
+           hidden="true"
+           flip="slide"
+           orient="vertical"
+           position="bottomcenter topleft">
+      <toolbarbutton id="sidebar-switcher-bookmarks"
+                     class="subviewbutton subviewbutton-iconic"
+                     key="viewBookmarksSidebarKb"
+                     observes="viewBookmarksSidebar"
+                     oncommand="SidebarUI.show('viewBookmarksSidebar');">
+         <observes element="viewBookmarksSidebar" attribute="checked"/>
+       </toolbarbutton>
+      <toolbarbutton id="sidebar-switcher-history"
+                     label="&historyButton.label;"
+                     class="subviewbutton subviewbutton-iconic"
+                     key="key_gotoHistory"
+                     observes="viewHistorySidebar"
+                     oncommand="SidebarUI.show('viewHistorySidebar');">
+         <observes element="viewHistorySidebar" attribute="checked"/>
+       </toolbarbutton>
+      <toolbarbutton id="sidebar-switcher-tabs"
+                     label="&syncedTabs.sidebar.label;"
+                     class="subviewbutton subviewbutton-iconic"
+                     observes="viewTabsSidebar"
+                     oncommand="SidebarUI.show('viewTabsSidebar');">
+         <observes element="viewTabsSidebar" attribute="checked"/>
+       </toolbarbutton>
+      <toolbarseparator/>
+      <toolbarbutton label="&sidebarCloseButton.tooltip;"
+                     class="subviewbutton"
+                     oncommand="SidebarUI.hide()"/>
+    </panel>
 
     <menupopup id="toolbar-context-menu"
                onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('viewToolbarsMenuSeparator'));">
       <menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
                 accesskey="&customizeMenu.moveToPanel.accesskey;"
                 label="&customizeMenu.moveToPanel.label;"
                 contexttype="toolbaritem"
                 class="customize-context-moveToPanel"/>
@@ -1110,19 +1145,24 @@
 
   <hbox id="fullscr-toggler" hidden="true"/>
 
   <deck id="content-deck" flex="1">
     <hbox flex="1" id="browser">
       <vbox id="browser-border-start" hidden="true" layer="true"/>
       <vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome">
         <sidebarheader id="sidebar-header" align="center">
-          <label id="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/>
+          <toolbarbutton id="sidebar-switcher-target" flex="1" class="tabbable">
+            <image id="sidebar-icon" consumeanchor="sidebar-switcher-target"/>
+            <label id="sidebar-title" persist="value" crop="end" control="sidebar"/>
+            <image id="sidebar-switcher-arrow"/>
+            <spacer flex="1"/>
+          </toolbarbutton>
           <image id="sidebar-throbber"/>
-          <toolbarbutton class="close-icon tabbable" tooltiptext="&sidebarCloseButton.tooltip;" oncommand="SidebarUI.hide();"/>
+          <toolbarbutton id="sidebar-close" class="tabbable" tooltiptext="&sidebarCloseButton.tooltip;" oncommand="SidebarUI.hide();"/>
         </sidebarheader>
         <browser id="sidebar" flex="1" autoscroll="false" disablehistory="true" disablefullscreen="true"
                   style="min-width: 14em; width: 18em; max-width: 36em;" tooltip="aHTMLTooltip"/>
       </vbox>
 
       <splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/>
       <vbox id="appcontent" flex="1">
         <notificationbox id="high-priority-global-notificationbox" notificationside="top"/>
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -135,18 +135,16 @@ skip-if = true # browser_bug321000.js is
 [browser_bug380960.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug386835.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug406216.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug408415.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
-[browser_bug409481.js]
-# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug409624.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug413915.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug416661.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_bug417483.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/sidebar/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test"
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/sidebar/browser.ini
@@ -0,0 +1,4 @@
+[DEFAULT]
+
+[browser_bug409481.js]
+[browser_sidebar_switcher.js]
rename from browser/base/content/test/general/browser_bug409481.js
rename to browser/base/content/test/sidebar/browser_bug409481.js
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/sidebar/browser_sidebar_switcher.js
@@ -0,0 +1,42 @@
+
+function showSwitcherPanelPromise() {
+  return new Promise(resolve => {
+    SidebarUI._switcherPanel.addEventListener("popupshown", () => {
+      resolve();
+    }, {once: true});
+    SidebarUI.showSwitcherPanel();
+  });
+}
+
+function clickSwitcherButton(querySelector) {
+  let sidebarPopup = document.querySelector("#sidebarMenu-popup");
+  let switcherPromise = Promise.all([
+    BrowserTestUtils.waitForEvent(window, "SidebarFocused"),
+    BrowserTestUtils.waitForEvent(sidebarPopup, "popuphidden"),
+  ]);
+  document.querySelector(querySelector).click();
+  return switcherPromise;
+}
+
+add_task(function* () {
+  // If a sidebar is already open, close it.
+  if (!document.getElementById("sidebar-box").hidden) {
+    ok(false, "Unexpected sidebar found - a previous test failed to cleanup correctly");
+    SidebarUI.hide();
+  }
+
+  let sidebar = document.querySelector("#sidebar-box");
+  yield SidebarUI.show("viewBookmarksSidebar");
+
+  yield showSwitcherPanelPromise();
+  yield clickSwitcherButton("#sidebar-switcher-history");
+  is(sidebar.getAttribute("sidebarcommand"), "viewHistorySidebar", "History sidebar loaded");
+
+  yield showSwitcherPanelPromise();
+  yield clickSwitcherButton("#sidebar-switcher-tabs");
+  is(sidebar.getAttribute("sidebarcommand"), "viewTabsSidebar", "Tabs sidebar loaded");
+
+  yield showSwitcherPanelPromise();
+  yield clickSwitcherButton("#sidebar-switcher-bookmarks");
+  is(sidebar.getAttribute("sidebarcommand"), "viewBookmarksSidebar", "Bookmarks sidebar loaded");
+});
--- a/browser/base/moz.build
+++ b/browser/base/moz.build
@@ -22,16 +22,17 @@ BROWSER_CHROME_MANIFESTS += [
     'content/test/general/browser.ini',
     'content/test/newtab/browser.ini',
     'content/test/pageinfo/browser.ini',
     'content/test/permissions/browser.ini',
     'content/test/plugins/browser.ini',
     'content/test/popupNotifications/browser.ini',
     'content/test/popups/browser.ini',
     'content/test/referrer/browser.ini',
+    'content/test/sidebar/browser.ini',
     'content/test/siteIdentity/browser.ini',
     'content/test/social/browser.ini',
     'content/test/static/browser.ini',
     'content/test/sync/browser.ini',
     'content/test/tabcrashed/browser.ini',
     'content/test/tabPrompts/browser.ini',
     'content/test/tabs/browser.ini',
     'content/test/urlbar/browser.ini',
--- a/browser/components/places/tests/browser/browser_sidebarpanels_click.js
+++ b/browser/components/places/tests/browser/browser_sidebarpanels_click.js
@@ -12,17 +12,17 @@ function test() {
   const BOOKMARKS_SIDEBAR_ID = "viewBookmarksSidebar";
   const BOOKMARKS_SIDEBAR_TREE_ID = "bookmarks-view";
   const HISTORY_SIDEBAR_ID = "viewHistorySidebar";
   const HISTORY_SIDEBAR_TREE_ID = "historyTree";
   const TEST_URL = "http://mochi.test:8888/browser/browser/components/places/tests/browser/sidebarpanels_click_test_page.html";
 
   // If a sidebar is already open, close it.
   if (!document.getElementById("sidebar-box").hidden) {
-    info("Unexpected sidebar found - a previous test failed to cleanup correctly");
+    ok(false, "Unexpected sidebar found - a previous test failed to cleanup correctly");
     SidebarUI.hide();
   }
 
   let sidebar = document.getElementById("sidebar");
   let tests = [];
   let currentTest;
 
   tests.push({
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -929,24 +929,23 @@ html|span.ac-emphasize-text-url {
 }
 
 /* Implements editBookmarkPanel resizing on folderTree un-collapse. */
 #editBMPanel_folderTree {
   min-width: 27em;
 }
 
 /* Content area */
+
+%include ../shared/sidebar.inc.css
+
 #sidebar {
   background-color: Window;
 }
 
-#sidebar-header > .close-icon:not(:hover):-moz-lwtheme-brighttext {
-  background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64);
-}
-
 .browserContainer > findbar {
   background-color: -moz-dialog;
   color: -moz-DialogText;
   text-shadow: none;
 }
 
 /* Tabstrip */
 
@@ -1075,22 +1074,16 @@ html|span.ac-emphasize-text-url {
 .alltabs-item[selected="true"] {
   font-weight: bold;
 }
 
 .alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon {
   list-style-image: url("chrome://global/skin/icons/loading.png");
 }
 
-/* Sidebar */
-#sidebar-throbber[loading="true"] {
-  list-style-image: url("chrome://global/skin/icons/loading.png");
-  margin-inline-end: 4px;
-}
-
 toolbarbutton.chevron {
   list-style-image: url("chrome://global/skin/toolbar/chevron.gif") !important;
 }
 
 toolbar[brighttext] toolbarbutton.chevron {
   list-style-image: url("chrome://global/skin/toolbar/chevron-inverted.png") !important;
 }
 
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -1359,88 +1359,25 @@ html|span.ac-emphasize-text-url {
 #historySwipeAnimationNextPage {
   box-shadow: 0 3px 6px rgba(0, 0, 0, 0.6);
 }
 
 #historySwipeAnimationContainer {
   background: url("chrome://browser/skin/subtle-pattern.png") #B3B9C1;
 }
 
+
 /* ----- SIDEBAR ELEMENTS ----- */
 
+%include ../shared/sidebar.inc.css
+
 #sidebar-box {
   -moz-appearance: -moz-mac-source-list;
-  box-shadow: inset -2px 0 0 hsla(0,0%,100%,.2);
 }
 
-sidebarheader {
-  padding: 2px 2px 0;
-  text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
-}
-
-.sidebar-splitter {
-  border-inline-start: none;
-  border-inline-end: 1px solid #b4b4b4;
-  min-width: 1px;
-  width: 3px;
-  background-image: none !important;
-  background-color: transparent;
-  margin-inline-start: -3px;
-  position: relative;
-}
-
-#appcontent ~ .sidebar-splitter {
-  border-inline-start: 1px solid #ccc;
-  border-inline-end: none;
-  margin-inline-start: 0;
-  margin-inline-end: -3px;
-}
-
-.sidebar-title,
-#sidebar-title {
-  color: #596c80;
-  font-weight: bold;
-}
-
-.sidebar-title:-moz-window-inactive,
-#sidebar-title:-moz-window-inactive {
-  color: #868b92;
-}
-
-.sidebar-throbber[loading="true"],
-#sidebar-throbber[loading="true"] {
-  list-style-image: url("chrome://global/skin/icons/loading.png");
-}
-
-@media (min-resolution: 2dppx) {
-  .sidebar-throbber[loading="true"],
-  #sidebar-throbber[loading="true"] {
-    list-style-image: url("chrome://global/skin/icons/loading@2x.png");
-    width: 16px;
-  }
-}
-
-@media (-moz-mac-yosemite-theme) {
-  #sidebar-box {
-    box-shadow: none;
-  }
-
-  sidebarheader {
-    text-shadow: none;
-    font-weight: 500;
-  }
-
-  .sidebar-title,
-  #sidebar-title {
-    color: #636363;
-    font-weight: 500;
-  }
-}
-
-
 /* ----- CONTENT ----- */
 
 .browserContainer > findbar {
   background: @scopeBarBackground@;
   border-top: @scopeBarSeparatorBorder@;
   color: -moz-DialogText;
   text-shadow: none;
 }
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -1108,35 +1108,35 @@ panelview:not([mainView]) .subviewbutton
 
 .subviewbutton:not(.panel-subview-footer) > .toolbarbutton-text,
 /* Bookmark items need a more specific selector. */
 .PanelUI-subView .subviewbutton:not(.panel-subview-footer) > .menu-text,
 .PanelUI-subView .subviewbutton:not(.panel-subview-footer) > .menu-iconic-text {
   font: menu;
 }
 
-.PanelUI-subView .subviewbutton[shortcut]::after {
+.subviewbutton[shortcut]::after {
   content: attr(shortcut);
   float: right;
   color: GrayText;
 }
 
 .PanelUI-subView .subviewbutton-nav::after {
   -moz-context-properties: fill;
   content: url(chrome://browser/skin/menu-icons/back-small.svg);
   fill: GrayText;
   float: right;
 }
 
 .PanelUI-subView .subviewbutton-nav:-moz-locale-dir(ltr)::after {
   transform: scaleX(-1);
 }
 
-.PanelUI-subView.cui-widget-panelview .subviewbutton[shortcut]::after,
-photonpanelmultiview .PanelUI-subView .subviewbutton[shortcut]::after,
+.subviewbutton[shortcut]::after,
+.subviewbutton[shortcut]::after,
 .PanelUI-subView .subviewbutton-nav::after {
   margin-inline-start: 10px;
 }
 
 /* This is a <label> but it should fit in with the menu font- and colorwise. */
 #PanelUI-characterEncodingView-autodetect-label {
   font: menu;
   color: inherit;
@@ -1273,17 +1273,18 @@ menuitem.panel-subview-footer@menuStateA
 /* Disabled (empty) item is always alone and never has an icon, so fix its left padding */
 #BMB_bookmarksPopup menupopup[emptyplacesresult] .bookmark-item.subviewbutton {
   padding-left: 6px;
 }
 
 #widget-overflow-scroller > toolbarseparator,
 .PanelUI-subView menuseparator,
 .PanelUI-subView toolbarseparator,
-.cui-widget-panelview menuseparator {
+.cui-widget-panelview menuseparator,
+.cui-widget-panel toolbarseparator {
   -moz-appearance: none;
   min-height: 0;
   border-top: 1px solid var(--panel-separator-color);
   border-bottom: none;
   margin: 6px 0;
   padding: 0;
 }
 
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -42,16 +42,21 @@
   skin/classic/browser/customizableui/menuPanel-customizeFinish.png  (../shared/customizableui/menuPanel-customizeFinish.png)
   skin/classic/browser/customizableui/menuPanel-customizeFinish@2x.png  (../shared/customizableui/menuPanel-customizeFinish@2x.png)
   skin/classic/browser/customizableui/panelarrow-customizeTip.png  (../shared/customizableui/panelarrow-customizeTip.png)
   skin/classic/browser/customizableui/panelarrow-customizeTip@2x.png  (../shared/customizableui/panelarrow-customizeTip@2x.png)
   skin/classic/browser/customizableui/subView-arrow-back-inverted.png  (../shared/customizableui/subView-arrow-back-inverted.png)
   skin/classic/browser/customizableui/subView-arrow-back-inverted@2x.png  (../shared/customizableui/subView-arrow-back-inverted@2x.png)
   skin/classic/browser/customizableui/subView-arrow-back-inverted-rtl.png  (../shared/customizableui/subView-arrow-back-inverted-rtl.png)
   skin/classic/browser/customizableui/subView-arrow-back-inverted-rtl@2x.png  (../shared/customizableui/subView-arrow-back-inverted-rtl@2x.png)
+  skin/classic/browser/sidebar/arrow-dropdown.svg           (../shared/sidebar/arrow-dropdown.svg)
+  skin/classic/browser/sidebar/bookmark-filled.svg          (../shared/sidebar/bookmark-filled.svg)
+  skin/classic/browser/sidebar/close.svg                    (../shared/sidebar/close.svg)
+  skin/classic/browser/sidebar/history.svg                  (../shared/sidebar/history.svg)
+  skin/classic/browser/sidebar/sync.svg                     (../shared/sidebar/sync.svg)
   skin/classic/browser/customizableui/whimsy.png               (../shared/customizableui/whimsy.png)
   skin/classic/browser/customizableui/whimsy@2x.png            (../shared/customizableui/whimsy@2x.png)
   skin/classic/browser/downloads/contentAreaDownloadsView.css  (../shared/downloads/contentAreaDownloadsView.css)
   skin/classic/browser/downloads/download-blocked.svg          (../shared/downloads/download-blocked.svg)
   skin/classic/browser/downloads/download-summary.svg          (../shared/downloads/download-summary.svg)
   skin/classic/browser/drm-icon.svg                            (../shared/drm-icon.svg)
   skin/classic/browser/fullscreen/insecure.svg                 (../shared/fullscreen/insecure.svg)
   skin/classic/browser/fullscreen/secure.svg                   (../shared/fullscreen/secure.svg)
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/sidebar.inc.css
@@ -0,0 +1,125 @@
+%if 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+%endif
+
+#sidebar-box {
+  --icon-fill: rgba(12, 12, 13, 0.8);
+  --header-background-color: #F2F2F2;
+  --header-background-color-hover: rgba(204, 204, 204, 0.6);
+  --title-font-size: 13px;
+}
+
+.sidebar-header,
+#sidebar-header {
+  padding: 4px;
+  background-color: var(--header-background-color);
+  text-shadow: none;
+}
+
+.sidebar-splitter {
+  -moz-appearance: none;
+  border: 0 solid #ccc;
+  border-inline-end-width: 1px;
+  min-width: 1px;
+  width: 3px;
+  background-image: none !important;
+  background-color: transparent;
+  margin-inline-start: -3px;
+  position: relative;
+}
+
+#appcontent ~ .sidebar-splitter {
+  border-inline-end-width: 0;
+  border-inline-start-width: 1px;
+  margin-inline-start: 0;
+  margin-inline-end: -3px;
+}
+
+#sidebar-throbber[loading="true"] {
+  list-style-image: url("chrome://global/skin/icons/loading.png");
+}
+
+@media (min-resolution: 2dppx) {
+  .sidebar-throbber[loading="true"],
+  #sidebar-throbber[loading="true"] {
+    list-style-image: url("chrome://global/skin/icons/loading@2x.png");
+    width: 16px;
+  }
+}
+
+.sidebar-title,
+#sidebar-title {
+  margin: 0;
+  padding: 0;
+  padding-inline-start: 8px;
+  padding-inline-end: 4px;
+  color: -moz-DialogText;
+  font-size: var(--title-font-size);
+}
+
+#sidebar-switcher-arrow {
+  -moz-context-properties: fill;
+  fill: var(--icon-fill);
+  list-style-image: url(chrome://browser/skin/sidebar/arrow-dropdown.svg);
+  width: 12px;
+  height: 12px;
+}
+
+#sidebar-close {
+  -moz-appearance: none;
+  -moz-context-properties: fill;
+  fill: var(--icon-fill);
+  list-style-image: url(chrome://browser/skin/sidebar/close.svg);
+  margin: 0;
+  padding: 4px;
+}
+
+#sidebar-switcher-target {
+  -moz-appearance: none;
+  padding: 4px;
+  margin-inline-end: 4px;
+}
+
+#sidebar-box #sidebar-switcher-target:hover,
+#sidebar-switcher-target.active,
+#sidebar-close:hover {
+  background: var(--header-background-color-hover);
+}
+
+#sidebarMenu-popup .subviewbutton {
+  min-width: 190px;
+}
+
+%ifndef XP_MACOSX
+/* Allow room for the checkbox drawn as a background image at the start of the toolbarbutton */
+#sidebarMenu-popup .subviewbutton-iconic > .toolbarbutton-icon {
+  padding-inline-start: 16px;
+}
+#sidebarMenu-popup .subviewbutton-iconic > .toolbarbutton-text {
+  padding-inline-start: 0;
+}
+%endif
+
+/* Use bookmarks star as default icon for the sidebar box (including when opening a web page) */
+#sidebar-switcher-bookmarks > .toolbarbutton-icon,
+#sidebar-box #sidebar-icon {
+  -moz-context-properties: fill;
+  fill: var(--icon-fill);
+  list-style-image: url(chrome://browser/skin/sidebar/bookmark-filled.svg);
+}
+
+#sidebar-switcher-history > .toolbarbutton-icon,
+#sidebar-box[sidebarcommand="viewHistorySidebar"] #sidebar-icon {
+  -moz-context-properties: fill;
+  fill: var(--icon-fill);
+  list-style-image: url(chrome://browser/skin/sidebar/history.svg);
+}
+
+#sidebar-switcher-tabs > .toolbarbutton-icon,
+#sidebar-box[sidebarcommand="viewTabsSidebar"] #sidebar-icon {
+  -moz-context-properties: fill;
+  fill: var(--icon-fill);
+  list-style-image: url(chrome://browser/skin/sidebar/sync.svg);
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/sidebar/arrow-dropdown.svg
@@ -0,0 +1,6 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" d="M8 12a1 1 0 0 1-.707-.293l-5-5a1 1 0 0 1 1.414-1.414L8 9.586l4.293-4.293a1 1 0 0 1 1.414 1.414l-5 5A1 1 0 0 1 8 12z"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/sidebar/bookmark-filled.svg
@@ -0,0 +1,6 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" d="M15.845 6.064A1.1 1.1 0 0 0 15 5.331L10.911 4.6 8.985.735a1.1 1.1 0 0 0-1.969 0L5.089 4.6l-4.081.729a1.1 1.1 0 0 0-.615 1.834L3.32 10.31l-.609 4.36a1.1 1.1 0 0 0 1.6 1.127L8 13.873l3.69 1.927a1.1 1.1 0 0 0 1.6-1.127l-.61-4.363 2.926-3.146a1.1 1.1 0 0 0 .239-1.1z"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/sidebar/close.svg
@@ -0,0 +1,6 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" d="M9.061,8l3.47-3.47A.75.75,0,0,0,11.47,3.47L8,6.939,4.53,3.47A.75.75,0,0,0,3.47,4.53L6.939,8,3.47,11.47A.75.75,0,1,0,4.53,12.53L8,9.061l3.47,3.47A.75.75,0,0,0,12.53,11.47Z"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/sidebar/history.svg
@@ -0,0 +1,6 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" d="M8 0a8 8 0 1 0 8 8 8.009 8.009 0 0 0-8-8zm0 14a6 6 0 1 1 6-6 6.007 6.007 0 0 1-6 6zm3.5-6H8V4.5a.5.5 0 0 0-1 0v4a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 0-1z"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/sidebar/sync.svg
@@ -0,0 +1,6 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" d="M14 1a1 1 0 0 0-1 1v1.146A6.948 6.948 0 0 0 1.227 6.307a1 1 0 1 0 1.94.484A4.983 4.983 0 0 1 8 3a4.919 4.919 0 0 1 3.967 2H10a1 1 0 0 0 0 2h4a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1zm.046 7.481a1 1 0 0 0-1.213.728A4.983 4.983 0 0 1 8 13a4.919 4.919 0 0 1-3.967-2H6a1 1 0 0 0 0-2H2a1 1 0 0 0-1 1v4a1 1 0 0 0 2 0v-1.146a6.948 6.948 0 0 0 11.773-3.161 1 1 0 0 0-.727-1.212z"/>
+</svg>
--- a/browser/themes/windows/browser-aero.css
+++ b/browser/themes/windows/browser-aero.css
@@ -11,57 +11,24 @@
   }
 }
 
 @media (-moz-windows-default-theme) {
   .sidebar-header,
   #sidebar-header {
     -moz-appearance: none;
     border-bottom: none;
-    text-shadow: none;
-  }
-
-  .sidebar-title,
-  #sidebar-title {
-    font-weight: bold;
-  }
-
-  .sidebar-splitter {
-    border: 0;
-    border-inline-end: 1px solid ThreeDLightShadow;
-    min-width: 0;
-    width: 3px;
-    background-color: transparent;
-    margin-inline-start: -3px;
-    position: relative;
-  }
-
-  #appcontent ~ .sidebar-splitter {
-    border-inline-start: 1px solid ThreeDLightShadow;
-    border-inline-end: none;
-    margin-inline-start: 0;
-    margin-inline-end: -3px;
   }
 
   .menu-accel,
   .menu-iconic-accel {
     color: graytext;
   }
 
   @media (-moz-os-version: windows-win7) {
-    .sidebar-header:not(:-moz-lwtheme),
-    #sidebar-header:not(:-moz-lwtheme) {
-      background-color: #EEF3FA;
-    }
-
-    .sidebar-splitter,
-    #appcontent ~ .sidebar-splitter {
-      border-color: #A9B7C9;
-    }
-
     #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar):not(:-moz-lwtheme),
     #browser-bottombox:not(:-moz-lwtheme),
     .browserContainer > findbar {
       background-color: @customToolbarColor@;
     }
 
     .tab-background-middle[selected=true]:not(:-moz-lwtheme) {
       background-color: @customToolbarColor@;
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -1383,50 +1383,22 @@ treechildren.searchbar-treebody::-moz-tr
 
 /* Implements editBookmarkPanel resizing on folderTree un-collapse. */
 #editBMPanel_folderTree {
   min-width: 27em;
 }
 
 /* ::::: content area ::::: */
 
+%include ../shared/sidebar.inc.css
+
 #sidebar {
   background-color: Window;
 }
 
-#sidebar-title {
-  padding-inline-start: 0px;
-}
-
-#sidebar-header > .close-icon {
-  -moz-appearance: none;
-  padding: 2px;
-  margin: 0;
-  border: none;
-}
-
-@media not all and (min-resolution: 1.1dppx) {
-  #sidebar-header > .close-icon:-moz-lwtheme-brighttext {
-    list-style-image: url("chrome://global/skin/icons/close-inverted.png");
-  }
-}
-
-@media (min-resolution: 1.1dppx) {
-  #sidebar-header > .close-icon:-moz-lwtheme-brighttext {
-    list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png");
-  }
-}
-
-@media (-moz-os-version: windows-win7) {
-  #sidebar-header > .close-icon {
-    padding-top: 4px;
-    padding-bottom: 4px;
-  }
-}
-
 .browserContainer > findbar {
   background-color: -moz-dialog;
   color: -moz-DialogText;
   text-shadow: none;
 }
 
 /* Tabstrip */
 
@@ -1590,28 +1562,16 @@ toolbarbutton.chevron > .toolbarbutton-t
 toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
   display: none;
 }
 
 toolbarbutton.chevron > .toolbarbutton-icon {
   margin: 0;
 }
 
-#sidebar-throbber[loading="true"] {
-  list-style-image: url("chrome://global/skin/icons/loading.png");
-  margin-inline-end: 4px;
-}
-
-@media (min-resolution: 1.1dppx) {
-  #sidebar-throbber[loading="true"] {
-    list-style-image: url("chrome://global/skin/icons/loading@2x.png");
-    width: 16px;
-  }
-}
-
 /* Bookmarks toolbar */
 #PlacesToolbarDropIndicator {
   list-style-image: url(chrome://browser/skin/places/toolbarDropMarker.png);
 }
 
 toolbarbutton.bookmark-item[dragover="true"][open="true"] {
   -moz-appearance: none;
   background: Highlight !important;