diff --git a/excalidraw-app/App.tsx b/excalidraw-app/App.tsx index 1bf126924..56033ec15 100644 --- a/excalidraw-app/App.tsx +++ b/excalidraw-app/App.tsx @@ -17,7 +17,6 @@ import { FileId, NonDeletedExcalidrawElement, OrderedExcalidrawElement, - Theme, } from "../packages/excalidraw/element/types"; import { useCallbackRefState } from "../packages/excalidraw/hooks/useCallbackRefState"; import { t } from "../packages/excalidraw/i18n"; @@ -124,6 +123,7 @@ import { exportToPlus, share, } from "../packages/excalidraw/components/icons"; +import { appThemeAtom, useHandleAppTheme } from "./useHandleAppTheme"; polyfill(); @@ -303,6 +303,9 @@ const ExcalidrawWrapper = () => { const [langCode, setLangCode] = useAtom(appLangCodeAtom); const isCollabDisabled = isRunningInIframe(); + const [appTheme, setAppTheme] = useAtom(appThemeAtom); + const { editorTheme } = useHandleAppTheme(); + // initial state // --------------------------------------------------------------------------- @@ -566,23 +569,6 @@ const ExcalidrawWrapper = () => { languageDetector.cacheUserLanguage(langCode); }, [langCode]); - const [theme, setTheme] = useState( - () => - (localStorage.getItem( - STORAGE_KEYS.LOCAL_STORAGE_THEME, - ) as Theme | null) || - // FIXME migration from old LS scheme. Can be removed later. #5660 - importFromLocalStorage().appState?.theme || - THEME.LIGHT, - ); - - useEffect(() => { - localStorage.setItem(STORAGE_KEYS.LOCAL_STORAGE_THEME, theme); - // currently only used for body styling during init (see public/index.html), - // but may change in the future - document.documentElement.classList.toggle("dark", theme === THEME.DARK); - }, [theme]); - const onChange = ( elements: readonly OrderedExcalidrawElement[], appState: AppState, @@ -592,8 +578,6 @@ const ExcalidrawWrapper = () => { collabAPI.syncElements(elements); } - setTheme(appState.theme); - // this check is redundant, but since this is a hot path, it's best // not to evaludate the nested expression every time if (!LocalData.isSavePaused()) { @@ -798,7 +782,7 @@ const ExcalidrawWrapper = () => { detectScroll={false} handleKeyboardGlobally={true} autoFocus={true} - theme={theme} + theme={editorTheme} renderTopRightUI={(isMobile) => { if (isMobile || !collabAPI || isCollabDisabled) { return null; @@ -820,6 +804,8 @@ const ExcalidrawWrapper = () => { onCollabDialogOpen={onCollabDialogOpen} isCollaborating={isCollaborating} isCollabEnabled={!isCollabDisabled} + theme={appTheme} + setTheme={(theme) => setAppTheme(theme)} /> { } }, }, - CommandPalette.defaultItems.toggleTheme, + { + ...CommandPalette.defaultItems.toggleTheme, + perform: () => { + setAppTheme( + editorTheme === THEME.DARK ? THEME.LIGHT : THEME.DARK, + ); + }, + }, ]} /> diff --git a/excalidraw-app/components/AppMainMenu.tsx b/excalidraw-app/components/AppMainMenu.tsx index 813d620c8..fe3f36c9e 100644 --- a/excalidraw-app/components/AppMainMenu.tsx +++ b/excalidraw-app/components/AppMainMenu.tsx @@ -1,5 +1,6 @@ import React from "react"; import { PlusPromoIcon } from "../../packages/excalidraw/components/icons"; +import { Theme } from "../../packages/excalidraw/element/types"; import { MainMenu } from "../../packages/excalidraw/index"; import { LanguageList } from "./LanguageList"; @@ -7,6 +8,8 @@ export const AppMainMenu: React.FC<{ onCollabDialogOpen: () => any; isCollaborating: boolean; isCollabEnabled: boolean; + theme: Theme | "system"; + setTheme: (theme: Theme | "system") => void; }> = React.memo((props) => { return ( @@ -35,7 +38,11 @@ export const AppMainMenu: React.FC<{ - + diff --git a/excalidraw-app/index.html b/excalidraw-app/index.html index 4d0e2eaa5..db5bd6457 100644 --- a/excalidraw-app/index.html +++ b/excalidraw-app/index.html @@ -64,12 +64,30 @@