Bug 1453010 - Part 1: Lock highlighted element by clicking on the inspect icon in AnimationTarget component. r=gl
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Fri, 27 Apr 2018 15:19:40 +0900
changeset 472313 bc816979fee8908ee4fb26cc0c1504dd9a318b10
parent 472312 be9164913cc69fbf6dcdbbab6c582a54faadc8b5
child 472314 407a33054ca6982ecf4aef9be233854db3a16f56
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgl
bugs1453010
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 1453010 - Part 1: Lock highlighted element by clicking on the inspect icon in AnimationTarget component. r=gl MozReview-Commit-ID: 1FzOpsVLiwX
devtools/client/inspector/animation/actions/animations.js
devtools/client/inspector/animation/actions/index.js
devtools/client/inspector/animation/animation.js
devtools/client/inspector/animation/components/AnimationItem.js
devtools/client/inspector/animation/components/AnimationList.js
devtools/client/inspector/animation/components/AnimationListContainer.js
devtools/client/inspector/animation/components/AnimationTarget.js
devtools/client/inspector/animation/components/App.js
devtools/client/inspector/animation/reducers/animations.js
devtools/client/inspector/shared/highlighters-overlay.js
devtools/client/themes/animation.css
--- a/devtools/client/inspector/animation/actions/animations.js
+++ b/devtools/client/inspector/animation/actions/animations.js
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {
   UPDATE_ANIMATIONS,
   UPDATE_DETAIL_VISIBILITY,
   UPDATE_ELEMENT_PICKER_ENABLED,
+  UPDATE_HIGHLIGHTED_NODE,
   UPDATE_SELECTED_ANIMATION,
   UPDATE_SIDEBAR_SIZE
 } = require("./index");
 
 module.exports = {
   /**
    * Update the list of animation in the animation inspector.
    */
@@ -39,16 +40,26 @@ module.exports = {
   updateElementPickerEnabled(elementPickerEnabled) {
     return {
       type: UPDATE_ELEMENT_PICKER_ENABLED,
       elementPickerEnabled,
     };
   },
 
   /**
+   * Update the highlighted node.
+   */
+  updateHighlightedNode(nodeFront) {
+    return {
+      type: UPDATE_HIGHLIGHTED_NODE,
+      highlightedNode: nodeFront ? nodeFront.actorID : null,
+    };
+  },
+
+  /**
    * Update selected animation.
    */
   updateSelectedAnimation(selectedAnimation) {
     return {
       type: UPDATE_SELECTED_ANIMATION,
       selectedAnimation,
     };
   },
--- a/devtools/client/inspector/animation/actions/index.js
+++ b/devtools/client/inspector/animation/actions/index.js
@@ -12,15 +12,18 @@ createEnum([
   "UPDATE_ANIMATIONS",
 
   // Update visibility of detail pane.
   "UPDATE_DETAIL_VISIBILITY",
 
   // Update state of the picker enabled.
   "UPDATE_ELEMENT_PICKER_ENABLED",
 
+  // Update highlighted node.
+  "UPDATE_HIGHLIGHTED_NODE",
+
   // Update selected animation.
   "UPDATE_SELECTED_ANIMATION",
 
   // Update sidebar size.
   "UPDATE_SIDEBAR_SIZE",
 
 ], module.exports);
--- a/devtools/client/inspector/animation/animation.js
+++ b/devtools/client/inspector/animation/animation.js
@@ -12,16 +12,17 @@ const EventEmitter = require("devtools/s
 
 const App = createFactory(require("./components/App"));
 const CurrentTimeTimer = require("./current-time-timer");
 
 const {
   updateAnimations,
   updateDetailVisibility,
   updateElementPickerEnabled,
+  updateHighlightedNode,
   updateSelectedAnimation,
   updateSidebarSize
 } = require("./actions/animations");
 const {
   isAllAnimationEqual,
   hasAnimationIterationCountInfinite,
   hasRunningAnimation,
 } = require("./utils/utils");
@@ -40,16 +41,17 @@ class AnimationInspector {
     this.removeAnimationsCurrentTimeListener =
       this.removeAnimationsCurrentTimeListener.bind(this);
     this.rewindAnimationsCurrentTime = this.rewindAnimationsCurrentTime.bind(this);
     this.selectAnimation = this.selectAnimation.bind(this);
     this.setAnimationsCurrentTime = this.setAnimationsCurrentTime.bind(this);
     this.setAnimationsPlaybackRate = this.setAnimationsPlaybackRate.bind(this);
     this.setAnimationsPlayState = this.setAnimationsPlayState.bind(this);
     this.setDetailVisibility = this.setDetailVisibility.bind(this);
+    this.setHighlightedNode = this.setHighlightedNode.bind(this);
     this.simulateAnimation = this.simulateAnimation.bind(this);
     this.simulateAnimationForKeyframesProgressBar =
       this.simulateAnimationForKeyframesProgressBar.bind(this);
     this.toggleElementPicker = this.toggleElementPicker.bind(this);
     this.update = this.update.bind(this);
     this.onAnimationStateChanged = this.onAnimationStateChanged.bind(this);
     this.onAnimationsCurrentTimeUpdated = this.onAnimationsCurrentTimeUpdated.bind(this);
     this.onAnimationsMutation = this.onAnimationsMutation.bind(this);
@@ -85,16 +87,17 @@ class AnimationInspector {
       isAnimationsRunning,
       removeAnimationsCurrentTimeListener,
       rewindAnimationsCurrentTime,
       selectAnimation,
       setAnimationsCurrentTime,
       setAnimationsPlaybackRate,
       setAnimationsPlayState,
       setDetailVisibility,
+      setHighlightedNode,
       simulateAnimation,
       simulateAnimationForKeyframesProgressBar,
       toggleElementPicker,
     } = this;
 
     const target = this.inspector.target;
     this.animationsFront = new AnimationsFront(target.client, target.form);
 
@@ -120,16 +123,17 @@ class AnimationInspector {
           onShowBoxModelHighlighterForNode,
           removeAnimationsCurrentTimeListener,
           rewindAnimationsCurrentTime,
           selectAnimation,
           setAnimationsCurrentTime,
           setAnimationsPlaybackRate,
           setAnimationsPlayState,
           setDetailVisibility,
+          setHighlightedNode,
           setSelectedNode,
           simulateAnimation,
           simulateAnimationForKeyframesProgressBar,
           toggleElementPicker,
         }
       )
     );
     this.provider = provider;
@@ -437,16 +441,32 @@ class AnimationInspector {
     }
   }
 
   setDetailVisibility(isVisible) {
     this.inspector.store.dispatch(updateDetailVisibility(isVisible));
   }
 
   /**
+   * Highlight the given node with the box model highlighter.
+   * If no node is provided, hide the box model highlighter.
+   *
+   * @param {NodeFront} nodeFront
+   */
+  async setHighlightedNode(nodeFront) {
+    await this.inspector.highlighters.hideBoxModelHighlighter();
+
+    if (nodeFront) {
+      await this.inspector.highlighters.showBoxModelHighlighter(nodeFront);
+    }
+
+    this.inspector.store.dispatch(updateHighlightedNode(nodeFront));
+  }
+
+  /**
    * Returns simulatable animation by given parameters.
    * The returned animation is implementing Animation interface of Web Animation API.
    * https://drafts.csswg.org/web-animations/#the-animation-interface
    *
    * @param {Array} keyframes
    *        e.g. [{ opacity: 0 }, { opacity: 1 }]
    * @param {Object} effectTiming
    *        e.g. { duration: 1000, fill: "both" }
--- a/devtools/client/inspector/animation/components/AnimationItem.js
+++ b/devtools/client/inspector/animation/components/AnimationItem.js
@@ -18,16 +18,17 @@ class AnimationItem extends Component {
       animation: PropTypes.object.isRequired,
       emitEventForTest: PropTypes.func.isRequired,
       getAnimatedPropertyMap: PropTypes.func.isRequired,
       getNodeFromActor: PropTypes.func.isRequired,
       onHideBoxModelHighlighter: PropTypes.func.isRequired,
       onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
       selectAnimation: PropTypes.func.isRequired,
       selectedAnimation: PropTypes.object.isRequired,
+      setHighlightedNode: PropTypes.func.isRequired,
       setSelectedNode: PropTypes.func.isRequired,
       simulateAnimation: PropTypes.func.isRequired,
       timeScale: PropTypes.object.isRequired,
     };
   }
 
   constructor(props) {
     super(props);
@@ -56,16 +57,17 @@ class AnimationItem extends Component {
     const {
       animation,
       emitEventForTest,
       getAnimatedPropertyMap,
       getNodeFromActor,
       onHideBoxModelHighlighter,
       onShowBoxModelHighlighterForNode,
       selectAnimation,
+      setHighlightedNode,
       setSelectedNode,
       simulateAnimation,
       timeScale,
     } = this.props;
     const {
       isSelected,
     } = this.state;
 
@@ -76,16 +78,17 @@ class AnimationItem extends Component {
       },
       AnimationTarget(
         {
           animation,
           emitEventForTest,
           getNodeFromActor,
           onHideBoxModelHighlighter,
           onShowBoxModelHighlighterForNode,
+          setHighlightedNode,
           setSelectedNode,
         }
       ),
       SummaryGraph(
         {
           animation,
           emitEventForTest,
           getAnimatedPropertyMap,
--- a/devtools/client/inspector/animation/components/AnimationList.js
+++ b/devtools/client/inspector/animation/components/AnimationList.js
@@ -15,31 +15,33 @@ class AnimationList extends PureComponen
     return {
       animations: PropTypes.arrayOf(PropTypes.object).isRequired,
       emitEventForTest: PropTypes.func.isRequired,
       getAnimatedPropertyMap: PropTypes.func.isRequired,
       getNodeFromActor: PropTypes.func.isRequired,
       onHideBoxModelHighlighter: PropTypes.func.isRequired,
       onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
       selectAnimation: PropTypes.func.isRequired,
+      setHighlightedNode: PropTypes.func.isRequired,
       setSelectedNode: PropTypes.func.isRequired,
       simulateAnimation: PropTypes.func.isRequired,
       timeScale: PropTypes.object.isRequired,
     };
   }
 
   render() {
     const {
       animations,
       emitEventForTest,
       getAnimatedPropertyMap,
       getNodeFromActor,
       onHideBoxModelHighlighter,
       onShowBoxModelHighlighterForNode,
       selectAnimation,
+      setHighlightedNode,
       setSelectedNode,
       simulateAnimation,
       timeScale,
     } = this.props;
 
     return dom.ul(
       {
         className: "animation-list"
@@ -49,16 +51,17 @@ class AnimationList extends PureComponen
           {
             animation,
             emitEventForTest,
             getAnimatedPropertyMap,
             getNodeFromActor,
             onHideBoxModelHighlighter,
             onShowBoxModelHighlighterForNode,
             selectAnimation,
+            setHighlightedNode,
             setSelectedNode,
             simulateAnimation,
             timeScale,
           }
         )
       )
     );
   }
--- a/devtools/client/inspector/animation/components/AnimationListContainer.js
+++ b/devtools/client/inspector/animation/components/AnimationListContainer.js
@@ -20,16 +20,17 @@ class AnimationListContainer extends Pur
       emitEventForTest: PropTypes.func.isRequired,
       getAnimatedPropertyMap: PropTypes.func.isRequired,
       getNodeFromActor: PropTypes.func.isRequired,
       onHideBoxModelHighlighter: PropTypes.func.isRequired,
       onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
       removeAnimationsCurrentTimeListener: PropTypes.func.isRequired,
       selectAnimation: PropTypes.func.isRequired,
       setAnimationsCurrentTime: PropTypes.func.isRequired,
+      setHighlightedNode: PropTypes.func.isRequired,
       setSelectedNode: PropTypes.func.isRequired,
       simulateAnimation: PropTypes.func.isRequired,
       timeScale: PropTypes.object.isRequired,
     };
   }
 
   render() {
     const {
@@ -38,16 +39,17 @@ class AnimationListContainer extends Pur
       emitEventForTest,
       getAnimatedPropertyMap,
       getNodeFromActor,
       onHideBoxModelHighlighter,
       onShowBoxModelHighlighterForNode,
       removeAnimationsCurrentTimeListener,
       selectAnimation,
       setAnimationsCurrentTime,
+      setHighlightedNode,
       setSelectedNode,
       simulateAnimation,
       timeScale,
     } = this.props;
 
     return dom.div(
       {
         className: "animation-list-container"
@@ -64,16 +66,17 @@ class AnimationListContainer extends Pur
         {
           animations,
           emitEventForTest,
           getAnimatedPropertyMap,
           getNodeFromActor,
           onHideBoxModelHighlighter,
           onShowBoxModelHighlighterForNode,
           selectAnimation,
+          setHighlightedNode,
           setSelectedNode,
           simulateAnimation,
           timeScale,
         }
       )
     );
   }
 }
--- a/devtools/client/inspector/animation/components/AnimationTarget.js
+++ b/devtools/client/inspector/animation/components/AnimationTarget.js
@@ -1,32 +1,34 @@
 /* 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/. */
 
 "use strict";
 
 const { Component } = require("devtools/client/shared/vendor/react");
+const { connect } = require("devtools/client/shared/vendor/react-redux");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 const dom = require("devtools/client/shared/vendor/react-dom-factories");
 const { translateNodeFrontToGrip } = require("devtools/client/inspector/shared/utils");
 
 const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
 const { Rep } = REPS;
 const ElementNode = REPS.ElementNode;
 
 class AnimationTarget extends Component {
   static get propTypes() {
     return {
       animation: PropTypes.object.isRequired,
       emitEventForTest: PropTypes.func.isRequired,
       getNodeFromActor: PropTypes.func.isRequired,
+      highlightedNode: PropTypes.string.isRequired,
       onHideBoxModelHighlighter: PropTypes.func.isRequired,
       onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
-      setSelectedNode: PropTypes.func.isRequired,
+      setHighlightedNode: PropTypes.func.isRequired,
     };
   }
 
   constructor(props) {
     super(props);
 
     this.state = {
       nodeFront: null,
@@ -39,17 +41,18 @@ class AnimationTarget extends Component 
 
   componentWillReceiveProps(nextProps) {
     if (this.props.animation.actorID !== nextProps.animation.actorID) {
       this.updateNodeFront(nextProps.animation);
     }
   }
 
   shouldComponentUpdate(nextProps, nextState) {
-    return this.state.nodeFront !== nextState.nodeFront;
+    return this.state.nodeFront !== nextState.nodeFront ||
+           this.props.highlightedNode !== nextState.highlightedNode;
   }
 
   async updateNodeFront(animation) {
     const { emitEventForTest, getNodeFromActor } = this.props;
 
     // Try and get it from the playerFront directly.
     let nodeFront = animation.animationTargetNodeFront;
 
@@ -69,41 +72,53 @@ class AnimationTarget extends Component 
     this.setState({ nodeFront });
     emitEventForTest("animation-target-rendered");
   }
 
   render() {
     const {
       onHideBoxModelHighlighter,
       onShowBoxModelHighlighterForNode,
-      setSelectedNode,
+      highlightedNode,
+      setHighlightedNode,
     } = this.props;
 
     const { nodeFront } = this.state;
 
     if (!nodeFront) {
       return dom.div(
         {
           className: "animation-target"
         }
       );
     }
 
+    const isHighlighted = nodeFront.actorID === highlightedNode;
+
     return dom.div(
       {
-        className: "animation-target"
+        className: "animation-target" +
+                   (isHighlighted ? " highlighting" : ""),
       },
       Rep(
         {
           defaultRep: ElementNode,
           mode: MODE.TINY,
           object: translateNodeFrontToGrip(nodeFront),
           onDOMNodeMouseOut: () => onHideBoxModelHighlighter(),
           onDOMNodeMouseOver: () => onShowBoxModelHighlighterForNode(nodeFront),
-          onInspectIconClick: () => setSelectedNode(nodeFront,
-            { reason: "animation-panel" }),
+          onInspectIconClick: (_, e) => {
+            e.stopPropagation();
+            setHighlightedNode(isHighlighted ? null : nodeFront);
+          }
         }
       )
     );
   }
 }
 
-module.exports = AnimationTarget;
+const mapStateToProps = state => {
+  return {
+    highlightedNode: state.animations.highlightedNode,
+  };
+};
+
+module.exports = connect(mapStateToProps)(AnimationTarget);
--- a/devtools/client/inspector/animation/components/App.js
+++ b/devtools/client/inspector/animation/components/App.js
@@ -30,21 +30,23 @@ class App extends Component {
       onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
       removeAnimationsCurrentTimeListener: PropTypes.func.isRequired,
       rewindAnimationsCurrentTime: PropTypes.func.isRequired,
       selectAnimation: PropTypes.func.isRequired,
       setAnimationsCurrentTime: PropTypes.func.isRequired,
       setAnimationsPlaybackRate: PropTypes.func.isRequired,
       setAnimationsPlayState: PropTypes.func.isRequired,
       setDetailVisibility: PropTypes.func.isRequired,
+      setHighlightedNode: PropTypes.func.isRequired,
       setSelectedNode: PropTypes.func.isRequired,
       simulateAnimation: PropTypes.func.isRequired,
       simulateAnimationForKeyframesProgressBar: PropTypes.func.isRequired,
       timeScale: PropTypes.object.isRequired,
       toggleElementPicker: PropTypes.func.isRequired,
+      toggleLockingHighlight: PropTypes.func.isRequired,
     };
   }
 
   shouldComponentUpdate(nextProps, nextState) {
     return this.props.animations.length !== 0 || nextProps.animations.length !== 0;
   }
 
   render() {
@@ -61,16 +63,17 @@ class App extends Component {
       onShowBoxModelHighlighterForNode,
       removeAnimationsCurrentTimeListener,
       rewindAnimationsCurrentTime,
       selectAnimation,
       setAnimationsCurrentTime,
       setAnimationsPlaybackRate,
       setAnimationsPlayState,
       setDetailVisibility,
+      setHighlightedNode,
       setSelectedNode,
       simulateAnimation,
       simulateAnimationForKeyframesProgressBar,
       timeScale,
       toggleElementPicker,
     } = this.props;
 
     return dom.div(
@@ -117,16 +120,17 @@ class App extends Component {
               emitEventForTest,
               getAnimatedPropertyMap,
               getNodeFromActor,
               onHideBoxModelHighlighter,
               onShowBoxModelHighlighterForNode,
               removeAnimationsCurrentTimeListener,
               selectAnimation,
               setAnimationsCurrentTime,
+              setHighlightedNode,
               setSelectedNode,
               simulateAnimation,
               timeScale,
             }
           ),
           vert: false,
         })
       ]
