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
This commit is contained in:
parent
6eecadce60
commit
0f0244224d
@ -1,14 +1,11 @@
|
|||||||
import { getDefaultAppState } from "../appState";
|
|
||||||
import { ColorPicker } from "../components/ColorPicker";
|
import { ColorPicker } from "../components/ColorPicker";
|
||||||
import { trash, zoomIn, zoomOut } from "../components/icons";
|
import { zoomIn, zoomOut } from "../components/icons";
|
||||||
import { ToolButton } from "../components/ToolButton";
|
import { ToolButton } from "../components/ToolButton";
|
||||||
import { DarkModeToggle } from "../components/DarkModeToggle";
|
import { DarkModeToggle } from "../components/DarkModeToggle";
|
||||||
import { THEME, ZOOM_STEP } from "../constants";
|
import { THEME, ZOOM_STEP } from "../constants";
|
||||||
import { getCommonBounds, getNonDeletedElements } from "../element";
|
import { getCommonBounds, getNonDeletedElements } from "../element";
|
||||||
import { newElementWith } from "../element/mutateElement";
|
|
||||||
import { ExcalidrawElement } from "../element/types";
|
import { ExcalidrawElement } from "../element/types";
|
||||||
import { t } from "../i18n";
|
import { t } from "../i18n";
|
||||||
import { useIsMobile } from "../components/App";
|
|
||||||
import { CODES, KEYS } from "../keys";
|
import { CODES, KEYS } from "../keys";
|
||||||
import { getNormalizedZoom, getSelectedElements } from "../scene";
|
import { getNormalizedZoom, getSelectedElements } from "../scene";
|
||||||
import { centerScrollOn } from "../scene/scroll";
|
import { centerScrollOn } from "../scene/scroll";
|
||||||
@ -17,6 +14,9 @@ import { AppState, NormalizedZoomValue } from "../types";
|
|||||||
import { getShortcutKey } from "../utils";
|
import { getShortcutKey } from "../utils";
|
||||||
import { register } from "./register";
|
import { register } from "./register";
|
||||||
import { Tooltip } from "../components/Tooltip";
|
import { Tooltip } from "../components/Tooltip";
|
||||||
|
import { newElementWith } from "../element/mutateElement";
|
||||||
|
import { getDefaultAppState } from "../appState";
|
||||||
|
import ClearCanvas from "../components/ClearCanvas";
|
||||||
|
|
||||||
export const actionChangeViewBackgroundColor = register({
|
export const actionChangeViewBackgroundColor = register({
|
||||||
name: "changeViewBackgroundColor",
|
name: "changeViewBackgroundColor",
|
||||||
@ -47,7 +47,7 @@ export const actionChangeViewBackgroundColor = register({
|
|||||||
|
|
||||||
export const actionClearCanvas = register({
|
export const actionClearCanvas = register({
|
||||||
name: "clearCanvas",
|
name: "clearCanvas",
|
||||||
perform: (elements, appState: AppState) => {
|
perform: (elements, appState) => {
|
||||||
return {
|
return {
|
||||||
elements: elements.map((element) =>
|
elements: elements.map((element) =>
|
||||||
newElementWith(element, { isDeleted: true }),
|
newElementWith(element, { isDeleted: true }),
|
||||||
@ -65,21 +65,8 @@ export const actionClearCanvas = register({
|
|||||||
commitToHistory: true,
|
commitToHistory: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
PanelComponent: ({ updateData }) => (
|
|
||||||
<ToolButton
|
PanelComponent: ({ updateData }) => <ClearCanvas onConfirm={updateData} />,
|
||||||
type="button"
|
|
||||||
icon={trash}
|
|
||||||
title={t("buttons.clearReset")}
|
|
||||||
aria-label={t("buttons.clearReset")}
|
|
||||||
showAriaLabel={useIsMobile()}
|
|
||||||
onClick={() => {
|
|
||||||
if (window.confirm(t("alerts.clearReset"))) {
|
|
||||||
updateData(null);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
data-testid="clear-canvas-button"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const actionZoomIn = register({
|
export const actionZoomIn = register({
|
||||||
|
42
src/components/ClearCanvas.scss
Normal file
42
src/components/ClearCanvas.scss
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
@import "../css/variables.module";
|
||||||
|
|
||||||
|
.excalidraw {
|
||||||
|
.clear-canvas {
|
||||||
|
&-buttons {
|
||||||
|
display: flex;
|
||||||
|
padding: 0.2rem 0;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.ToolIcon__icon {
|
||||||
|
min-width: 2.5rem;
|
||||||
|
width: auto;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ToolIcon_type_button {
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--confirm.ToolIcon_type_button {
|
||||||
|
background-color: $oc-red-6;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $oc-red-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ToolIcon__icon {
|
||||||
|
color: $oc-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--cancel.ToolIcon_type_button {
|
||||||
|
background-color: $oc-gray-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
src/components/ClearCanvas.tsx
Normal file
67
src/components/ClearCanvas.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { t } from "../i18n";
|
||||||
|
import { useIsMobile } from "./App";
|
||||||
|
import { Dialog } from "./Dialog";
|
||||||
|
import { trash } from "./icons";
|
||||||
|
import { ToolButton } from "./ToolButton";
|
||||||
|
|
||||||
|
import "./ClearCanvas.scss";
|
||||||
|
|
||||||
|
const ClearCanvas = ({ onConfirm }: { onConfirm: () => void }) => {
|
||||||
|
const [showDialog, setShowDialog] = useState(false);
|
||||||
|
const toggleDialog = () => {
|
||||||
|
setShowDialog(!showDialog);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ToolButton
|
||||||
|
type="button"
|
||||||
|
icon={trash}
|
||||||
|
title={t("buttons.clearReset")}
|
||||||
|
aria-label={t("buttons.clearReset")}
|
||||||
|
showAriaLabel={useIsMobile()}
|
||||||
|
onClick={toggleDialog}
|
||||||
|
data-testid="clear-canvas-button"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{showDialog && (
|
||||||
|
<Dialog
|
||||||
|
onCloseRequest={toggleDialog}
|
||||||
|
title={t("clearCanvasDialog.title")}
|
||||||
|
className="clear-canvas"
|
||||||
|
small={true}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<p className="clear-canvas__content"> {t("alerts.clearReset")}</p>
|
||||||
|
<div className="clear-canvas-buttons">
|
||||||
|
<ToolButton
|
||||||
|
type="button"
|
||||||
|
title={t("buttons.clear")}
|
||||||
|
aria-label={t("buttons.clear")}
|
||||||
|
label={t("buttons.clear")}
|
||||||
|
onClick={() => {
|
||||||
|
onConfirm();
|
||||||
|
toggleDialog();
|
||||||
|
}}
|
||||||
|
data-testid="confirm-clear-canvas-button"
|
||||||
|
className="clear-canvas--confirm"
|
||||||
|
/>
|
||||||
|
<ToolButton
|
||||||
|
type="button"
|
||||||
|
title={t("buttons.cancel")}
|
||||||
|
aria-label={t("buttons.cancel")}
|
||||||
|
label={t("buttons.cancel")}
|
||||||
|
onClick={toggleDialog}
|
||||||
|
data-testid="cancel-clear-canvas-button"
|
||||||
|
className="clear-canvas--cancel"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
</Dialog>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ClearCanvas;
|
@ -468,6 +468,7 @@ const LayerUI = ({
|
|||||||
</Section>
|
</Section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderCanvasActions = () => (
|
const renderCanvasActions = () => (
|
||||||
<Section
|
<Section
|
||||||
heading="canvasActions"
|
heading="canvasActions"
|
||||||
|
@ -136,7 +136,9 @@
|
|||||||
"darkMode": "Dark mode",
|
"darkMode": "Dark mode",
|
||||||
"lightMode": "Light mode",
|
"lightMode": "Light mode",
|
||||||
"zenMode": "Zen mode",
|
"zenMode": "Zen mode",
|
||||||
"exitZenMode": "Exit zen mode"
|
"exitZenMode": "Exit zen mode",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"clear": "Clear"
|
||||||
},
|
},
|
||||||
"alerts": {
|
"alerts": {
|
||||||
"clearReset": "This will clear the whole canvas. Are you sure?",
|
"clearReset": "This will clear the whole canvas. Are you sure?",
|
||||||
@ -256,6 +258,9 @@
|
|||||||
"zoomToFit": "Zoom to fit all elements",
|
"zoomToFit": "Zoom to fit all elements",
|
||||||
"zoomToSelection": "Zoom to selection"
|
"zoomToSelection": "Zoom to selection"
|
||||||
},
|
},
|
||||||
|
"clearCanvasDialog": {
|
||||||
|
"title": "Clear Canvas"
|
||||||
|
},
|
||||||
"encrypted": {
|
"encrypted": {
|
||||||
"tooltip": "Your drawings are end-to-end encrypted so Excalidraw's servers will never see them.",
|
"tooltip": "Your drawings are end-to-end encrypted so Excalidraw's servers will never see them.",
|
||||||
"link": "Blog post on end-to-end encryption in Excalidraw"
|
"link": "Blog post on end-to-end encryption in Excalidraw"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user