소스 검색

RTL updates (#2416)

* Update a bunch of icons to be mirrored in RTL

* Fix RTL layout issues in in zen mode and collaboration

* Small change to the shortcuts dialog to make isRTL unnecessary

* Tweaks to alignment in RTL
Jed Fox 4 년 전
부모
커밋
8d479ab238
6개의 변경된 파일63개의 추가작업 그리고 28개의 파일을 삭제
  1. 19 3
      src/components/Actions.tsx
  2. 10 2
      src/components/LayerUI.scss
  3. 8 3
      src/components/RoomDialog.scss
  4. 1 3
      src/components/ShortcutsDialog.tsx
  5. 21 15
      src/components/icons.tsx
  6. 4 2
      src/css/styles.scss

+ 19 - 3
src/components/Actions.tsx

@@ -35,6 +35,8 @@ export const SelectedShapeActions = ({
   const isEditing = Boolean(appState.editingElement);
   const isMobile = useIsMobile();
 
+  const isRTL = document.documentElement.getAttribute("dir") === "rtl";
+
   return (
     <div className="panelColumn">
       {renderAction("changeStrokeColor")}
@@ -88,9 +90,23 @@ export const SelectedShapeActions = ({
         <fieldset>
           <legend>{t("labels.align")}</legend>
           <div className="buttonList">
-            {renderAction("alignLeft")}
-            {renderAction("alignHorizontallyCentered")}
-            {renderAction("alignRight")}
+            {
+              // swap this order for RTL so the button positions always match their action
+              // (i.e. the leftmost button aligns left)
+            }
+            {isRTL ? (
+              <>
+                {renderAction("alignRight")}
+                {renderAction("alignHorizontallyCentered")}
+                {renderAction("alignLeft")}
+              </>
+            ) : (
+              <>
+                {renderAction("alignLeft")}
+                {renderAction("alignHorizontallyCentered")}
+                {renderAction("alignRight")}
+              </>
+            )}
             {targetElements.length > 2 &&
               renderAction("distributeHorizontally")}
             <div className="iconRow">

+ 10 - 2
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;

+ 8 - 3
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;

+ 1 - 3
src/components/ShortcutsDialog.tsx

@@ -37,7 +37,6 @@ const Shortcut = (props: {
   shortcuts: string[];
   isOr: boolean;
 }) => {
-  const isRTL = document.documentElement.getAttribute("dir") === "rtl";
   return (
     <div className="ShorcutsDialog-shortcut">
       <div
@@ -60,8 +59,7 @@ const Shortcut = (props: {
             display: "flex",
             flex: "0 0 auto",
             justifyContent: "flex-end",
-            marginLeft: isRTL ? "0em" : "auto",
-            marginRight: isRTL ? "auto" : "0em",
+            marginInlineStart: "auto",
             minWidth: "30%",
           }}
         >

+ 21 - 15
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 },
     ),
 );

+ 4 - 2
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;