From cd50aa719fa5dcb77beb9f736725fa744e5ba6ba Mon Sep 17 00:00:00 2001 From: Arnost Pleskot Date: Mon, 8 Apr 2024 16:46:24 +0200 Subject: [PATCH] feat: add system mode to the theme selector (#7853) Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com> --- excalidraw-app/App.tsx | 37 ++++------ excalidraw-app/components/AppMainMenu.tsx | 9 ++- excalidraw-app/index.html | 28 ++++++-- excalidraw-app/useHandleAppTheme.ts | 70 +++++++++++++++++++ packages/excalidraw/CHANGELOG.md | 1 + packages/excalidraw/actions/actionCanvas.tsx | 4 +- packages/excalidraw/components/App.tsx | 6 +- .../excalidraw/components/DarkModeToggle.tsx | 4 +- packages/excalidraw/components/RadioGroup.tsx | 7 +- .../components/dropdownMenu/DropdownMenu.scss | 22 ++++++ .../DropdownMenuItemContentRadio.tsx | 51 ++++++++++++++ packages/excalidraw/components/icons.tsx | 17 +++-- .../components/main-menu/DefaultItems.tsx | 64 +++++++++++++++-- packages/excalidraw/data/magic.ts | 3 +- .../hooks/useCreatePortalContainer.ts | 3 +- packages/excalidraw/locales/en.json | 2 + packages/excalidraw/renderer/helpers.ts | 4 +- packages/excalidraw/renderer/renderElement.ts | 5 +- packages/excalidraw/renderer/renderSnaps.ts | 3 +- packages/excalidraw/scene/export.ts | 3 +- setupTests.ts | 14 ++++ 21 files changed, 301 insertions(+), 56 deletions(-) create mode 100644 excalidraw-app/useHandleAppTheme.ts create mode 100644 packages/excalidraw/components/dropdownMenu/DropdownMenuItemContentRadio.tsx 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 @@