Bug 1444301 - Move dock functions to a new meatball menu; r=jryans
authorBrian Birtles <birtles@gmail.com>
Thu, 05 Apr 2018 10:13:21 +0900
changeset 412179 0f07755ee54f665c18a0f16449481edefa3e200e
parent 412178 b34330320b8c06cf1faaaeb1ff41e9f14f42af31
child 412180 a6afc78b217ee54d3a9de7f58d2710d104e2ad54
push id62302
push userbbirtles@mozilla.com
push dateFri, 06 Apr 2018 21:15:54 +0000
treeherderautoland@c5e2ad71fce5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjryans
bugs1444301
milestone61.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 1444301 - Move dock functions to a new meatball menu; r=jryans MozReview-Commit-ID: IfFsiZnmw74
devtools/client/framework/components/toolbox-controller.js
devtools/client/framework/components/toolbox-toolbar.js
devtools/client/framework/toolbox.js
devtools/client/jar.mn
devtools/client/locales/en-US/toolbox.properties
devtools/client/themes/images/dock-bottom.svg
devtools/client/themes/images/dock-side.svg
devtools/client/themes/images/dock-undock.svg
devtools/client/themes/images/more.svg
devtools/client/themes/toolbox.css
devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_nodes_highlight.js
devtools/client/webconsole/test/head.js
--- a/devtools/client/framework/components/toolbox-controller.js
+++ b/devtools/client/framework/components/toolbox-controller.js
@@ -21,33 +21,33 @@ class ToolboxController extends Componen
     // state, and for the definitions of the props that are expected to be passed in.
     this.state = {
       focusedButton: ELEMENT_PICKER_ID,
       toolboxButtons: [],
       currentToolId: null,
       highlightedTools: new Set(),
       panelDefinitions: [],
       hostTypes: [],
-      areDockButtonsEnabled: true,
+      areDockOptionsEnabled: true,
       canCloseToolbox: true,
       canRender: false,
       buttonIds: [],
       checkedButtonsUpdated: () => {
         this.forceUpdate();
       }
     };
 
     this.setFocusedButton = this.setFocusedButton.bind(this);
     this.setToolboxButtons = this.setToolboxButtons.bind(this);
     this.setCurrentToolId = this.setCurrentToolId.bind(this);
     this.highlightTool = this.highlightTool.bind(this);
     this.unhighlightTool = this.unhighlightTool.bind(this);
     this.setOptionsPanel = this.setOptionsPanel.bind(this);
     this.setHostTypes = this.setHostTypes.bind(this);
