Skip to content

Commit 7af2908

Browse files
committed
feat: add SettingsDialog and integrate into ExcalidrawWrapper and MainMenu
- Introduced a new SettingsDialog component for managing application settings. - Updated ExcalidrawWrapper to handle the visibility of the SettingsDialog. - Enhanced MainMenu to include a Settings option that triggers the SettingsDialog. - Added corresponding styles for the SettingsDialog to ensure a cohesive UI experience.
1 parent 8d7d145 commit 7af2908

File tree

4 files changed

+124
-3
lines changed

4 files changed

+124
-3
lines changed

src/frontend/src/ExcalidrawWrapper.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { MainMenuConfig } from './ui/MainMenu';
88
import { lockEmbeddables, renderCustomEmbeddable } from './CustomEmbeddableRenderer';
99
import AuthDialog from './ui/AuthDialog';
1010
import BackupsModal from './ui/BackupsDialog';
11+
import SettingsDialog from './ui/SettingsDialog';
1112

1213
const defaultInitialData = {
1314
elements: [],
@@ -47,8 +48,9 @@ export const ExcalidrawWrapper: React.FC<ExcalidrawWrapperProps> = ({
4748
// Add state for modal animation
4849
const [isExiting, setIsExiting] = useState(false);
4950

50-
// State for BackupsModal
51+
// State for modals
5152
const [showBackupsModal, setShowBackupsModal] = useState(false);
53+
const [showSettingsModal, setShowSettingsModal] = useState(false);
5254

5355
// Handle auth state changes
5456
useEffect(() => {
@@ -57,11 +59,15 @@ export const ExcalidrawWrapper: React.FC<ExcalidrawWrapperProps> = ({
5759
}
5860
}, [isAuthenticated]);
5961

60-
// Handler for closing the backups modal
62+
// Handlers for closing modals
6163
const handleCloseBackupsModal = () => {
6264
setShowBackupsModal(false);
6365
};
6466

67+
const handleCloseSettingsModal = () => {
68+
setShowSettingsModal(false);
69+
};
70+
6571
const renderExcalidraw = (children: React.ReactNode) => {
6672
const Excalidraw = Children.toArray(children).find(
6773
(child: any) =>
@@ -98,6 +104,8 @@ export const ExcalidrawWrapper: React.FC<ExcalidrawWrapperProps> = ({
98104
excalidrawAPI={excalidrawAPI}
99105
showBackupsModal={showBackupsModal}
100106
setShowBackupsModal={setShowBackupsModal}
107+
showSettingsModal={showSettingsModal}
108+
setShowSettingsModal={setShowSettingsModal}
101109
/>
102110
{!isAuthLoading && isAuthenticated === false && (
103111
<AuthDialog
@@ -111,6 +119,12 @@ export const ExcalidrawWrapper: React.FC<ExcalidrawWrapperProps> = ({
111119
onClose={handleCloseBackupsModal}
112120
/>
113121
)}
122+
123+
{showSettingsModal && (
124+
<SettingsDialog
125+
onClose={handleCloseSettingsModal}
126+
/>
127+
)}
114128
</>
115129
);
116130
};

src/frontend/src/ui/MainMenu.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,29 @@ import React, { useState } from 'react';
33
import type { ExcalidrawImperativeAPI } from '@atyrode/excalidraw/types';
44
import type { MainMenu as MainMenuType } from '@atyrode/excalidraw';
55

6-
import { LogOut, SquarePlus, LayoutDashboard, SquareCode, Eye, Coffee, Grid2x2, User, Text, ArchiveRestore } from 'lucide-react';
6+
import { LogOut, SquarePlus, LayoutDashboard, SquareCode, Eye, Coffee, Grid2x2, User, Text, ArchiveRestore, Settings } from 'lucide-react';
77
import { capture } from '../utils/posthog';
88
import { ExcalidrawElementFactory, PlacementMode } from '../lib/ExcalidrawElementFactory';
99
import { useUserProfile } from "../api/hooks";
1010
import { queryClient } from "../api/queryClient";
11+
import SettingsDialog from "./SettingsDialog";
1112
import "./MainMenu.scss";
1213
interface MainMenuConfigProps {
1314
MainMenu: typeof MainMenuType;
1415
excalidrawAPI: ExcalidrawImperativeAPI | null;
1516
showBackupsModal: boolean;
1617
setShowBackupsModal: (show: boolean) => void;
18+
showSettingsModal?: boolean;
19+
setShowSettingsModal?: (show: boolean) => void;
1720
}
1821

1922
export const MainMenuConfig: React.FC<MainMenuConfigProps> = ({
2023
MainMenu,
2124
excalidrawAPI,
2225
showBackupsModal,
2326
setShowBackupsModal,
27+
showSettingsModal = false,
28+
setShowSettingsModal = (show: boolean) => {},
2429
}) => {
2530
const { data, isLoading, isError } = useUserProfile();
2631

@@ -100,6 +105,10 @@ export const MainMenuConfig: React.FC<MainMenuConfigProps> = ({
100105
setShowBackupsModal(true);
101106
};
102107

108+
const handleSettingsClick = () => {
109+
setShowSettingsModal(true);
110+
};
111+
103112
const handleGridToggle = () => {
104113
if (!excalidrawAPI) return;
105114
const appState = excalidrawAPI.getAppState();
@@ -207,6 +216,13 @@ export const MainMenuConfig: React.FC<MainMenuConfigProps> = ({
207216

208217
<MainMenu.Separator />
209218

219+
<MainMenu.Item
220+
icon={<Settings />}
221+
onClick={handleSettingsClick}
222+
>
223+
Settings
224+
</MainMenu.Item>
225+
210226
<MainMenu.Item
211227
icon={<LogOut />}
212228
onClick={async () => {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
.settings-dialog {
2+
&__wrapper {
3+
position: absolute;
4+
top: 0;
5+
left: 0;
6+
right: 0;
7+
bottom: 0;
8+
z-index: 1000;
9+
background-color: rgba(0, 0, 0, 0.2);
10+
backdrop-filter: blur(1px);
11+
}
12+
13+
&__title-container {
14+
display: flex;
15+
align-items: center;
16+
justify-content: space-between;
17+
}
18+
19+
&__title {
20+
margin: 0;
21+
font-size: 1.2rem;
22+
font-weight: 600;
23+
}
24+
25+
&__content {
26+
padding: 1rem;
27+
min-height: 200px;
28+
display: flex;
29+
flex-direction: column;
30+
}
31+
32+
&__empty {
33+
display: flex;
34+
align-items: center;
35+
justify-content: center;
36+
height: 100%;
37+
color: #888;
38+
font-style: italic;
39+
}
40+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import React, { useState, useCallback } from "react";
2+
import { Dialog } from "@atyrode/excalidraw";
3+
import "./SettingsDialog.scss";
4+
5+
interface SettingsDialogProps {
6+
onClose?: () => void;
7+
}
8+
9+
const SettingsDialog: React.FC<SettingsDialogProps> = ({
10+
onClose,
11+
}) => {
12+
const [modalIsShown, setModalIsShown] = useState(true);
13+
14+
const handleClose = useCallback(() => {
15+
setModalIsShown(false);
16+
if (onClose) {
17+
onClose();
18+
}
19+
}, [onClose]);
20+
21+
// Dialog content
22+
const dialogContent = (
23+
<div className="settings-dialog__content">
24+
{/* Settings content will go here in the future */}
25+
<div className="settings-dialog__empty">Settings dialog is empty for now</div>
26+
</div>
27+
);
28+
29+
return (
30+
<>
31+
{modalIsShown && (
32+
<div className="settings-dialog__wrapper">
33+
<Dialog
34+
className="settings-dialog"
35+
size="small"
36+
onCloseRequest={handleClose}
37+
title={
38+
<div className="settings-dialog__title-container">
39+
<h2 className="settings-dialog__title">Settings</h2>
40+
</div>
41+
}
42+
closeOnClickOutside={true}
43+
children={dialogContent}
44+
/>
45+
</div>
46+
)}
47+
</>
48+
);
49+
};
50+
51+
export default SettingsDialog;

0 commit comments

Comments
 (0)