--- a/devtools/client/inspector/animation/reducers/animations.js
+++ b/devtools/client/inspector/animation/reducers/animations.js
@@ -3,26 +3,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {
   UPDATE_ANIMATIONS,
   UPDATE_DETAIL_VISIBILITY,
   UPDATE_ELEMENT_PICKER_ENABLED,
+  UPDATE_HIGHLIGHTED_NODE,
   UPDATE_SELECTED_ANIMATION,
   UPDATE_SIDEBAR_SIZE,
 } = require("../actions/index");
 
 const TimeScale = require("../utils/timescale");
 
 const INITIAL_STATE = {
   animations: [],
   detailVisibility: false,
   elementPickerEnabled: false,
+  highlightedNode: null,
   selectedAnimation: null,
   sidebarSize: {
     height: 0,
     width: 0,
   },
   timeScale: null,
 };
 
@@ -52,16 +54,22 @@ const reducers = {
   },
 
   [UPDATE_ELEMENT_PICKER_ENABLED](state, { elementPickerEnabled }) {
     return Object.assign({}, state, {
       elementPickerEnabled
     });
   },
 
+  [UPDATE_HIGHLIGHTED_NODE](state, { highlightedNode }) {
+    return Object.assign({}, state, {
+      highlightedNode
+    });
+  },
+
   [UPDATE_SELECTED_ANIMATION](state, { selectedAnimation }) {
     const detailVisibility = !!selectedAnimation;
 
     return Object.assign({}, state, {
       detailVisibility,
       selectedAnimation
     });
   },