-    this.setDockButtonsEnabled = this.setDockButtonsEnabled.bind(this);
+    this.setDockOptionsEnabled = this.setDockOptionsEnabled.bind(this);
     this.setCanCloseToolbox = this.setCanCloseToolbox.bind(this);
     this.setCanRender = this.setCanRender.bind(this);
     this.setPanelDefinitions = this.setPanelDefinitions.bind(this);
     this.updateButtonIds = this.updateButtonIds.bind(this);
     this.updateFocusedButton = this.updateFocusedButton.bind(this);
   }
 
   shouldComponentUpdate() {
@@ -64,28 +64,26 @@ class ToolboxController extends Componen
    * The button and tab ids must be known in order to be able to focus left and right
    * using the arrow keys.
    */
   updateButtonIds() {
     const {
       toolboxButtons,
       panelDefinitions,
       optionsPanel,
-      hostTypes,
       canCloseToolbox,
     } = this.state;
 
     // This is a little gnarly, but go through all of the state and extract the IDs.
     this.setState({
       buttonIds: [
         ...toolboxButtons.filter(btn => btn.isInStartContainer).map(({id}) => id),
         ...panelDefinitions.map(({id}) => id),
         ...toolboxButtons.filter(btn => !btn.isInStartContainer).map(({id}) => id),
         optionsPanel ? optionsPanel.id : null,
-        ...hostTypes.map(({position}) => "toolbox-dock-" + position),
         canCloseToolbox ? "toolbox-close" : null
       ].filter(id => id)
     });
 
     this.updateFocusedButton();
   }
 
   updateFocusedButton() {
@@ -129,22 +127,22 @@ class ToolboxController extends Componen
   unhighlightTool(id) {
     let { highlightedTools } = this.state;
     if (highlightedTools.has(id)) {
       highlightedTools.delete(id);
       this.setState({ highlightedTools });
     }
   }
 
-  setDockButtonsEnabled(areDockButtonsEnabled) {
-    this.setState({ areDockButtonsEnabled }, this.updateButtonIds);
+  setDockOptionsEnabled(areDockOptionsEnabled) {
+    this.setState({ areDockOptionsEnabled });
   }
 
   setHostTypes(hostTypes) {
-    this.setState({ hostTypes }, this.updateButtonIds);
+    this.setState({ hostTypes });
   }
 
   setCanCloseToolbox(canCloseToolbox) {
     this.setState({ canCloseToolbox }, this.updateButtonIds);
   }
 
   setPanelDefinitions(panelDefinitions) {
     this.setState({ panelDefinitions }, this.updateButtonIds);
--- a/devtools/client/framework/components/toolbox-toolbar.js
+++ b/devtools/client/framework/components/toolbox-toolbar.js
@@ -3,16 +3,18 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 const { Component, createFactory } = require("devtools/client/shared/vendor/react");
 const dom = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 const {div, button} = dom;
 
+const Menu = require("devtools/client/framework/menu");
+const MenuItem = require("devtools/client/framework/menu-item");
 const ToolboxTab = createFactory(require("devtools/client/framework/components/toolbox-tab"));
 const ToolboxTabs = createFactory(require("devtools/client/framework/components/toolbox-tabs"));
 
 /**
  * This is the overall component for the toolbox toolbar. It is designed to not know how
  * the state is being managed, and attempts to be as pure as possible. The
  * ToolboxController component controls the changing state, and passes in everything as
  * props.
@@ -70,17 +72,17 @@ class ToolboxToolbar extends Component {
       ? (
         div(
           containerProps,
           renderToolboxButtonsStart(this.props),
           ToolboxTabs(this.props),
           renderToolboxButtonsEnd(this.props),
           renderOptions(this.props),
           renderSeparator(),
-          renderDockButtons(this.props)
+          renderToolboxControls(this.props)
         )
       )
       : div(containerProps);
   }
 }
 
 module.exports = ToolboxToolbar;
 
@@ -188,69 +190,65 @@ function renderOptions({focusedButton, c
 /**
  * Render a separator.
  */
 function renderSeparator() {
   return div({className: "devtools-separator"});
 }
 
 /**
- * Render the dock buttons, and handle all the cases for what type of host the toolbox
- * is attached to. The following props are expected.
+ * Render the toolbox control buttons. The following props are expected:
  *
  * @param {string} focusedButton
  *        The id of the focused button.
  * @param {Object[]} hostTypes
  *        Array of host type objects.
  * @param {string} hostTypes[].position
  *        Position name.
  * @param {Function} hostTypes[].switchHost
  *        Function to switch the host.
- * @param {boolean} areDockButtonsEnabled
+ * @param {boolean} areDockOptionsEnabled
  *        They are not enabled in certain situations like when they are in the
  *        WebIDE.
  * @param {boolean} canCloseToolbox
  *        Do we need to add UI for closing the toolbox? We don't when the
  *        toolbox is undocked, for example.
  * @param {Function} closeToolbox
  *        Completely close the toolbox.
  * @param {Function} focusButton
  *        Keep a record of the currently focused button.
  * @param {Object} L10N
  *        Localization interface.
  */
-function renderDockButtons(props) {
+function renderToolboxControls(props) {
   const {
     focusedButton,
     closeToolbox,
     hostTypes,
     focusButton,
     L10N,
-    areDockButtonsEnabled,
+    areDockOptionsEnabled,
     canCloseToolbox,
   } = props;
 
-  let buttons = [];
+  const meatballMenuButtonId = "toolbox-meatball-menu-button";
 
-  if (areDockButtonsEnabled) {
-    hostTypes.forEach(hostType => {
-      const id = "toolbox-dock-" + hostType.position;
-      buttons.push(button({
-        id,
-        onFocus: () => focusButton(id),
-        className: "toolbox-dock-button devtools-button",
-        title: L10N.getStr(`toolboxDockButtons.${hostType.position}.tooltip`),
-        onClick: e => {
-          hostType.switchHost();
-          focusButton(id);
-        },
-        tabIndex: focusedButton === id ? "0" : "-1",
-      }));
-    });
-  }
+  const meatballMenuButton = button({
+    id: meatballMenuButtonId,
+    onFocus: () => focusButton(meatballMenuButtonId),
+    className: "devtools-button",
+    title: L10N.getStr("toolbox.meatballMenu.button.tooltip"),
+    onClick: evt => {
+      showMeatballMenu(evt.target, {
+        ...props,
+        hostTypes: areDockOptionsEnabled ? hostTypes : [],
+      });
+    },
+    tabIndex: focusedButton === meatballMenuButtonId ? "0" : "-1",
+  });
 
   const closeButtonId = "toolbox-close";
 
   const closeButton = canCloseToolbox
     ? button({
       id: closeButtonId,
       onFocus: () => focusButton(closeButtonId),
       className: "devtools-button",
@@ -258,12 +256,58 @@ function renderDockButtons(props) {
       onClick: () => {
         closeToolbox();
       },
       tabIndex: focusedButton === "toolbox-close" ? "0" : "-1",
     })
     : null;
 
   return div({id: "toolbox-controls"},
-    div({id: "toolbox-dock-buttons"}, ...buttons),
+    meatballMenuButton,
     closeButton
   );
 }
+
+/**
+ * Display the "..." menu (affectionately known as the meatball menu).
+ *
+ * @param {Object} menuButton
+ *        The <button> element from which the menu should pop out. The geometry
+ *        of this element is used to position the menu.
+ * @param {Object} props
+ *        Properties as described below.
+ * @param {Object[]} props.hostTypes
+ *        Array of host type objects.
+ * @param {string} props.hostTypes[].position
+ *        Position name.
+ * @param {Function} props.hostTypes[].switchHost
+ *        Function to switch the host.
+ *        This array will be empty if we shouldn't shouldn't show any dock
+ *        options.
+ * @param {Object} props.L10N
+ *        Localization interface.
+ * @param {Object} props.toolbox
+ *        The devtools toolbox. Used by the Menu component to determine which
+ *        document to use.
+ */
+function showMeatballMenu(menuButton, {hostTypes, L10N, toolbox}) {
+  const menu = new Menu({ id: "toolbox-meatball-menu" });
+
+  for (const hostType of hostTypes) {
+    menu.append(new MenuItem({
+      id: `toolbox-meatball-menu-dock-${hostType.position}`,
+      label: L10N.getStr(
+        `toolbox.meatballMenu.dock.${hostType.position}.label`
+      ),
+      click: () => hostType.switchHost(),
+    }));
+  }
+
+  // (Yes, it's true we might end up with an empty menu here. Don't worry,
+  // by the end of this patch series that won't be the case.)
+
+  const rect = menuButton.getBoundingClientRect();
+  const screenX = menuButton.ownerDocument.defaultView.mozInnerScreenX;
+  const screenY = menuButton.ownerDocument.defaultView.mozInnerScreenY;
+
+  // Display the popup below the button.
+  menu.popup(rect.left + screenX, rect.bottom + screenY, toolbox);
+}
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -486,17 +486,17 @@ Toolbox.prototype = {
 
       this.shortcuts = new KeyShortcuts({
         window: this.doc.defaultView
       });
       // Get the DOM element to mount the ToolboxController to.
       this._componentMount = this.doc.getElementById("toolbox-toolbar-mount");
 
       this._mountReactComponent();
-      this._buildDockButtons();
+      this._buildDockOptions();
       this._buildOptions();
       this._buildTabs();
       this._applyCacheSettings();
       this._applyServiceWorkersTestingSettings();
       this._addKeysToWindow();
       this._addReloadKeys();
       this._addHostListeners();
       this._registerOverlays();
@@ -1044,26 +1044,26 @@ Toolbox.prototype = {
       this._notificationBox = Object.assign(
         this.ReactDOM.render(NotificationBox({}), box),
         PriorityLevels);
     }
     return this._notificationBox;
   },
 
   /**
-   * Build the buttons for changing hosts. Called every time
+   * Build the options for changing hosts. Called every time
    * the host changes.
    */
-  _buildDockButtons: function() {
+  _buildDockOptions: function() {
     if (!this._target.isLocalTab) {
-      this.component.setDockButtonsEnabled(false);
+      this.component.setDockOptionsEnabled(false);
       return;
     }
 
-    this.component.setDockButtonsEnabled(true);
+    this.component.setDockOptionsEnabled(true);
     this.component.setCanCloseToolbox(this.hostType !== Toolbox.HostType.WINDOW);
 
     let sideEnabled = Services.prefs.getBoolPref(this._prefs.SIDE_ENABLED);
 
     let hostTypes = [];
     for (let type in Toolbox.HostType) {
       let position = Toolbox.HostType[type];
       if (position == this.hostType ||
@@ -2350,17 +2350,17 @@ Toolbox.prototype = {
     });
 
     return this.once("host-changed");
   },
 
   _onSwitchedHost: function({ hostType }) {
     this._hostType = hostType;
 
-    this._buildDockButtons();
+    this._buildDockOptions();
     this._addKeysToWindow();
 
     // We blurred the tools at start of switchHost, but also when clicking on
     // host switching button. We now have to restore the focus.
     this.focusTool(this.currentToolId, true);
 
     this.emit("host-changed");
     this._telemetry.log(HOST_HISTOGRAM, this._getTelemetryHostId());
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -180,31 +180,29 @@ devtools.jar:
     skin/images/item-toggle.svg (themes/images/item-toggle.svg)
     skin/images/item-arrow-dark-rtl.svg (themes/images/item-arrow-dark-rtl.svg)
     skin/images/item-arrow-dark-ltr.svg (themes/images/item-arrow-dark-ltr.svg)
     skin/images/item-arrow-rtl.svg (themes/images/item-arrow-rtl.svg)
     skin/images/item-arrow-ltr.svg (themes/images/item-arrow-ltr.svg)
     skin/images/dropmarker.svg (themes/images/dropmarker.svg)
     skin/boxmodel.css (themes/boxmodel.css)
     skin/images/geometry-editor.svg (themes/images/geometry-editor.svg)
+    skin/images/more.svg (themes/images/more.svg)
     skin/images/pause.svg (themes/images/pause.svg)
     skin/images/play.svg (themes/images/play.svg)
     skin/images/rewind.svg (themes/images/rewind.svg)
     skin/images/debugger-step-in.svg (themes/images/debugger-step-in.svg)
     skin/images/debugger-step-out.svg (themes/images/debugger-step-out.svg)
     skin/images/debugger-step-over.svg (themes/images/debugger-step-over.svg)
     skin/images/debugger-toggleBreakpoints.svg (themes/images/debugger-toggleBreakpoints.svg)
     skin/images/jump-definition.svg (themes/images/jump-definition.svg)
     skin/images/tracer-icon.png (themes/images/tracer-icon.png)
     skin/images/tracer-icon@2x.png (themes/images/tracer-icon@2x.png)
     skin/images/toggle-tools.png (themes/images/toggle-tools.png)
     skin/images/toggle-tools@2x.png (themes/images/toggle-tools@2x.png)
-    skin/images/dock-bottom.svg (themes/images/dock-bottom.svg)
-    skin/images/dock-side.svg (themes/images/dock-side.svg)
-    skin/images/dock-undock.svg (themes/images/dock-undock.svg)
     skin/floating-scrollbars-dark-theme.css (themes/floating-scrollbars-dark-theme.css)
     skin/floating-scrollbars-responsive-design.css (themes/floating-scrollbars-responsive-design.css)
     skin/inspector.css (themes/inspector.css)
     skin/images/profiler-stopwatch.svg (themes/images/profiler-stopwatch.svg)
     skin/images/debugging-addons.svg (themes/images/debugging-addons.svg)
     skin/images/debugging-tabs.svg (themes/images/debugging-tabs.svg)
     skin/images/debugging-workers.svg (themes/images/debugging-workers.svg)
     skin/images/gcli_sec_bad.svg (themes/images/gcli_sec_bad.svg)
@@ -304,9 +302,9 @@ devtools.jar:
     content/netmonitor/index.html (netmonitor/index.html)
     content/netmonitor/initializer.js (netmonitor/initializer.js)
 
     # Devtools-components
     skin/images/devtools-components/arrow.svg (themes/images/devtools-components/arrow.svg)
 
     # Devtools-reps
     skin/images/devtools-reps/jump-definition.svg (themes/images/devtools-reps/jump-definition.svg)
-    skin/images/devtools-reps/open-inspector.svg (themes/images/devtools-reps/open-inspector.svg)
\ No newline at end of file
+    skin/images/devtools-reps/open-inspector.svg (themes/images/devtools-reps/open-inspector.svg)
--- a/devtools/client/locales/en-US/toolbox.properties
+++ b/devtools/client/locales/en-US/toolbox.properties
@@ -1,16 +1,12 @@
 # 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/.
 
-toolboxDockButtons.bottom.tooltip=Dock to bottom of browser window
-toolboxDockButtons.side.tooltip=Dock to side of browser window
-toolboxDockButtons.window.tooltip=Show in separate window
-
 # LOCALIZATION NOTE (toolboxToggleButton.errors): Semi-colon list of plural
 # forms.
 # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
 # #1 number of errors in the current web page
 toolboxToggleButton.errors=#1 error;#1 errors
 
 # LOCALIZATION NOTE (toolboxToggleButton.warnings): Semi-colon list of plural
 # forms.
@@ -147,16 +143,27 @@ toolbox.frames.tooltip=Select an iframe 
 toolbox.showFrames.key=Alt+Down
 
 # LOCALIZATION NOTE (toolbox.noautohide.tooltip): This is the label for
 # the button to force the popups/panels to stay visible on blur.
 # This is only visible in the browser toolbox as it is meant for
 # addon developers and Firefox contributors.
 toolbox.noautohide.tooltip=Disable popup auto hide
 
+# LOCALIZATION NOTE (toolbox.meatballMenu.button.tooltip): This is the tooltip
+# for the "..." button on the developer tools toolbox.
+toolbox.meatballMenu.button.tooltip=Customize Developer Tools and get help
+
+# LOCALIZATION NOTE (toolbox.meatballMenu.dock.*.label): These labels are shown
+# in the "..." menu in the toolbox and represent the different arrangements for
+# docking (or undocking) the developer tools toolbox.
+toolbox.meatballMenu.dock.bottom.label=Dock to bottom
+toolbox.meatballMenu.dock.side.label=Dock to side
+toolbox.meatballMenu.dock.window.label=Undock
+
 # LOCALIZATION NOTE (toolbox.closebutton.tooltip): This is the tooltip for
 # the close button the developer tools toolbox.
 toolbox.closebutton.tooltip=Close Developer Tools
 
 # LOCALIZATION NOTE (toolbox.allToolsButton.tooltip): This is the tooltip for the
 # "all tools" button displayed when some tools are hidden by overflow of the toolbar.
 toolbox.allToolsButton.tooltip=Select another tool
 
deleted file mode 100644
--- a/devtools/client/themes/images/dock-bottom.svg
+++ /dev/null
@@ -1,6 +0,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/. -->
-<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="context-fill #0b0b0b">
-  <path d="M10.004 3H.996C.999 3 1 3 1 3.002v9.996c0-.001.003.002-.004.002h9.008c-.003 0-.004 0-.004-.002V3.002c0 .001-.003-.002.004-.002zm0-1c.55 0 .996.456.996 1.002v9.996A.998.998 0 0 1 10.004 14H.996C.446 14 0 13.544 0 12.998V3.002A.998.998 0 0 1 .996 2h9.008zm-.41 8H.996v1h9.01v-1h-.41z"/>
-</svg>
deleted file mode 100644
--- a/devtools/client/themes/images/dock-side.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="context-fill #0b0b0b">
-  <path d="M1 2.996v9.008c0-.003 0-.004.002-.004h9.996c-.001 0 .002-.003.002.004V2.996c0 .003 0 .004-.002.004H1.002C1.003 3 1 3.003 1 2.996zm-1 0C0 2.446.456 2 1.002 2h9.996A.998.998 0 0 1 12 2.996v9.008c0 .55-.456.996-1.002.996H1.002A.998.998 0 0 1 0 12.004V2.996zm8 .413V12h1V3H8v.41z"/>
-</svg>
deleted file mode 100644
--- a/devtools/client/themes/images/dock-undock.svg
+++ /dev/null
@@ -1,8 +0,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/. -->
-<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="context-fill #0b0b0b">
-  <path d="M13.003 1.941H6.997c.008 0 .003.004.003.008v6.102c0 .004.004.008-.003.008h6.006c-.008 0-.003-.004-.003-.008V1.949c0-.004-.004-.008.003-.008zm0-.941c.55 0 .997.43.997.95v6.1c0 .525-.453.95-.997.95H6.997C6.447 9 6 8.57 6 8.05v-6.1c0-.525.453-.95.997-.95h6.006z"/>
-  <path d="M9 9.91v-.278h1v1.183c0 .516-.453.935-.997.935H2.997c-.55 0-.997-.43-.997-.95V4.7c0-.525.444-.95 1.006-.95h2.288v.941H3.006C3 4.691 3 4.691 3 4.7v6.102c0 .004.004.008-.003.008h6.006c-.004 0-.003-.001-.003.006v-.248-.657-.278h1v1.183c0 .516-.453.935-.997.935H2.997c-.55 0-.997-.43-.997-.95V4.7c0-.525.444-.95 1.006-.95h2.288v.941H3.006C3 4.691 3 4.691 3 4.7v6.102c0 .004.004.008-.003.008h6.006c-.004 0-.003-.001-.003.006v-.248-.657z"/>
-  <path d="M12.52 5H6.976v1h6.046V5zM6.5 7H2.975v1H7V7z"/>
-</svg>
new file mode 100644
--- /dev/null
+++ b/devtools/client/themes/images/more.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="M2 6a2 2 0 1 0 2 2 2 2 0 0 0-2-2zm6 0a2 2 0 1 0 2 2 2 2 0 0 0-2-2zm6 0a2 2 0 1 0 2 2 2 2 0 0 0-2-2z"></path>
+</svg>
--- a/devtools/client/themes/toolbox.css
+++ b/devtools/client/themes/toolbox.css
@@ -1,18 +1,16 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* 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/. */
 
 :root {
   --close-button-image: url(chrome://devtools/skin/images/close.svg);
-  --dock-bottom-image: url(chrome://devtools/skin/images/dock-bottom.svg);
-  --dock-side-image: url(chrome://devtools/skin/images/dock-side.svg);
-  --dock-undock-image: url(chrome://devtools/skin/images/dock-undock.svg);
+  --more-button-image: url(chrome://devtools/skin/images/more.svg);
 
   --command-paintflashing-image: url(images/command-paintflashing.svg);
   --command-screenshot-image: url(images/command-screenshot.svg);
   --command-responsive-image: url(images/command-responsivemode.svg);
   --command-scratchpad-image: url(images/tool-scratchpad.svg);
   --command-pick-image: url(images/command-pick.svg);
   --command-pick-accessibility-image: url(images/command-pick-accessibility.svg);
   --command-frames-image: url(images/command-frames.svg);
@@ -57,18 +55,17 @@
   overflow: hidden;
 }
 
 /* Set flex attribute to Toolbox buttons and Picker container so,
    they don't overlap with the tab bar */
 #toolbox-buttons-start,
 #toolbox-buttons-end,
 #toolbox-option-container,
-#toolbox-controls,
-#toolbox-dock-buttons {
+#toolbox-controls {
   display: flex;
   align-items: stretch;
 }
 
 /* Toolbox tabs */
 
 .devtools-tab {
   position: relative;
@@ -176,33 +173,24 @@
 
 /* Toolbox controls */
 
 
 #toolbox-close::before {
   background-image: var(--close-button-image);
 }
 
-#toolbox-dock-bottom::before {
-  background-image: var(--dock-bottom-image);
-}
-
-#toolbox-dock-side::before {
-  background-image: var(--dock-side-image);
-}
-
-#toolbox-dock-window::before {
-  background-image: var(--dock-undock-image);
+#toolbox-meatball-menu-button::before {
+  background-image: var(--more-button-image);
 }
 
 /* Command buttons */
 
 .command-button,
-#toolbox-controls > button,
-#toolbox-dock-buttons > button {
+#toolbox-controls > button {
   /* !important is needed to override .devtools-button rules in common.css */
   padding: 0 !important;
   margin: 0 !important;
   border: none !important;
   border-radius: 0 !important;
   position: relative;
   min-width: 24px;
 }
--- a/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_nodes_highlight.js
+++ b/devtools/client/webconsole/new-console-output/test/mochitest/browser_webconsole_nodes_highlight.js
@@ -38,14 +38,14 @@ add_task(async function() {
   let onNodeHighlight = toolbox.once("node-highlight");
   EventUtils.synthesizeMouseAtCenter(node, {type: "mousemove"}, view);
 
   let nodeFront = await onNodeHighlight;
   is(nodeFront.displayName, "h1", "The correct node was highlighted");
 
   info("Unhighlight the node by moving away from the node");
   let onNodeUnhighlight = toolbox.once("node-unhighlight");
-  let btn = toolbox.doc.querySelector(".toolbox-dock-button");
+  let btn = toolbox.doc.getElementById("toolbox-meatball-menu-button");
   EventUtils.synthesizeMouseAtCenter(btn, {type: "mousemove"}, view);
 
   await onNodeUnhighlight;
   ok(true, "node-unhighlight event was fired when moving away from the node");
 });
--- a/devtools/client/webconsole/test/head.js
+++ b/devtools/client/webconsole/test/head.js
@@ -1682,17 +1682,18 @@ function checkDomElementHighlightingForI
            "Expected attribute's name is present");
         is(attrs[i].value, testData.attrs[i].value,
            "Expected attribute's value is present");
       }
     }
 
     info("Unhighlight the node by moving away from the markup view");
     let onNodeUnhighlight = toolbox.once("node-unhighlight");
-    let btn = inspector.toolbox.doc.querySelector(".toolbox-dock-button");
+    let btn =
+      inspector.toolbox.doc.getElementById("toolbox-meatball-menu-button");
     EventUtils.synthesizeMouseAtCenter(btn, {type: "mousemove"},
       inspector.toolbox.win);
     yield onNodeUnhighlight;
 
     info("Switching back to the console");
     yield toolbox.selectTool("webconsole");
   }