Просмотр исходного кода

feat: Use dialog component for clear canvas instead of window confirm (#4075)

* feat: Use dialog component for clear canvas instead of window confirm

* reduce font weight

* fix specs

* update button name and use action

* export clearCanvas from actions
vanilla_orig
Aakansha Doshi 3 лет назад
Родитель
Сommit
0f0244224d
Аккаунт пользователя с таким Email не найден

+ 7
- 20
src/actions/actionCanvas.tsx Просмотреть файл

@@ -1,14 +1,11 @@
1
-import { getDefaultAppState } from "../appState";
2 1
 import { ColorPicker } from "../components/ColorPicker";
3
-import { trash, zoomIn, zoomOut } from "../components/icons";
2
+import { zoomIn, zoomOut } from "../components/icons";
4 3
 import { ToolButton } from "../components/ToolButton";
5 4
 import { DarkModeToggle } from "../components/DarkModeToggle";
6 5
 import { THEME, ZOOM_STEP } from "../constants";
7 6
 import { getCommonBounds, getNonDeletedElements } from "../element";
8
-import { newElementWith } from "../element/mutateElement";
9 7
 import { ExcalidrawElement } from "../element/types";
10 8
 import { t } from "../i18n";
11
-import { useIsMobile } from "../components/App";
12 9
 import { CODES, KEYS } from "../keys";
13 10
 import { getNormalizedZoom, getSelectedElements } from "../scene";
14 11
 import { centerScrollOn } from "../scene/scroll";
@@ -17,6 +14,9 @@ import { AppState, NormalizedZoomValue } from "../types";
17 14
 import { getShortcutKey } from "../utils";
18 15
 import { register } from "./register";
19 16
 import { Tooltip } from "../components/Tooltip";
17
+import { newElementWith } from "../element/mutateElement";
18
+import { getDefaultAppState } from "../appState";
19
+import ClearCanvas from "../components/ClearCanvas";
20 20
 
21 21
 export const actionChangeViewBackgroundColor = register({
22 22
   name: "changeViewBackgroundColor",
@@ -47,7 +47,7 @@ export const actionChangeViewBackgroundColor = register({
47 47
 
48 48
 export const actionClearCanvas = register({
49 49
   name: "clearCanvas",
50
-  perform: (elements, appState: AppState) => {
50
+  perform: (elements, appState) => {
51 51
     return {
52 52
       elements: elements.map((element) =>
53 53
         newElementWith(element, { isDeleted: true }),
@@ -65,21 +65,8 @@ export const actionClearCanvas = register({
65 65
       commitToHistory: true,
66 66
     };
67 67
   },
68
-  PanelComponent: ({ updateData }) => (
69
-    <ToolButton
70
-      type="button"
71
-      icon={trash}
72
-      title={t("buttons.clearReset")}
73
-      aria-label={t("buttons.clearReset")}
74
-      showAriaLabel={useIsMobile()}
75
-      onClick={() => {
76
-        if (window.confirm(t("alerts.clearReset"))) {
77
-          updateData(null);
78
-        }
79
-      }}
80
-      data-testid="clear-canvas-button"
81
-    />
82
-  ),
68
+
69
+  PanelComponent: ({ updateData }) => <ClearCanvas onConfirm={updateData} />,
83 70
 });
84 71
 
85 72
 export const actionZoomIn = register({

+ 42
- 0
src/components/ClearCanvas.scss Просмотреть файл

@@ -0,0 +1,42 @@
1
+@import "../css/variables.module";
2
+
3
+.excalidraw {
4
+  .clear-canvas {
5
+    &-buttons {
6
+      display: flex;
7
+      padding: 0.2rem 0;
8
+      justify-content: flex-end;
9
+
10
+      .ToolIcon__icon {
11
+        min-width: 2.5rem;
12
+        width: auto;
13
+        font-size: 1rem;
14
+      }
15
+
16
+      .ToolIcon_type_button {
17
+        margin-left: 1.5rem;
18
+        padding: 0 0.5rem;
19
+      }
20
+    }
21
+
22
+    &__content {
23
+      font-size: 1rem;
24
+    }
25
+
26
+    &--confirm.ToolIcon_type_button {
27
+      background-color: $oc-red-6;
28
+
29
+      &:hover {
30
+        background-color: $oc-red-8;
31
+      }
32
+
33
+      .ToolIcon__icon {
34
+        color: $oc-white;
35
+      }
36
+    }
37
+
38
+    &--cancel.ToolIcon_type_button {
39
+      background-color: $oc-gray-2;
40
+    }
41
+  }
42
+}

+ 67
- 0
src/components/ClearCanvas.tsx Просмотреть файл

@@ -0,0 +1,67 @@
1
+import { useState } from "react";
2
+import { t } from "../i18n";
3
+import { useIsMobile } from "./App";
4
+import { Dialog } from "./Dialog";
5
+import { trash } from "./icons";
6
+import { ToolButton } from "./ToolButton";
7
+
8
+import "./ClearCanvas.scss";
9
+
10
+const ClearCanvas = ({ onConfirm }: { onConfirm: () => void }) => {
11
+  const [showDialog, setShowDialog] = useState(false);
12
+  const toggleDialog = () => {
13
+    setShowDialog(!showDialog);
14
+  };
15
+
16
+  return (
17
+    <>
18
+      <ToolButton
19
+        type="button"
20
+        icon={trash}
21
+        title={t("buttons.clearReset")}
22
+        aria-label={t("buttons.clearReset")}
23
+        showAriaLabel={useIsMobile()}
24
+        onClick={toggleDialog}
25
+        data-testid="clear-canvas-button"
26
+      />
27
+
28
+      {showDialog && (
29
+        <Dialog
30
+          onCloseRequest={toggleDialog}
31
+          title={t("clearCanvasDialog.title")}
32
+          className="clear-canvas"
33
+          small={true}
34
+        >
35
+          <>
36
+            <p className="clear-canvas__content"> {t("alerts.clearReset")}</p>
37
+            <div className="clear-canvas-buttons">
38
+              <ToolButton
39
+                type="button"
40
+                title={t("buttons.clear")}
41
+                aria-label={t("buttons.clear")}
42
+                label={t("buttons.clear")}
43
+                onClick={() => {
44
+                  onConfirm();
45
+                  toggleDialog();
46
+                }}
47
+                data-testid="confirm-clear-canvas-button"
48
+                className="clear-canvas--confirm"
49
+              />
50
+              <ToolButton
51
+                type="button"
52
+                title={t("buttons.cancel")}
53
+                aria-label={t("buttons.cancel")}
54
+                label={t("buttons.cancel")}
55
+                onClick={toggleDialog}
56
+                data-testid="cancel-clear-canvas-button"
57
+                className="clear-canvas--cancel"
58
+              />
59
+            </div>
60
+          </>
61
+        </Dialog>
62
+      )}
63
+    </>
64
+  );
65
+};
66
+
67
+export default ClearCanvas;

+ 1
- 0
src/components/LayerUI.tsx Просмотреть файл

@@ -468,6 +468,7 @@ const LayerUI = ({
468 468
       </Section>
469 469
     );
470 470
   };
471
+
471 472
   const renderCanvasActions = () => (
472 473
     <Section
473 474
       heading="canvasActions"

+ 6
- 1
src/locales/en.json Просмотреть файл

@@ -136,7 +136,9 @@
136 136
     "darkMode": "Dark mode",
137 137
     "lightMode": "Light mode",
138 138
     "zenMode": "Zen mode",
139
-    "exitZenMode": "Exit zen mode"
139
+    "exitZenMode": "Exit zen mode",
140
+    "cancel": "Cancel",
141
+    "clear": "Clear"
140 142
   },
141 143
   "alerts": {
142 144
     "clearReset": "This will clear the whole canvas. Are you sure?",
@@ -256,6 +258,9 @@
256 258
     "zoomToFit": "Zoom to fit all elements",
257 259
     "zoomToSelection": "Zoom to selection"
258 260
   },
261
+  "clearCanvasDialog": {
262
+    "title": "Clear Canvas"
263
+  },
259 264
   "encrypted": {
260 265
     "tooltip": "Your drawings are end-to-end encrypted so Excalidraw's servers will never see them.",
261 266
     "link": "Blog post on end-to-end encryption in Excalidraw"

Загрузка…
Отмена
Сохранить