--- a/devtools/client/inspector/shared/highlighters-overlay.js
+++ b/devtools/client/inspector/shared/highlighters-overlay.js
@@ -384,16 +384,50 @@ class HighlightersOverlay {
       this.state.grid.options);
     this.gridHighlighterShown = null;
 
     // Erase grid highlighter state.
     this.state.grid = {};
   }
 
   /**
+   * Show the box model highlighter for the given node.
+   *
+   * @param  {NodeFront} node
+   *         The NodeFront of the element to highlight.
+   * @param  {Object} options
+   *         Object used for passing options to the box model highlighter.
+   */
+  async showBoxModelHighlighter(node, options) {
+    const highlighter = await this._getHighlighter("BoxModelHighlighter");
+    if (!highlighter) {
+      return;
+    }
+
+    const isShown = await highlighter.show(node, options);
+    if (!isShown) {
+      return;
+    }
+
+    this.boxModelHighlighterShown = node;
+  }
+
+  /**
+   * Hide the box model highlighter.
+   */
+  async hideBoxModelHighlighter() {
+    if (!this.boxModelHighlighterShown || !this.highlighters.BoxModelHighlighter) {
+      return;
+    }
+
+    await this.highlighters.BoxModelHighlighter.hide();
+    this.boxModelHighlighterShown = null;
+  }
+
+  /**
    * Toggle the geometry editor highlighter for the given element.
    *
    * @param {NodeFront} node
    *        The NodeFront of the element to highlight.
    */
   async toggleGeometryHighlighter(node) {
     if (node == this.geometryEditorHighlighterShown) {
       await this.hideGeometryEditor();
@@ -866,16 +900,17 @@ class HighlightersOverlay {
     this._hideHighlighterIfDeadNode(this.shapesHighlighterShown,
       this.hideShapesHighlighter);
   }
 
   /**
    * Clear saved highlighter shown properties on will-navigate.
    */
   onWillNavigate() {
+    this.boxModelHighlighterShown = null;
     this.flexboxHighlighterShown = null;
     this.geometryEditorHighlighterShown = null;
     this.gridHighlighterShown = null;
     this.hoveredHighlighterShown = null;
     this.selectorHighlighterShown = null;
     this.shapesHighlighterShown = null;
     this.destroyEditors();
   }
@@ -921,16 +956,17 @@ class HighlightersOverlay {
 
     this._lastHovered = null;
 
     this.inspector = null;
     this.highlighterUtils = null;
     this.supportsHighlighters = null;
     this.state = null;
 
+    this.boxModelHighlighterShown = null;
     this.flexboxHighlighterShown = null;
     this.geometryEditorHighlighterShown = null;
     this.gridHighlighterShown = null;
     this.hoveredHighlighterShown = null;
     this.selectorHighlighterShown = null;
     this.shapesHighlighterShown = null;
 
     this.destroyed = true;
--- a/devtools/client/themes/animation.css
+++ b/devtools/client/themes/animation.css
@@ -231,26 +231,34 @@ select.playback-rate-selector.devtools-b
   height: 100%;
   padding-left: 4px;
   width: var(--sidebar-width);
 }
 
 /* Reps component */
 .animation-target .objectBox {
   display: flex;
-  width: 100%;
+  max-width: 100%;
 }
 
 .animation-target .objectBox .attrName {
   min-width: 0;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
 }
 
+.animation-target .objectBox:hover .open-inspector {
+  background-color: var(--comment-node-color);
+}
+
+.animation-target.highlighting .objectBox .open-inspector {
+  background-color: var(--theme-highlight-blue);
+}
+
 /* Summary Graph */
 .animation-summary-graph {
   cursor: pointer;
   height: 100%;
   padding-top: 5px;
   position: relative;
   width: calc(100% - var(--sidebar-width) - var(--graph-right-offset));
 }