Bug 1210796 - Part 14: Add close button. r=pbro
MozReview-Commit-ID: 59NdVAtgeLw
--- a/devtools/client/animationinspector/components/animation-timeline.js
+++ b/devtools/client/animationinspector/components/animation-timeline.js
@@ -54,16 +54,17 @@ function AnimationsTimeline(inspector, s
this.onAnimationStateChanged = this.onAnimationStateChanged.bind(this);
this.onScrubberMouseDown = this.onScrubberMouseDown.bind(this);
this.onScrubberMouseUp = this.onScrubberMouseUp.bind(this);
this.onScrubberMouseOut = this.onScrubberMouseOut.bind(this);
this.onScrubberMouseMove = this.onScrubberMouseMove.bind(this);
this.onAnimationSelected = this.onAnimationSelected.bind(this);
this.onWindowResize = this.onWindowResize.bind(this);
this.onTimelineDataChanged = this.onTimelineDataChanged.bind(this);
+ this.onDetailCloseButtonClick = this.onDetailCloseButtonClick.bind(this);
EventEmitter.decorate(this);
}
exports.AnimationsTimeline = AnimationsTimeline;
AnimationsTimeline.prototype = {
init: function (containerEl) {
@@ -87,30 +88,31 @@ AnimationsTimeline.prototype = {
const React = browserRequire("devtools/client/shared/vendor/react");
const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
const SplitBox = React.createFactory(
browserRequire("devtools/client/shared/components/splitter/split-box"));
const splitter = SplitBox({
className: "animation-root",
- initialSize: "0 0",
- maxSize: "calc(100% - (var(--timeline-animation-height) * 2))",
splitterSize: 1,
+ initialHeight: "50%",
endPanelControl: true,
startPanel: React.DOM.div({
className: "animation-timeline"
}),
endPanel: React.DOM.div({
className: "animation-detail"
}),
vert: false
});
ReactDOM.render(splitter, this.rootWrapperEl);
+
+ this.animationRootEl = this.rootWrapperEl.querySelector(".animation-root");
},
setupAnimationTimeline: function () {
const animationTimelineEl = this.rootWrapperEl.querySelector(".animation-timeline");
let scrubberContainer = createNode({
parent: animationTimelineEl,
attributes: {"class": "scrubber-wrapper"}
@@ -167,24 +169,20 @@ AnimationsTimeline.prototype = {
nodeType: "ul",
attributes: {
"class": "animations"
}
});
},
setupAnimationDetail: function () {
- this.animationDetailEl = this.rootWrapperEl.querySelector(".animation-detail");
-
- this.animationDetailEl.dataset.defaultDisplayStyle =
- this.win.getComputedStyle(this.animationDetailEl).display;
- this.animationDetailEl.style.display = "none";
+ const animationDetailEl = this.rootWrapperEl.querySelector(".animation-detail");
const animationDetailHeaderEl = createNode({
- parent: this.animationDetailEl,
+ parent: animationDetailEl,
attributes: {
"class": "animation-detail-header"
}
});
const headerTitleEl = createNode({
parent: animationDetailHeaderEl,
attributes: {
@@ -196,18 +194,29 @@ AnimationsTimeline.prototype = {
parent: headerTitleEl,
textContent: L10N.getStr("detail.headerTitle")
});
this.animationAnimationNameEl = createNode({
parent: headerTitleEl
});
+ this.animationDetailCloseButton = createNode({
+ parent: headerTitleEl,
+ nodeType: "button",
+ attributes: {
+ "class": "devtools-button",
+ title: L10N.getStr("detail.header.closeLabel"),
+ }
+ });
+ this.animationDetailCloseButton.addEventListener("click",
+ this.onDetailCloseButtonClick);
+
const animationDetailBodyEl = createNode({
- parent: this.animationDetailEl,
+ parent: animationDetailEl,
attributes: {
"class": "animation-detail-body"
}
});
this.animatedPropertiesEl = createNode({
parent: animationDetailBodyEl,
attributes: {
@@ -225,31 +234,35 @@ AnimationsTimeline.prototype = {
this.details.destroy();
this.win.removeEventListener("resize",
this.onWindowResize);
this.timeHeaderEl.removeEventListener("mousedown",
this.onScrubberMouseDown);
this.scrubberHandleEl.removeEventListener("mousedown",
this.onScrubberMouseDown);
+ this.animationDetailCloseButton.removeEventListener("click",
+ this.onDetailCloseButtonClick);
this.rootWrapperEl.remove();
this.animations = [];
this.rootWrapperEl = null;
this.timeHeaderEl = null;
this.animationsEl = null;
this.animatedPropertiesEl = null;
this.scrubberEl = null;
this.scrubberHandleEl = null;
this.win = null;
this.inspector = null;
this.serverTraits = null;
this.animationDetailEl = null;
this.animationAnimationNameEl = null;
this.animatedPropertiesEl = null;
+ this.animationDetailCloseButton = null;
+ this.animationRootEl = null;
},
/**
* Destroy sub-components that have been created and stored on this instance.
* @param {String} name An array of components will be expected in this[name]
* @param {Array} handlers An option list of event handlers information that
* should be used to remove these handlers.
*/
@@ -318,18 +331,17 @@ AnimationsTimeline.prototype = {
if (!this.animatedPropertiesEl.classList.contains(animation.state.type)) {
this.animatedPropertiesEl.className =
`animated-properties ${ animation.state.type }`;
}
// Select and render.
const selectedAnimationEl = animationEls[index];
selectedAnimationEl.classList.add("selected");
- this.animationDetailEl.style.display =
- this.animationDetailEl.dataset.defaultDisplayStyle;
+ this.animationRootEl.classList.add("animation-detail-visible");
yield this.details.render(animation);
this.onTimelineDataChanged(null, { time: this.currentTime || 0 });
this.animationAnimationNameEl.textContent = getFormattedAnimationTitle(animation);
this.emit("animation-selected", animation);
}),
/**
* When move the scrubber to the corresponding position
@@ -599,10 +611,15 @@ AnimationsTimeline.prototype = {
}
},
onTimelineDataChanged: function (e, { time }) {
this.currentTime = time;
const indicateTime =
TimeScale.minStartTime === Infinity ? 0 : this.currentTime + TimeScale.minStartTime;
this.details.indicateProgress(indicateTime);
+ },
+
+ onDetailCloseButtonClick: function (e) {
+ this.animationRootEl.classList.remove("animation-detail-visible");
+ this.emit("animation-detail-closed");
}
};
--- a/devtools/client/animationinspector/test/browser_animation_detail_displayed.js
+++ b/devtools/client/animationinspector/test/browser_animation_detail_displayed.js
@@ -5,37 +5,56 @@
"use strict";
// Tests the behavior of animation-detail container.
// We test following cases.
// 1. Existance of animation-detail element.
// 2. Hidden at first if multiple animations were displayed.
// 3. Display after click on an animation.
// 4. Display from first time if displayed animation is only one.
+// 5. Close the animation-detail element by clicking on close button.
requestLongerTimeout(5);
add_task(function* () {
yield addTab(URL_ROOT + "doc_multiple_property_types.html");
const { panel, inspector } = yield openAnimationInspector();
const timelineComponent = panel.animationsTimelineComponent;
const animationDetailEl =
timelineComponent.rootWrapperEl.querySelector(".animation-detail");
+ const splitboxControlledEl =
+ timelineComponent.rootWrapperEl.querySelector(".controlled");
// 1. Existance of animation-detail element.
ok(animationDetailEl, "The animation-detail element should exist");
// 2. Hidden at first if multiple animations were displayed.
const win = animationDetailEl.ownerDocument.defaultView;
- is(win.getComputedStyle(animationDetailEl).display, "none",
+ is(win.getComputedStyle(splitboxControlledEl).display, "none",
"The animation-detail element should be hidden at first "
+ "if multiple animations were displayed");
// 3. Display after click on an animation.
yield clickOnAnimation(panel, 0);
- isnot(win.getComputedStyle(animationDetailEl).display, "none",
+ isnot(win.getComputedStyle(splitboxControlledEl).display, "none",
"The animation-detail element should be displayed after clicked on an animation");
// 4. Display from first time if displayed animation is only one.
yield selectNodeAndWaitForAnimations("#target1", inspector);
ok(animationDetailEl.querySelector(".property"),
"The property in animation-detail element should be displayed");
+
+ // 5. Close the animation-detail element by clicking on close button.
+ const previousHeight = animationDetailEl.offsetHeight;
+ const button = animationDetailEl.querySelector(".animation-detail-header button");
+ const onclosed = timelineComponent.once("animation-detail-closed");
+ EventUtils.sendMouseEvent({type: "click"}, button, win);
+ yield onclosed;
+ is(win.getComputedStyle(splitboxControlledEl).display, "none",
+ "animation-detail element should not display");
+
+ // Select another animation.
+ yield selectNodeAndWaitForAnimations("#target2", inspector);
+ isnot(win.getComputedStyle(splitboxControlledEl).display, "none",
+ "animation-detail element should display");
+ is(animationDetailEl.offsetHeight, previousHeight,
+ "The height of animation-detail should keep the height");
});
--- a/devtools/client/locales/en-US/animationinspector.properties
+++ b/devtools/client/locales/en-US/animationinspector.properties
@@ -177,8 +177,12 @@ timeline.unknown.nameLabel=%S
# This string is displayed on header label in .animated-properties-header.
# %S represents the value in percentage with two decimal points, localized.
# there are two "%" after %S to escape and display "%"
detail.propertiesHeader.percentage=%S%%
# LOCALIZATION NOTE (detail.headerTitle):
# This string is displayed on header label in .animation-detail-header.
detail.headerTitle=Animated properties for
+
+# LOCALIZATION NOTE (detail.header.closeLabel):
+# This string is displayed in a tooltip of close button for animated properties
+detail.header.closeLabel=Close animated properties panel
--- a/devtools/client/themes/animationinspector.css
+++ b/devtools/client/themes/animationinspector.css
@@ -5,16 +5,17 @@
/* Animation-inspector specific theme variables */
.theme-dark {
--even-animation-timeline-background-color: rgba(255,255,255,0.03);
--command-pick-image: url(chrome://devtools/skin/images/command-pick.svg);
--pause-image: url(chrome://devtools/skin/images/pause.svg);
--rewind-image: url(chrome://devtools/skin/images/rewind.svg);
--play-image: url(chrome://devtools/skin/images/play.svg);
+ --close-button-image: url(chrome://devtools/skin/images/close.svg);
/* The color for animation type 'opacity' */
--opacity-border-color: var(--theme-highlight-pink);
--opacity-background-color: #df80ff80;
/* The color for animation type 'transform' */
--transform-border-color: var(--theme-graphs-yellow);
--transform-background-color: #d99b2880;
/* The color for other animation type */
--other-border-color: var(--theme-graphs-bluegrey);
@@ -24,24 +25,26 @@
}
.theme-light {
--even-animation-timeline-background-color: rgba(128,128,128,0.03);
--command-pick-image: url(chrome://devtools/skin/images/command-pick.svg);
--pause-image: url(chrome://devtools/skin/images/pause.svg);
--rewind-image: url(chrome://devtools/skin/images/rewind.svg);
--play-image: url(chrome://devtools/skin/images/play.svg);
+ --close-button-image: url(chrome://devtools/skin/images/close.svg);
}
.theme-firebug {
--even-animation-timeline-background-color: rgba(128,128,128,0.03);
--command-pick-image: url(chrome://devtools/skin/images/firebug/command-pick.svg);
--pause-image: url(chrome://devtools/skin/images/firebug/pause.svg);
--rewind-image: url(chrome://devtools/skin/images/firebug/rewind.svg);
--play-image: url(chrome://devtools/skin/images/firebug/play.svg);
+ --close-button-image: url(chrome://devtools/skin/images/firebug/close.svg);
}
.theme-light, .theme-firebug {
/* The color for animation type 'opacity' */
--opacity-border-color: var(--theme-highlight-pink);
--opacity-background-color: #b82ee580;
/* The color for animation type 'transform' */
--transform-border-color: var(--theme-graphs-orange);
@@ -683,41 +686,55 @@ body {
.animation-detail {
position: relative;
width: 100%;
background-color: var(--theme-body-background);
z-index: 5;
}
.animation-detail .animation-detail-header {
+ position: relative;
height: var(--toolbar-height);
width: 100%;
}
.animation-detail .animation-detail-header > div {
position: fixed;
display: flex;
flex-wrap: nowrap;
width: 100%;
height: var(--toolbar-height);
line-height: var(--toolbar-height);
background-color: var(--theme-body-background);
+ padding: 0;
z-index: 5;
}
.animation-detail .animation-detail-header > div > div {
white-space: nowrap;
}
.animation-detail .animation-detail-header > div > div:first-child {
margin-left: 15px;
}
.animation-detail .animation-detail-header > div > div:nth-child(2) {
+ flex: 1;
margin-left: .5em;
+ min-width: 0;
+}
+
+.animation-detail .animation-detail-header .devtools-button {
+ /* We need to tweak the padding
+ since the devtools-button is optimized for toolbox-tab height */
+ padding-top: 0;
+}
+
+.animation-detail .animation-detail-header .devtools-button::before {
+ background-image: var(--close-button-image);
}
.animation-detail .animation-detail-body {
position: relative;
background-color: var(--theme-body-background);
}
.animation-detail .animation-detail-body .animated-properties {
@@ -780,8 +797,12 @@ body {
position: absolute;
top: 0;
right: -6px;
width: 1px;
border-top: 5px solid var(--progress-indicator-color);
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
+
+.animation-root:not(.animation-detail-visible) .controlled {
+ display: none;
+}