Skip to content

Commit

Permalink
fix: default light theme splash 🔧 (excalidraw#5660)
Browse files Browse the repository at this point in the history
Co-authored-by: dwelle <[email protected]>
Co-authored-by: Aakansha Doshi <[email protected]>
  • Loading branch information
3 people authored Sep 16, 2022
1 parent ec4b3d9 commit 7eaf47c
Show file tree
Hide file tree
Showing 16 changed files with 97 additions and 52 deletions.
1 change: 0 additions & 1 deletion src/actions/manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ export class ActionManager {
*/
renderAction = (name: ActionName, data?: PanelComponentProps["data"]) => {
const canvasActions = this.app.props.UIOptions.canvasActions;

if (
this.actions[name] &&
"PanelComponent" in this.actions[name] &&
Expand Down
15 changes: 6 additions & 9 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -552,10 +552,6 @@ class App extends React.Component<AppProps, AppState> {
typeof this.props?.zenModeEnabled === "undefined" &&
this.state.zenModeEnabled
}
showThemeBtn={
typeof this.props?.theme === "undefined" &&
this.props.UIOptions.canvasActions.theme
}
libraryReturnUrl={this.props.libraryReturnUrl}
UIOptions={this.props.UIOptions}
focusContainer={this.focusContainer}
Expand Down Expand Up @@ -645,7 +641,8 @@ class App extends React.Component<AppProps, AppState> {
let viewModeEnabled = actionResult?.appState?.viewModeEnabled || false;
let zenModeEnabled = actionResult?.appState?.zenModeEnabled || false;
let gridSize = actionResult?.appState?.gridSize || null;
let theme = actionResult?.appState?.theme || THEME.LIGHT;
const theme =
actionResult?.appState?.theme || this.props.theme || THEME.LIGHT;
let name = actionResult?.appState?.name ?? this.state.name;
if (typeof this.props.viewModeEnabled !== "undefined") {
viewModeEnabled = this.props.viewModeEnabled;
Expand All @@ -659,10 +656,6 @@ class App extends React.Component<AppProps, AppState> {
gridSize = this.props.gridModeEnabled ? GRID_SIZE : null;
}

if (typeof this.props.theme !== "undefined") {
theme = this.props.theme;
}

if (typeof this.props.name !== "undefined") {
name = this.props.name;
}
Expand Down Expand Up @@ -755,6 +748,9 @@ class App extends React.Component<AppProps, AppState> {
);
}

if (this.props.theme) {
this.setState({ theme: this.props.theme });
}
if (!this.state.isLoading) {
this.setState({ isLoading: true });
}
Expand Down Expand Up @@ -784,6 +780,7 @@ class App extends React.Component<AppProps, AppState> {
const scene = restore(initialData, null, null);
scene.appState = {
...scene.appState,
theme: this.props.theme || scene.appState.theme,
// we're falling back to current (pre-init) state when deciding
// whether to open the library, to handle a case where we
// update the state outside of initialData (e.g. when loading the app
Expand Down
10 changes: 1 addition & 9 deletions src/components/BackgroundPickerAndDarkModeToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import React from "react";
import { ActionManager } from "../actions/manager";
import { AppState } from "../types";

export const BackgroundPickerAndDarkModeToggle = ({
appState,
setAppState,
actionManager,
showThemeBtn,
}: {
actionManager: ActionManager;
appState: AppState;
setAppState: React.Component<any, AppState>["setState"];
showThemeBtn: boolean;
}) => (
<div style={{ display: "flex" }}>
{actionManager.renderAction("changeViewBackgroundColor")}
{showThemeBtn && actionManager.renderAction("toggleTheme")}
{actionManager.renderAction("toggleTheme")}
</div>
);
4 changes: 3 additions & 1 deletion src/components/InitializeApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import React, { useEffect, useState } from "react";

import { LoadingMessage } from "./LoadingMessage";
import { defaultLang, Language, languages, setLanguage } from "../i18n";
import { Theme } from "../element/types";

interface Props {
langCode: Language["code"];
children: React.ReactElement;
theme?: Theme;
}

export const InitializeApp = (props: Props) => {
Expand All @@ -21,5 +23,5 @@ export const InitializeApp = (props: Props) => {
updateLang();
}, [props.langCode]);

return loading ? <LoadingMessage /> : props.children;
return loading ? <LoadingMessage theme={props.theme} /> : props.children;
};
10 changes: 1 addition & 9 deletions src/components/LayerUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ interface LayerUIProps {
onPenModeToggle: () => void;
onInsertElements: (elements: readonly NonDeletedExcalidrawElement[]) => void;
showExitZenModeBtn: boolean;
showThemeBtn: boolean;
langCode: Language["code"];
isCollaborating: boolean;
renderTopRightUI?: ExcalidrawProps["renderTopRightUI"];
Expand All @@ -78,7 +77,6 @@ const LayerUI = ({
onPenModeToggle,
onInsertElements,
showExitZenModeBtn,
showThemeBtn,
isCollaborating,
renderTopRightUI,
renderCustomFooter,
Expand Down Expand Up @@ -209,12 +207,7 @@ const LayerUI = ({
/>
)}
</Stack.Row>
<BackgroundPickerAndDarkModeToggle
appState={appState}
actionManager={actionManager}
setAppState={setAppState}
showThemeBtn={showThemeBtn}
/>
<BackgroundPickerAndDarkModeToggle actionManager={actionManager} />
{appState.fileHandle && (
<>{actionManager.renderAction("saveToActiveFile")}</>
)}
Expand Down Expand Up @@ -424,7 +417,6 @@ const LayerUI = ({
canvas={canvas}
isCollaborating={isCollaborating}
renderCustomFooter={renderCustomFooter}
showThemeBtn={showThemeBtn}
onImageAction={onImageAction}
renderTopRightUI={renderTopRightUI}
renderCustomStats={renderCustomStats}
Expand Down
14 changes: 12 additions & 2 deletions src/components/LoadingMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { t } from "../i18n";
import { useState, useEffect } from "react";
import Spinner from "./Spinner";
import clsx from "clsx";
import { THEME } from "../constants";
import { Theme } from "../element/types";

export const LoadingMessage: React.FC<{ delay?: number }> = ({ delay }) => {
export const LoadingMessage: React.FC<{ delay?: number; theme?: Theme }> = ({
delay,
theme,
}) => {
const [isWaiting, setIsWaiting] = useState(!!delay);

useEffect(() => {
Expand All @@ -20,7 +26,11 @@ export const LoadingMessage: React.FC<{ delay?: number }> = ({ delay }) => {
}

return (
<div className="LoadingMessage">
<div
className={clsx("LoadingMessage", {
"LoadingMessage--dark": theme === THEME.DARK,
})}
>
<div>
<Spinner />
</div>
Expand Down
11 changes: 1 addition & 10 deletions src/components/MobileMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ type MobileMenuProps = {
isMobile: boolean,
appState: AppState,
) => JSX.Element | null;
showThemeBtn: boolean;
onImageAction: (data: { insertOnCanvasDirectly: boolean }) => void;
renderTopRightUI?: (
isMobile: boolean,
Expand All @@ -61,7 +60,6 @@ export const MobileMenu = ({
canvas,
isCollaborating,
renderCustomFooter,
showThemeBtn,
onImageAction,
renderTopRightUI,
renderCustomStats,
Expand Down Expand Up @@ -171,14 +169,7 @@ export const MobileMenu = ({
onClick={onCollabButtonClick}
/>
)}
{
<BackgroundPickerAndDarkModeToggle
actionManager={actionManager}
appState={appState}
setAppState={setAppState}
showThemeBtn={showThemeBtn}
/>
}
{<BackgroundPickerAndDarkModeToggle actionManager={actionManager} />}
</>
);
};
Expand Down
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export const DEFAULT_UI_OPTIONS: AppProps["UIOptions"] = {
export: { saveFileToDisk: true },
loadScene: true,
saveToActiveFile: true,
theme: true,
toggleTheme: null,
saveAsImage: true,
},
};
Expand Down
7 changes: 7 additions & 0 deletions src/css/app.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@import "open-color/open-color.scss";

.visually-hidden {
position: absolute !important;
height: 1px;
Expand Down Expand Up @@ -30,3 +32,8 @@
font-size: 0.8em;
}
}

.LoadingMessage--dark {
background-color: $oc-black;
color: $oc-white;
}
1 change: 1 addition & 0 deletions src/excalidraw-app/app_constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const STORAGE_KEYS = {
LOCAL_STORAGE_APP_STATE: "excalidraw-state",
LOCAL_STORAGE_COLLAB: "excalidraw-collab",
LOCAL_STORAGE_LIBRARY: "excalidraw-library",
LOCAL_STORAGE_THEME: "excalidraw-theme",
VERSION_DATA_STATE: "version-dataState",
VERSION_FILES: "version-files",
} as const;
18 changes: 18 additions & 0 deletions src/excalidraw-app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
APP_NAME,
COOKIES,
EVENT,
THEME,
TITLE_TIMEOUT,
VERSION_TIMEOUT,
} from "../constants";
Expand All @@ -17,6 +18,7 @@ import {
ExcalidrawElement,
FileId,
NonDeletedExcalidrawElement,
Theme,
} from "../element/types";
import { useCallbackRefState } from "../hooks/useCallbackRefState";
import { t } from "../i18n";
Expand Down Expand Up @@ -512,6 +514,18 @@ const ExcalidrawWrapper = () => {
languageDetector.cacheUserLanguage(langCode);
}, [langCode]);

const [theme, setTheme] = useState<Theme>(
() =>
localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_THEME) ||
// 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);
}, [theme]);

const onChange = (
elements: readonly ExcalidrawElement[],
appState: AppState,
Expand All @@ -521,6 +535,8 @@ 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()) {
Expand Down Expand Up @@ -710,6 +726,7 @@ const ExcalidrawWrapper = () => {
onPointerUpdate={collabAPI?.onPointerUpdate}
UIOptions={{
canvasActions: {
toggleTheme: true,
export: {
onExportToBackend,
renderCustomUI: (elements, appState, files) => {
Expand Down Expand Up @@ -739,6 +756,7 @@ const ExcalidrawWrapper = () => {
handleKeyboardGlobally={true}
onLibraryChange={onLibraryChange}
autoFocus={true}
theme={theme}
/>
{excalidrawAPI && <Collab excalidrawAPI={excalidrawAPI} />}
{errorMessage && (
Expand Down
2 changes: 2 additions & 0 deletions src/packages/excalidraw/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ Please add the latest change on the top under the correct section.

#### Features

- Support [theme](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#theme) to be semi-controlled [#5660](https://github.com/excalidraw/excalidraw/pull/5660).
- Added support for storing [`customData`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#storing-custom-data-to-excalidraw-elements) on Excalidraw elements [#5592].
- Added `exportPadding?: number;` to [exportToCanvas](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#exporttocanvas) and [exportToBlob](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#exporttoblob). The default value of the padding is 10.

#### Breaking Changes

- `props.UIOptions.canvasActions.theme` is now renamed to `props.UIOptions.canvasActions.toggleTheme` [#5660](https://github.com/excalidraw/excalidraw/pull/5660).
- `setToastMessage` API is now renamed to `setToast` API and the function signature is also updated [#5427](https://github.com/excalidraw/excalidraw/pull/5427). You can also pass `duration` and `closable` attributes along with `message`.

## 0.12.0 (2022-07-07)
Expand Down
6 changes: 4 additions & 2 deletions src/packages/excalidraw/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,9 @@ If supplied, this URL will be used when user tries to install a library from [li

#### `theme`

This prop controls Excalidraw's theme. When supplied, the value takes precedence over `intialData.appState.theme`, the theme will be fully controlled by the host app, and users won't be able to toggle it from within the app. You can use [`THEME`](#THEME-1) to specify the theme.
This prop controls Excalidraw's theme. When supplied, the value takes precedence over `intialData.appState.theme`, the theme will be fully controlled by the host app, and users won't be able to toggle it from within the app unless `UIOptions.canvasActions.toggleTheme` is set to `true`, in which case the `theme` prop will control Excalidraw's default theme with ability to allow theme switching (you must take care of updating the `theme` prop when you detect a change to `appState.theme` from the [onChange](#onChange) callback).

You can use [`THEME`](#THEME-1) to specify the theme.

#### `name`

Expand All @@ -660,7 +662,7 @@ This prop can be used to customise UI of Excalidraw. Currently we support custom
| `export` | false &#124; [exportOpts](#exportOpts) | <pre>{ saveFileToDisk: true }</pre> | This prop allows to customize the UI inside the export dialog. By default it shows the "saveFileToDisk". If this prop is `false` the export button will not be rendered. For more details visit [`exportOpts`](#exportOpts). |
| `loadScene` | boolean | true | Implies whether to show `Load button` |
| `saveToActiveFile` | boolean | true | Implies whether to show `Save button` to save to current file |
| `theme` | boolean | true | Implies whether to show `Theme toggle` |
| `toggleTheme` | boolean &#124; null | null | Implies whether to show `Theme toggle`. When defined as `boolean`, takes precedence over [`props.theme`](#theme) to show `Theme toggle` |
| `saveAsImage` | boolean | true | Implies whether to show `Save as image button` |

##### `dockedSidebarBreakpoint`
Expand Down
9 changes: 8 additions & 1 deletion src/packages/excalidraw/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
DEFAULT_UI_OPTIONS.canvasActions.export.saveFileToDisk;
}

if (
UIOptions.canvasActions.toggleTheme === null &&
typeof theme === "undefined"
) {
UIOptions.canvasActions.toggleTheme = true;
}

useEffect(() => {
// Block pinch-zooming on iOS outside of the content area
const handleTouchMove = (event: TouchEvent) => {
Expand All @@ -75,7 +82,7 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
}, []);

return (
<InitializeApp langCode={langCode}>
<InitializeApp langCode={langCode} theme={theme}>
<Provider unstable_createStore={() => jotaiStore} scope={jotaiScope}>
<App
onChange={onChange}
Expand Down
Loading

0 comments on commit 7eaf47c

Please sign in to comment.