--- a/devtools/client/inspector/animation/animation.js
+++ b/devtools/client/inspector/animation/animation.js
@@ -94,31 +94,33 @@ class AnimationInspector {
setHighlightedNode,
setSelectedNode,
simulateAnimation,
simulateAnimationForKeyframesProgressBar,
toggleElementPicker,
} = this;
const target = this.inspector.target;
+ const direction = this.win.document.dir;
this.animationsFront = new AnimationsFront(target.client, target.form);
this.animationsFront.setWalkerActor(this.inspector.walker);
this.animationsCurrentTimeListeners = [];
this.isCurrentTimeSet = false;
const provider = createElement(Provider,
{
id: "newanimationinspector",
key: "newanimationinspector",
store: this.inspector.store
},
App(
{
addAnimationsCurrentTimeListener,
+ direction,
emitEventForTest,
getAnimatedPropertyMap,
getAnimationsCurrentTime,
getComputedStyle,
getNodeFromActor,
isAnimationsRunning,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
--- a/devtools/client/inspector/animation/components/AnimationListContainer.js
+++ b/devtools/client/inspector/animation/components/AnimationListContainer.js
@@ -20,16 +20,17 @@ const { findOptimalTimeInterval } = requ
// The minimum spacing between 2 time graduation headers in the timeline (px).
const TIME_GRADUATION_MIN_SPACING = 40;
class AnimationListContainer extends PureComponent {
static get propTypes() {
return {
addAnimationsCurrentTimeListener: PropTypes.func.isRequired,
animations: PropTypes.arrayOf(PropTypes.object).isRequired,
+ direction: PropTypes.string.isRequired,
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,
@@ -77,16 +78,17 @@ class AnimationListContainer extends Pur
this.setState({ ticks });
}
render() {
const {
addAnimationsCurrentTimeListener,
animations,
+ direction,
emitEventForTest,
getAnimatedPropertyMap,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
removeAnimationsCurrentTimeListener,
selectAnimation,
setAnimationsCurrentTime,
@@ -101,16 +103,17 @@ class AnimationListContainer extends Pur
{
className: "animation-list-container"
},
ProgressInspectionPanel(
{
indicator: CurrentTimeScrubber(
{
addAnimationsCurrentTimeListener,
+ direction,
removeAnimationsCurrentTimeListener,
setAnimationsCurrentTime,
timeScale,
}
),
list: AnimationList(
{
animations,
--- a/devtools/client/inspector/animation/components/App.js
+++ b/devtools/client/inspector/animation/components/App.js
@@ -16,16 +16,17 @@ const NoAnimationPanel = createFactory(r
const SplitBox = createFactory(require("devtools/client/shared/components/splitter/SplitBox"));
class App extends Component {
static get propTypes() {
return {
addAnimationsCurrentTimeListener: PropTypes.func.isRequired,
animations: PropTypes.arrayOf(PropTypes.object).isRequired,
detailVisibility: PropTypes.bool.isRequired,
+ direction: PropTypes.string.isRequired,
emitEventForTest: PropTypes.func.isRequired,
getAnimatedPropertyMap: PropTypes.func.isRequired,
getAnimationsCurrentTime: PropTypes.func.isRequired,
getComputedStyle: PropTypes.func.isRequired,
getNodeFromActor: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
removeAnimationsCurrentTimeListener: PropTypes.func.isRequired,
@@ -49,16 +50,17 @@ class App extends Component {
return this.props.animations.length !== 0 || nextProps.animations.length !== 0;
}
render() {
const {
addAnimationsCurrentTimeListener,
animations,
detailVisibility,
+ direction,
emitEventForTest,
getAnimatedPropertyMap,
getAnimationsCurrentTime,
getComputedStyle,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
removeAnimationsCurrentTimeListener,
@@ -112,16 +114,17 @@ class App extends Component {
),
endPanelControl: true,
initialHeight: "50%",
splitterSize: 1,
startPanel: AnimationListContainer(
{
addAnimationsCurrentTimeListener,
animations,
+ direction,
emitEventForTest,
getAnimatedPropertyMap,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
removeAnimationsCurrentTimeListener,
selectAnimation,
setAnimationsCurrentTime,
--- a/devtools/client/inspector/animation/components/CurrentTimeScrubber.js
+++ b/devtools/client/inspector/animation/components/CurrentTimeScrubber.js
@@ -10,16 +10,17 @@ const PropTypes = require("devtools/clie
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const IndicationBar = createFactory(require("./IndicationBar"));
class CurrentTimeScrubber extends PureComponent {
static get propTypes() {
return {
addAnimationsCurrentTimeListener: PropTypes.func.isRequired,
+ direction: PropTypes.string.isRequired,
removeAnimationsCurrentTimeListener: PropTypes.func.isRequired,
setAnimationsCurrentTime: PropTypes.func.isRequired,
timeScale: PropTypes.object.isRequired,
};
}
constructor(props) {
super(props);
@@ -103,24 +104,32 @@ class CurrentTimeScrubber extends PureCo
this.listenerTarget.removeEventListener("mouseup", this.onMouseUp);
this.listenerTarget.classList.remove("active-scrubber");
this.listenerTarget = null;
this.controllerArea = null;
}
updateAnimationsCurrentTime(pageX, needRefresh) {
const {
+ direction,
setAnimationsCurrentTime,
timeScale,
} = this.props;
- const time = pageX - this.controllerArea.x < 0 ?
- 0 :
- (pageX - this.controllerArea.x) /
- this.controllerArea.width * timeScale.getDuration();
+ let progressRate = (pageX - this.controllerArea.x) / this.controllerArea.width;
+
+ if (progressRate < 0.0) {
+ progressRate = 0.0;
+ } else if (progressRate > 1.0) {
+ progressRate = 1.0;
+ }
+
+ const time = direction === "ltr"
+ ? progressRate * timeScale.getDuration()
+ : (1 - progressRate) * timeScale.getDuration();
setAnimationsCurrentTime(time, needRefresh);
}
render() {
const { position } = this.state;
return dom.div(
--- a/devtools/client/inspector/animation/components/IndicationBar.js
+++ b/devtools/client/inspector/animation/components/IndicationBar.js
@@ -52,17 +52,17 @@ class IndicationBar extends PureComponen
render() {
const { className } = this.props;
const { offset } = this.state;
return dom.div(
{
className: `indication-bar ${ className }`,
style: {
- transform: `translateX(${ offset }px)`,
+ marginInlineStart: offset + "px",
},
}
);
}
}
const mapStateToProps = state => {
return {
--- a/devtools/client/inspector/animation/components/TickLabels.js
+++ b/devtools/client/inspector/animation/components/TickLabels.js
@@ -24,17 +24,17 @@ class TickLabels extends PureComponent {
return dom.div(
{
className: "tick-labels"
},
ticks.map(tick =>
dom.div(
{
className: "tick-label",
- style: { left: `${ tick.position }%` },
+ style: { marginInlineStart: `${ tick.position }%` },
},
tick.label
)
)
);
}
}
--- a/devtools/client/inspector/animation/components/TickLines.js
+++ b/devtools/client/inspector/animation/components/TickLines.js
@@ -24,17 +24,17 @@ class TickLines extends PureComponent {
return dom.div(
{
className: "tick-lines"
},
ticks.map(tick =>
dom.div(
{
className: "tick-line",
- style: { left: `${ tick.position }%` }
+ style: { marginInlineStart: `${ tick.position }%` }
}
)
)
);
}
}
module.exports = TickLines;
--- a/devtools/client/inspector/animation/components/graph/AnimationName.js
+++ b/devtools/client/inspector/animation/components/graph/AnimationName.js
@@ -22,17 +22,17 @@ class AnimationName extends PureComponen
return dom.svg(
{
className: "animation-name",
},
dom.text(
{
y: "50%",
- x: "100%"
+ x: "100%",
},
animation.state.name
)
);
}
}
module.exports = AnimationName;
--- a/devtools/client/inspector/animation/components/graph/DelaySign.js
+++ b/devtools/client/inspector/animation/components/graph/DelaySign.js
@@ -40,16 +40,16 @@ class DelaySign extends PureComponent {
return dom.div(
{
className: "animation-delay-sign" +
(delay < 0 ? " negative" : "") +
(fill === "both" || fill === "backwards" ? " fill" : ""),
style: {
width: `${ width }%`,
- left: `${ offset }%`,
+ marginInlineStart: `${ offset }%`,
},
}
);
}
}
module.exports = DelaySign;
--- a/devtools/client/inspector/animation/components/graph/EndDelaySign.js
+++ b/devtools/client/inspector/animation/components/graph/EndDelaySign.js
@@ -44,16 +44,16 @@ class EndDelaySign extends PureComponent
return dom.div(
{
className: "animation-end-delay-sign" +
(endDelay < 0 ? " negative" : "") +
(fill === "both" || fill === "forwards" ? " fill" : ""),
style: {
width: `${ width }%`,
- left: `${ offset }%`,
+ marginInlineStart: `${ offset }%`,
},
}
);
}
}
module.exports = EndDelaySign;
--- a/devtools/client/inspector/animation/components/graph/SummaryGraph.js
+++ b/devtools/client/inspector/animation/components/graph/SummaryGraph.js
@@ -175,17 +175,17 @@ class SummaryGraph extends PureComponent
timeScale,
}
)
:
null,
animation.state.name ?
AnimationName(
{
- animation
+ animation,
}
)
:
null
);
}
}
--- a/devtools/client/inspector/animation/components/keyframes-graph/KeyframeMarkerItem.js
+++ b/devtools/client/inspector/animation/components/keyframes-graph/KeyframeMarkerItem.js
@@ -18,16 +18,16 @@ class KeyframeMarkerItem extends PureCom
render() {
const { keyframe } = this.props;
return dom.li(
{
className: "keyframe-marker-item",
title: keyframe.value,
style: {
- left: `${ keyframe.offset * 100 }%`,
+ marginInlineStart: `${ keyframe.offset * 100 }%`,
},
}
);
}
}
module.exports = KeyframeMarkerItem;
--- a/devtools/client/inspector/animation/test/browser_animation_animation-timeline-tick.js
+++ b/devtools/client/inspector/animation/test/browser_animation_animation-timeline-tick.js
@@ -57,17 +57,17 @@ function assertTickLabels(timeScale, lis
const expectedTickItem = Math.ceil(animationDuration / interval);
const timelineTickItemEls = timelineTickListEl.querySelectorAll(".tick-label");
is(timelineTickItemEls.length, expectedTickItem,
"The expected number of timeline ticks were found");
info("Make sure graduations are evenly distributed and show the right times");
for (const [index, tickEl] of timelineTickItemEls.entries()) {
- const left = parseFloat(tickEl.style.left);
+ const left = parseFloat(tickEl.style.marginInlineStart);
const expectedPos = index * interval * 100 / animationDuration;
is(Math.round(left), Math.round(expectedPos),
`Graduation ${ index } is positioned correctly`);
// Note that the distancetoRelativeTime and formatTime functions are tested
// separately in xpcshell test test_timeScale.js, so we assume that they
// work here.
const formattedTime =
--- a/devtools/client/inspector/animation/test/browser_animation_keyframes-graph_keyframe-marker.js
+++ b/devtools/client/inspector/animation/test/browser_animation_keyframes-graph_keyframe-marker.js
@@ -1,136 +1,136 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test for following keyframe marker.
// * element existence
// * title
-// * and left style
+// * and marginInlineStart style
const TEST_DATA = [
{
targetClass: "multi-types",
properties: [
{
name: "background-color",
expectedValues: [
{
title: "rgb(255, 0, 0)",
- left: "0%",
+ marginInlineStart: "0%",
},
{
title: "rgb(0, 255, 0)",
- left: "100%",
+ marginInlineStart: "100%",
}
],
},
{
name: "background-repeat",
expectedValues: [
{
title: "space round",
- left: "0%",
+ marginInlineStart: "0%",
},
{
title: "round space",
- left: "100%",
+ marginInlineStart: "100%",
}
],
},
{
name: "font-size",
expectedValues: [
{
title: "10px",
- left: "0%",
+ marginInlineStart: "0%",
},
{
title: "20px",
- left: "100%",
+ marginInlineStart: "100%",
}
],
},
{
name: "margin-left",
expectedValues: [
{
title: "0px",
- left: "0%",
+ marginInlineStart: "0%",
},
{
title: "100px",
- left: "100%",
+ marginInlineStart: "100%",
}
],
},
{
name: "opacity",
expectedValues: [
{
title: "0",
- left: "0%",
+ marginInlineStart: "0%",
},
{
title: "1",
- left: "100%",
+ marginInlineStart: "100%",
}
],
},
{
name: "text-align",
expectedValues: [
{
title: "right",
- left: "0%",
+ marginInlineStart: "0%",
},
{
title: "center",
- left: "100%",
+ marginInlineStart: "100%",
}
],
},
{
name: "transform",
expectedValues: [
{
title: "translate(0px)",
- left: "0%",
+ marginInlineStart: "0%",
},
{
title: "translate(100px)",
- left: "100%",
+ marginInlineStart: "100%",
}
],
},
],
},
{
targetClass: "narrow-offsets",
properties: [
{
name: "opacity",
expectedValues: [
{
title: "0",
- left: "0%",
+ marginInlineStart: "0%",
},
{
title: "1",
- left: "10%",
+ marginInlineStart: "10%",
},
{
title: "0",
- left: "13%",
+ marginInlineStart: "13%",
},
{
title: "1",
- left: "100%",
+ marginInlineStart: "100%",
},
],
},
],
}
];
add_task(async function() {
@@ -158,15 +158,16 @@ add_task(async function() {
info(`Checking ${ hintTarget }`);
const markerEl = markerEls[i];
const expectedValue = expectedValues[i];
info(`Checking title in ${ hintTarget }`);
is(markerEl.getAttribute("title"), expectedValue.title,
`title in ${ hintTarget } should be ${ expectedValue.title }`);
- info(`Checking left style in ${ hintTarget }`);
- is(markerEl.style.left, expectedValue.left,
- `left in ${ hintTarget } should be ${ expectedValue.left }`);
+ info(`Checking marginInlineStart style in ${ hintTarget }`);
+ is(markerEl.style.marginInlineStart, expectedValue.marginInlineStart,
+ `marginInlineStart in ${ hintTarget } should be ` +
+ `${ expectedValue.marginInlineStart }`);
}
}
}
});
--- a/devtools/client/inspector/animation/test/browser_animation_pause-resume-button_end-time.js
+++ b/devtools/client/inspector/animation/test/browser_animation_pause-resume-button_end-time.js
@@ -45,11 +45,12 @@ function assertCurrentTimeLessThanDurati
animations.forEach((animation, index) => {
ok(animation.state.currentTime < animation.state.duration,
`The current time of animation[${ index }] should be less than its duration`);
});
}
function assertScrubberPosition(panel) {
const scrubberEl = panel.querySelector(".current-time-scrubber");
- const translateX = parseFloat(scrubberEl.style.transform.match(/-?\d+(\.\d+)?/)[0]);
- ok(translateX >= 0, "The translateX of scrubber position should be zero or more");
+ const marginInlineStart = parseFloat(scrubberEl.style.marginInlineStart);
+ ok(marginInlineStart >= 0,
+ "The translateX of scrubber position should be zero or more");
}
--- a/devtools/client/inspector/animation/test/browser_animation_summary-graph_delay-sign.js
+++ b/devtools/client/inspector/animation/test/browser_animation_summary-graph_delay-sign.js
@@ -1,51 +1,51 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test for following DelaySign component works.
// * element existance
-// * left position
+// * marginInlineStart position
// * width
// * additinal class
const TEST_DATA = [
{
targetClass: "delay-positive",
expectedResult: {
- left: "25%",
+ marginInlineStart: "25%",
width: "25%",
},
},
{
targetClass: "delay-negative",
expectedResult: {
additionalClass: "negative",
- left: "0%",
+ marginInlineStart: "0%",
width: "25%",
},
},
{
targetClass: "fill-backwards-with-delay-iterationstart",
expectedResult: {
additionalClass: "fill",
- left: "25%",
+ marginInlineStart: "25%",
width: "25%",
},
},
{
targetClass: "fill-both",
},
{
targetClass: "fill-both-width-delay-iterationstart",
expectedResult: {
additionalClass: "fill",
- left: "25%",
+ marginInlineStart: "25%",
width: "25%",
},
},
{
targetClass: "keyframes-easing-step",
},
];
@@ -59,18 +59,18 @@ add_task(async function() {
findAnimationItemElementsByTargetSelector(panel, `.${ targetClass }`);
info(`Checking delay sign existance for ${ targetClass }`);
const delaySignEl = animationItemEl.querySelector(".animation-delay-sign");
if (expectedResult) {
ok(delaySignEl, "The delay sign element should be in animation item element");
- is(delaySignEl.style.left, expectedResult.left,
- `Left position should be ${ expectedResult.left }`);
+ is(delaySignEl.style.marginInlineStart, expectedResult.marginInlineStart,
+ `marginInlineStart position should be ${ expectedResult.marginInlineStart }`);
is(delaySignEl.style.width, expectedResult.width,
`Width should be ${ expectedResult.width }`);
if (expectedResult.additionalClass) {
ok(delaySignEl.classList.contains(expectedResult.additionalClass),
`delay sign element should have ${ expectedResult.additionalClass } class`);
} else {
ok(!delaySignEl.classList.contains(expectedResult.additionalClass),
--- a/devtools/client/inspector/animation/test/browser_animation_summary-graph_end-delay-sign.js
+++ b/devtools/client/inspector/animation/test/browser_animation_summary-graph_end-delay-sign.js
@@ -1,40 +1,40 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test for following EndDelaySign component works.
// * element existance
-// * left position
+// * marginInlineStart position
// * width
// * additinal class
const TEST_DATA = [
{
targetClass: "enddelay-positive",
expectedResult: {
- left: "75%",
+ marginInlineStart: "75%",
width: "25%",
},
},
{
targetClass: "enddelay-negative",
expectedResult: {
additionalClass: "negative",
- left: "50%",
+ marginInlineStart: "50%",
width: "25%",
},
},
{
targetClass: "enddelay-with-fill-forwards",
expectedResult: {
additionalClass: "fill",
- left: "75%",
+ marginInlineStart: "75%",
width: "25%",
},
},
{
targetClass: "enddelay-with-iterations-infinity",
},
{
targetClass: "delay-negative",
@@ -51,18 +51,18 @@ add_task(async function() {
findAnimationItemElementsByTargetSelector(panel, `.${ targetClass }`);
info(`Checking endDelay sign existance for ${ targetClass }`);
const endDelaySignEl = animationItemEl.querySelector(".animation-end-delay-sign");
if (expectedResult) {
ok(endDelaySignEl, "The endDelay sign element should be in animation item element");
- is(endDelaySignEl.style.left, expectedResult.left,
- `Left position should be ${ expectedResult.left }`);
+ is(endDelaySignEl.style.marginInlineStart, expectedResult.marginInlineStart,
+ `marginInlineStart position should be ${ expectedResult.marginInlineStart }`);
is(endDelaySignEl.style.width, expectedResult.width,
`Width should be ${ expectedResult.width }`);
if (expectedResult.additionalClass) {
ok(endDelaySignEl.classList.contains(expectedResult.additionalClass),
`endDelay sign element should have ${ expectedResult.additionalClass } class`);
} else {
ok(!endDelaySignEl.classList.contains(expectedResult.additionalClass),
--- a/devtools/client/themes/animation.css
+++ b/devtools/client/themes/animation.css
@@ -67,17 +67,17 @@
.pause-resume-button.paused::before {
background-image: var(--resume-image);
}
select.playback-rate-selector.devtools-button {
background-image: url("chrome://devtools/skin/images/dropmarker.svg");
background-position: calc(100% - 4px) center;
background-repeat: no-repeat;
- padding-right: 1em;
+ padding-inline-end: 1em;
text-align: center;
}
select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.checked):hover {
background: none;
background-color: var(--toolbarbutton-background);
background-image: url("chrome://devtools/skin/images/dropmarker.svg");
background-position: calc(100% - 4px) center;
@@ -113,28 +113,32 @@ select.playback-rate-selector.devtools-b
pointer-events: auto;
position: absolute;
/* In order to click on edge of current-time-scrubber-controller element */
width: calc(100% + 1px);
}
.indication-bar.current-time-scrubber {
cursor: col-resize;
- margin-left: -6px;
pointer-events: auto;
width: 12px;
+ transform: translateX(-6px);
+}
+
+.indication-bar.current-time-scrubber:dir(rtl) {
+ transform: translateX(6px);
}
.indication-bar.current-time-scrubber::before {
border-top-color: var(--scrubber-color);
left: 0;
}
.indication-bar.current-time-scrubber::after {
- border-left-color: var(--scrubber-color);
+ border-inline-start-color: var(--scrubber-color);
left: 5px;
}
/* Animation Item */
.animation-item.cssanimation {
--graph-color: var(--cssanimation-color);
--graph-opacity: 0.7;
}
@@ -158,17 +162,23 @@ select.playback-rate-selector.devtools-b
}
/* Animation Target */
.animation-target {
align-items: center;
display: flex;
grid-column: 1 / 2;
height: var(--graph-height);
- padding-left: 4px;
+ padding-inline-start: 4px;
+ /* animation-target is tech term, so it should be displayed as ltr. */
+ direction: ltr;
+}
+
+.animation-item:dir(rtl).animation-target {
+ right:0;
}
/* Reps component */
.animation-target .objectBox {
display: flex;
max-width: 100%;
}
@@ -207,21 +217,30 @@ select.playback-rate-selector.devtools-b
height: 100%;
position: absolute;
right: 0;
top: 5px;
width: 15px;
-moz-context-properties: fill;
}
+.animation-summary-graph.compositor:dir(rtl)::after {
+ right: unset;
+ left: 0;
+}
+
.animation-summary-graph-path {
height: 100%;
width: 100%;
}
+.animation-summary-graph:dir(rtl) .animation-summary-graph-path {
+ transform: scaleX(-1.0);
+}
+
.animation-computed-timing-path path {
fill: var(--graph-color);
fill-opacity: var(--graph-opacity);
vector-effect: non-scaling-stroke;
transform: scale(1, -1);
}
.animation-computed-timing-path path.infinity:nth-child(n+2) {
@@ -268,30 +287,58 @@ select.playback-rate-selector.devtools-b
width: 6px;
}
.animation-delay-sign.fill,
.animation-end-delay-sign.fill {
background-color: var(--graph-color);
}
-.animation-delay-sign.negative::before {
+/* These are delay sign directions. Basically, we can't use
+ the transform due to pseudo element, So we use the left/right align. */
+
+.animation-delay-sign:dir(ltr)::before {
+ left: -3px;
+ right: unset;
+}
+
+.animation-delay-sign:dir(rtl)::before {
+ left: unset;
+ right: -3px;
+}
+
+.animation-delay-sign.negative:dir(ltr)::before {
left: unset;
right: -3px;
}
-.animation-end-delay-sign::before {
+.animation-delay-sign.negative:dir(rtl)::before {
+ left: -3px;
+ right: unset;
+}
+
+.animation-end-delay-sign:dir(ltr)::before {
+ left: unset;
right: -3px;
}
-.animation-end-delay-sign.negative::before {
+.animation-end-delay-sign:dir(rtl)::before {
left: -3px;
right: unset;
}
+.animation-end-delay-sign.negative:dir(ltr)::before {
+ left: -3px;
+ right: unset;
+}
+.animation-end-delay-sign.negative:dir(rtl)::before {
+ left: unset;
+ right: -3px;
+}
+
.animation-name {
height: 100%;
left: 0;
pointer-events: none;
position: absolute;
top: 0;
width: calc(100% - 20px);
}
@@ -302,16 +349,24 @@ select.playback-rate-selector.devtools-b
paint-order: stroke;
stroke: var(--theme-body-background);
stroke-linejoin: round;
stroke-opacity: .5;
stroke-width: 4;
text-anchor: end;
}
+.animation-summary-graph:dir(rtl) .animation-name text {
+ transform: translateX(-100%);
+}
+
+.animation-summary-graph:dir(rtl) .animation-name {
+ right:0;
+}
+
/* Animation Detail */
.animation-detail-container {
background-color: var(--theme-sidebar-background);
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
width: 100%;
@@ -360,75 +415,82 @@ select.playback-rate-selector.devtools-b
z-index: 2;
}
.indication-bar.keyframes-progress-bar::before {
border-top-color: var(--progress-bar-color);
}
.indication-bar.keyframes-progress-bar::after {
- border-left-color: var(--progress-bar-color);
+ border-inline-start-color: var(--progress-bar-color);
}
/* Animated Property Item */
.animated-property-item.unchanged {
opacity: 0.6;
}
/* Animated Property Name */
.animated-property-name {
align-items: center;
display: flex;
height: var(--graph-height);
justify-content: flex-end;
- padding-right: 10px;
+ padding-inline-end: 10px;
}
.animated-property-name.compositor span {
- padding-left: 15px;
+ padding-inline-start: 15px;
position: relative;
}
.animated-property-list-container.cssanimation .animated-property-name.compositor {
--fast-track-color: var(--cssanimation-color);
}
.animated-property-list-container.csstransition .animated-property-name.compositor {
--fast-track-color: var(--csstransition-color);
}
.animated-property-list-container.scriptanimation .animated-property-name.compositor {
--fast-track-color: var(--scriptanimation-color);
}
-.animated-property-name.compositor span::before {
+.animated-property-name.compositor span:dir(ltr)::before,
+.animated-property-name.compositor span:dir(rtl)::after {
background-image: var(--fast-track-image);
background-repeat: no-repeat;
background-size: contain;
content: "";
fill: var(--fast-track-color);
height: 100%;
position: absolute;
+ /* In order to support RTL/LTR both of environment, set the left and right to zero */
left: 0;
+ right: 0;
width: 15px;
-moz-context-properties: fill;
}
.animated-property-name.warning span {
text-decoration: underline dotted;
}
/* Keyframes Graph */
.keyframes-graph {
grid-column: 2 / 3;
height: var(--graph-height);
padding-top: 5px;
position: relative;
}
+.keyframes-graph:dir(rtl) .keyframes-graph-path {
+ transform: scaleX(-1.0);
+}
+
.keyframes-graph-path {
height: 100%;
width: 100%;
}
.keyframes-graph-path path {
fill: var(--teal-60);
fill-opacity: 0.5;
@@ -478,29 +540,34 @@ select.playback-rate-selector.devtools-b
/* Keyframe Marker List */
.keyframe-marker-list {
pointer-events: none;
position: absolute;
height: 100%;
list-style-type: none;
top: 0%;
width: 100%;
+ padding-inline-start: 0;
}
.keyframe-marker-item {
box-shadow: 0 0 0 1px var(--keyframe-marker-shadow-color);
border-radius: 100%;
pointer-events: auto;
position: absolute;
top: 50%;
height: 10px;
transform: translate(-5px, -3px);
width: 10px;
}
+.keyframe-marker-item:dir(rtl) {
+ transform: translate(5px, -3px);
+}
+
.animated-property-list-container.cssanimation .keyframe-marker-item {
background-color: var(--cssanimation-color);
}
.animated-property-list-container.csstransition .keyframe-marker-item {
background-color: var(--csstransition-color);
}
@@ -542,60 +609,64 @@ select.playback-rate-selector.devtools-b
position: relative;
}
.tick-line {
position: absolute;
}
.tick-line::before {
- border-left: var(--tick-line-style);
+ border-inline-start: var(--tick-line-style);
content: "";
height: 100vh;
position: fixed;
}
/* Tick Labels */
.tick-labels {
grid-column: 2 / 3;
height: 100%;
position: relative;
}
.tick-label {
- border-left: var(--tick-line-style);
+ border-inline-start: var(--tick-line-style);
height: 100%;
position: absolute;
}
.animated-property-list-container .tick-label:last-child {
- border-left: none;
- border-right: var(--tick-line-style);
+ border-inline-start: unset;
+ border-inline-end: var(--tick-line-style);
transform: translateX(calc(-100% + 0.5px));
}
+.animated-property-list-container .tick-label:dir(rtl):last-child {
+ transform: translateX(calc(100% - 0.6px));
+}
+
/* Indication Bar */
.indication-bar {
height: 100%;
position: absolute;
}
.indication-bar::before {
- border-left: 5px solid transparent;
- border-right: 5px solid transparent;
+ border-inline-start: 5px solid transparent;
+ border-inline-end: 5px solid transparent;
border-top: 5px solid;
content: "";
left: -5px;
position: absolute;
top: 0;
width: 0;
}
.indication-bar::after {
- border-left: 1px solid;
+ border-inline-start: 1px solid;
content: "";
height: 100%;
position: absolute;
top: 0;
width: 0;
}
/* No Animation Panel */