diff --git a/src/components/LayerUI.scss b/src/components/LayerUI.scss
index c40ca6e0..a9a80931 100644
--- a/src/components/LayerUI.scss
+++ b/src/components/LayerUI.scss
@@ -142,16 +142,24 @@
transform: translate(-999px, 0);
}
- &.App-menu_bottom--transition-left {
+ :root[dir="ltr"] &.App-menu_bottom--transition-left {
transform: translate(-92px, 0);
}
+ :root[dir="rtl"] &.App-menu_bottom--transition-left {
+ transform: translate(92px, 0);
+ }
}
.disable-zen-mode {
height: 30px;
position: absolute;
bottom: 10px;
- right: 15px;
+ [dir="ltr"] & {
+ right: 15px;
+ }
+ [dir="rtl"] & {
+ left: 15px;
+ }
font-size: 10px;
padding: 10px;
font-weight: 500;
diff --git a/src/components/RoomDialog.scss b/src/components/RoomDialog.scss
index 9e54152d..5142ece2 100644
--- a/src/components/RoomDialog.scss
+++ b/src/components/RoomDialog.scss
@@ -12,8 +12,13 @@
.RoomDialog-modalButton-collaborators {
min-width: 1em;
position: absolute;
+ :root[dir="ltr"] & {
+ right: -5px;
+ }
+ :root[dir="rtl"] & {
+ left: -5px;
+ }
bottom: -5px;
- right: -5px;
padding: 3px;
border-radius: 50%;
background-color: $oc-green-6;
@@ -31,7 +36,7 @@
color: var(--text-color-primary);
min-width: 0;
flex: 1 1 auto;
- margin-left: 1em;
+ margin-inline-start: 1em;
display: inline-block;
cursor: pointer;
border: none;
@@ -61,7 +66,7 @@
appearance: none;
min-width: 0;
flex: 1 1 auto;
- margin-left: 1em;
+ margin-inline-start: 1em;
height: 2.5rem;
font-size: 1em;
line-height: 1.5;
diff --git a/src/components/ShortcutsDialog.tsx b/src/components/ShortcutsDialog.tsx
index d85adee1..c9b2e1ca 100644
--- a/src/components/ShortcutsDialog.tsx
+++ b/src/components/ShortcutsDialog.tsx
@@ -37,7 +37,6 @@ const Shortcut = (props: {
shortcuts: string[];
isOr: boolean;
}) => {
- const isRTL = document.documentElement.getAttribute("dir") === "rtl";
return (
diff --git a/src/components/icons.tsx b/src/components/icons.tsx
index 0ae2929f..e6d23198 100644
--- a/src/components/icons.tsx
+++ b/src/components/icons.tsx
@@ -3,6 +3,9 @@
// Icons are under the license https://fontawesome.com/license
//
+// Note: when adding new icons, review https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/RTL_Guidelines
+// to determine whether or not the icons should be mirrored in right-to-left languages.
+
import React from "react";
import oc from "open-color";
@@ -89,7 +92,6 @@ export const zoomOut = createIcon(
export const done = createIcon(
"M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z",
- { mirror: true },
);
export const menu = createIcon(
@@ -135,7 +137,7 @@ export const BringForwardIcon = React.memo(
strokeWidth="2"
/>
>,
- { width: 24 },
+ { width: 24, mirror: true },
),
);
@@ -156,7 +158,7 @@ export const SendBackwardIcon = React.memo(
strokeWidth="2"
/>
>,
- { width: 24 },
+ { width: 24, mirror: true },
),
);
@@ -177,7 +179,7 @@ export const BringToFrontIcon = React.memo(
strokeWidth="2"
/>
>,
- { width: 24 },
+ { width: 24, mirror: true },
),
);
@@ -200,12 +202,15 @@ export const SendToBackIcon = React.memo(
strokeWidth="2"
/>
>,
- { width: 24 },
+ { width: 24, mirror: true },
),
);
//
// Align action icons created from scratch to match those of z-index actions
+// Note: vertical align icons are flipped so the larger item is always the
+// first one the user sees. Horizontal align icons should not be flipped since
+// that would make them lie about their function.
//
export const AlignTopIcon = React.memo(
({ appearance }: { appearance: "light" | "dark" }) =>
@@ -225,7 +230,7 @@ export const AlignTopIcon = React.memo(
strokeWidth="2"
/>
>,
- { width: 24 },
+ { width: 24, mirror: true },
),
);
@@ -247,7 +252,7 @@ export const AlignBottomIcon = React.memo(
strokeWidth="2"
/>
>,
- { width: 24 },
+ { width: 24, mirror: true },
),
);
@@ -366,7 +371,7 @@ export const CenterVerticallyIcon = React.memo(
strokeLinecap="round"
/>
>,
- { width: 24 },
+ { width: 24, mirror: true },
),
);
@@ -398,6 +403,7 @@ export const users = createIcon(
{ width: 640, height: 512, mirror: true },
);
+// not mirrored because it's inspired by a playback control, which is always RTL
export const start = createIcon(
"M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm115.7 272l-176 101c-15.8 8.8-35.7-2.5-35.7-21V152c0-18.4 19.8-29.8 35.7-21l176 107c16.4 9.2 16.4 32.9 0 42z",
);
@@ -480,7 +486,7 @@ export const GroupIcon = React.memo(
strokeWidth="6"
/>
>,
- { width: 182, height: 182 },
+ { width: 182, height: 182, mirror: true },
),
);
@@ -555,7 +561,7 @@ export const UngroupIcon = React.memo(
strokeWidth="6"
/>
>,
- { width: 182, height: 182 },
+ { width: 182, height: 182, mirror: true },
),
);
@@ -672,7 +678,7 @@ export const SloppinessArchitectIcon = React.memo(
strokeWidth={2}
fill="none"
/>,
- { width: 40, height: 20 },
+ { width: 40, height: 20, mirror: true },
),
);
@@ -685,7 +691,7 @@ export const SloppinessArtistIcon = React.memo(
strokeWidth={2}
fill="none"
/>,
- { width: 40, height: 20 },
+ { width: 40, height: 20, mirror: true },
),
);
@@ -706,7 +712,7 @@ export const SloppinessCartoonistIcon = React.memo(
fill="none"
/>
>,
- { width: 40, height: 20 },
+ { width: 40, height: 20, mirror: true },
),
);
@@ -719,7 +725,7 @@ export const EdgeSharpIcon = React.memo(
strokeWidth={2}
fill="none"
/>,
- { width: 40, height: 20 },
+ { width: 40, height: 20, mirror: true },
),
);
@@ -732,6 +738,6 @@ export const EdgeRoundIcon = React.memo(
strokeWidth={2}
fill="none"
/>,
- { width: 40, height: 20 },
+ { width: 40, height: 20, mirror: true },
),
);
diff --git a/src/css/styles.scss b/src/css/styles.scss
index 7d483882..0b929053 100644
--- a/src/css/styles.scss
+++ b/src/css/styles.scss
@@ -104,7 +104,8 @@
}
.ToolIcon {
- margin: 0 8px 0 0;
+ margin: 0;
+ margin-inline-end: 8px;
&:focus {
outline: transparent;
@@ -392,7 +393,8 @@
}
.zIndexButton {
- margin: 0 8px 0 0;
+ margin: 0;
+ margin-inline-end: 8px;
padding: 5px;
display: inline-flex;
align-items: center;