/* 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/. */ /* Animation-inspector specific theme variables */ .theme-dark, .theme-light { --even-animation-timeline-background-color: rgba(160,144,144,0.03); } :root { /* How high should toolbars be */ --toolbar-height: 20px; /* How wide should the sidebar be */ --timeline-sidebar-width: 150px; /* How high should animations displayed in the timeline be */ --timeline-animation-height: 20px; } html { height: 100%; } body { margin: 0; padding: 0; display : flex; flex-direction: column; height: 100%; overflow: hidden; color: var(--theme-content-color3); } /* The top toolbar, containing the toggle-all button. And the timeline toolbar, containing playback control buttons, shown only when there are animations displayed in the timeline */ #global-toolbar, #timeline-toolbar { border-bottom: 1px solid var(--theme-splitter-color); display: flex; flex-direction: row; align-items: center; justify-content: flex-end; height: var(--toolbar-height); } #timeline-toolbar { display: none; } [timeline] #global-toolbar { display: none; } [timeline] #timeline-toolbar { display: flex; } #global-toolbar .label { padding: 1px 4px; } /* The main animations container */ #players { height: calc(100% - var(--toolbar-height)); overflow: auto; } [empty] #players { display: none; } /* The error message, shown when an invalid/unanimated element is selected */ #error-message { padding-top: 10%; text-align: center; flex: 1; overflow: auto; /* The error message is hidden by default */ display: none; } [empty] #error-message { display: block; } /* Element picker, toggle-all buttons, timeline pause button, ... */ #global-toolbar .devtools-button, #timeline-toolbar .devtools-button { border-width: 0 0 0 1px; min-height: var(--toolbar-height); } .devtools-button { position: relative; } .devtools-button::before { content: ""; display: block; width: 16px; height: 16px; position: absolute; left: 50%; top: 50%; margin: -8px 0 0 -8px; } #element-picker::before { background-image: url("chrome://devtools/skin/command-pick.png"); } .pause-button::before { background-image: url("debugger-pause.png"); } #element-picker[checked]::before { background-position: -48px 0; filter: none; /* Icon is blue when checked, don't invert for light theme */ } .pause-button.paused::before { background-image: url("debugger-play.png"); } @media (min-resolution: 1.1dppx) { #element-picker::before { background-image: url("chrome://devtools/skin/command-pick@2x.png"); background-size: 64px; } .pause-button::before { background-image: url("debugger-pause@2x.png"); } .pause-button.paused::before { background-image: url("debugger-play@2x.png"); } } /* Animation timeline component */ .animation-timeline { height: 100%; overflow: hidden; position: relative; /* The timeline gets its background-image from a canvas element created in /browser/devtools/animationinspector/utils.js drawGraphElementBackground thanks to document.mozSetImageElement("time-graduations", canvas) This is done so that the background can be built dynamically from script */ background-image: -moz-element(#time-graduations); background-repeat: repeat-y; /* The animations are drawn 150px from the left edge so that animated nodes can be displayed in a sidebar */ background-position: var(--timeline-sidebar-width) 0; display: flex; flex-direction: column; } .animation-timeline .scrubber { position: absolute; height: 100%; width: var(--timeline-sidebar-width); border-right: 1px solid #FF0000; box-sizing: border-box; z-index: 1; pointer-events: none; } .animation-timeline .scrubber::before { content: ""; position: absolute; top: 0; width: 1px; right: -6px; border-top: 5px solid #FF0000; border-left: 5px solid transparent; border-right: 5px solid transparent; } .animation-timeline .time-header { margin-left: var(--timeline-sidebar-width); height: var(--toolbar-height); overflow: hidden; position: relative; /* This is the same color as the time graduations in browser/devtools/animationinspector/utils.js */ border-bottom: 1px solid var(--theme-splitter-color); cursor: col-resize; -moz-user-select: none; } .animation-timeline .time-header .time-tick { position: absolute; top: 3px; } .animation-timeline .animations { width: 100%; overflow-y: auto; overflow-x: hidden; margin: 0; padding: 0; list-style-type: none; } /* Animation block widgets */ .animation-timeline .animation { margin: 4px 0; height: var(--timeline-animation-height); position: relative; } .animation-timeline .animation:nth-child(2n) { background-color: var(--even-animation-timeline-background-color); } .animation-timeline .animation .target { width: var(--timeline-sidebar-width); overflow: hidden; height: 100%; } .animation-timeline .animation-target { background-color: transparent; } .animation-timeline .animation .time-block { position: absolute; top: 0; left: var(--timeline-sidebar-width); right: 0; height: 100%; } /* Animation iterations */ .animation-timeline .animation .iterations { position: relative; height: 100%; box-sizing: border-box; --timelime-border-color: var(--theme-body-color); --timeline-background-color: var(--theme-splitter-color); /* Iterations of the animation are displayed with a repeating linear-gradient which size is dynamically changed from JS. The gradient only draws 1px borders between each iteration. These borders must have the same color as the border of this element */ background-image: linear-gradient(to right, var(--timelime-border-color) 0, var(--timelime-border-color) 1px, transparent 1px, transparent 2px); background-repeat: repeat-x; background-position: -1px 0; border: 1px solid var(--timelime-border-color); /* The background color is set independently */ background-color: var(--timeline-background-color); } .animation-timeline .animation .cssanimation { --timelime-border-color: var(--theme-highlight-lightorange); --timeline-background-color: var(--theme-contrast-background); } .animation-timeline .animation .csstransition { --timelime-border-color: var(--theme-highlight-bluegrey); --timeline-background-color: var(--theme-highlight-blue); } .animation-timeline .animation .iterations.infinite { border-right-width: 0; } .animation-timeline .animation .iterations.infinite::before, .animation-timeline .animation .iterations.infinite::after { content: ""; position: absolute; top: 0; right: 0; width: 0; height: 0; border-right: 4px solid var(--theme-body-background); border-top: 4px solid transparent; border-bottom: 4px solid transparent; } .animation-timeline .animation .iterations.infinite::after { bottom: 0; top: unset; } .animation-timeline .animation .name { color: var(--theme-selection-color); height: 100%; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 150%; padding: 0 2px; } .animation-timeline .animation .delay { position: absolute; top: 0; /* Make sure the delay covers up the animation border */ transform: translate(-1px, -1px); box-sizing: border-box; height: calc(100% + 2px); border: 1px solid var(--timelime-border-color); border-width: 1px 0 1px 1px; background-image: repeating-linear-gradient(45deg, transparent, transparent 1px, var(--theme-selection-color) 1px, var(--theme-selection-color) 4px); background-color: var(--timelime-border-color); } .animation-timeline .animation .delay.negative { /* Negative delays are displayed on top of the animation, so they need a right border. Whereas normal delays are displayed just before the animation, so there's already the animation's left border that serves as a separation. */ border-width: 1px; } .animation-timeline .animation .delay::before { position: absolute; content: ""; left: 0; width: 2px; height: 8px; top: 50%; margin-top: -4px; background: var(--timelime-border-color); } /* Animation target node gutter, contains a preview of the dom node */ .animation-target { background-color: var(--theme-toolbar-background); padding: 1px 4px; box-sizing: border-box; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .animation-target .attribute-name { padding-left: 4px; } .animation-target .node-selector { background: url("chrome://devtools/skin/images/vview-open-inspector.png") no-repeat 0 0; padding-left: 16px; margin-right: 5px; cursor: pointer; } .animation-target .node-selector:hover { background-position: -32px 0; } .animation-target .node-selector:active { background-position: -16px 0; } /* Animation title gutter, contains the name, duration, iteration */ .animation-title { background-color: var(--theme-toolbar-background); border-bottom: 1px solid var(--theme-splitter-color); padding: 1px 4px; word-wrap: break-word; overflow: auto; } .animation-title .meta-data { float: right; } .animation-title strong { margin: 0 .5em; } .animation-title .meta-data .compositor-icon { display: none; background-image: url("animation-fast-track.svg"); background-repeat: no-repeat; padding-left: 12px; /* Make sure the icon is positioned above the timeline range input so that its tooltip appears on hover */ z-index: 1; position: relative; } /* Timeline wiget */ .timeline { height: var(--timeline-animation-height); width: 100%; display: flex; flex-direction: row; border-bottom: 1px solid var(--theme-splitter-color); } .timeline .playback-controls { display: flex; flex-direction: row; } /* Playback control buttons */ .timeline .playback-controls button { flex-grow: 1; border-width: 0 1px 0 0; } .timeline .toggle::before { background-image: url(debugger-pause.png); } .paused .timeline .toggle::before, .finished .timeline .toggle::before { background-image: url(debugger-play.png); } .timeline .ff::before { background-image: url(fast-forward.png); } .timeline .rw::before { background-image: url(rewind.png); } @media (min-resolution: 1.1dppx) { .timeline .toggle::before { background-image: url(debugger-pause@2x.png); } .paused .timeline .toggle::before, .finished .timeline .toggle::before { background-image: url(debugger-play@2x.png); } .timeline .ff::before { background-image: url(fast-forward@2x.png); } .timeline .rw::before { background-image: url(rewind@2x.png); } } .timeline .rate { -moz-appearance: none; text-align: center; color: var(--theme-body-color); border-right: 1px solid var(--theme-splitter-color); } /* Slider (input type range) container */ .timeline .sliders-container { flex-grow: 1; height: 100%; position: relative; border-width: 1px 0; } .timeline .sliders-container .current-time { position: absolute; padding: 0; margin: 0; left: 0; width: 100%; height: 100%; } .timeline .sliders-container .current-time::-moz-range-thumb { height: 100%; width: 4px; border-radius: 0; border: none; background: var(--theme-highlight-blue); } .timeline .sliders-container .current-time::-moz-range-track { width: 100%; height: 50px; background: transparent; } /* Current time label */ .timeline .time-display { display: flex; align-items: center; justify-content: center; width: 50px; border-left: 1px solid var(--theme-splitter-color); background: var(--theme-toolbar-background); }