diff --git a/src/app/App.test.tsx b/src/app/App.test.tsx
index 2f15a31f..02be2edc 100644
--- a/src/app/App.test.tsx
+++ b/src/app/App.test.tsx
@@ -21,7 +21,10 @@ afterEach(() => {
});
it.each([false, true])('should render', (darkMode) => {
- localStorage.setItem('usehooks-ts-dark-mode', String(darkMode));
+ localStorage.setItem(
+ 'usehooks-ts-ternary-dark-mode',
+ JSON.stringify(darkMode ? 'dark' : 'light'),
+ );
testRender();
});
diff --git a/src/app/App.tsx b/src/app/App.tsx
index c049f48d..9337d94f 100644
--- a/src/app/App.tsx
+++ b/src/app/App.tsx
@@ -5,7 +5,7 @@ import { Classes } from '@blueprintjs/core';
import React, { useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
import SplitterLayout from 'react-splitter-layout';
-import { useDarkMode, useLocalStorage } from 'usehooks-ts';
+import { useLocalStorage, useTernaryDarkMode } from 'usehooks-ts';
import Editor, { EditorType } from '../editor/Editor';
import Explorer from '../explorer/Explorer';
import { settingsToggleShowDocs } from '../settings/actions';
@@ -131,7 +131,7 @@ type AppProps = {
};
const App: React.VoidFunctionComponent = ({ onEditorChanged }) => {
- const { isDarkMode } = useDarkMode();
+ const { isDarkMode } = useTernaryDarkMode();
const { isSettingShowDocsEnabled } = useSettingIsShowDocsEnabled();
const [isDragging, setIsDragging] = useState(false);
const dispatch = useDispatch();
diff --git a/src/editor/Editor.tsx b/src/editor/Editor.tsx
index 20884feb..4c48d6af 100644
--- a/src/editor/Editor.tsx
+++ b/src/editor/Editor.tsx
@@ -9,7 +9,7 @@ import xcodeTheme from 'monaco-themes/themes/Xcode_default.json';
import React, { useState } from 'react';
import MonacoEditor, { monaco } from 'react-monaco-editor';
import { useDispatch } from 'react-redux';
-import { useDarkMode } from 'usehooks-ts';
+import { useTernaryDarkMode } from 'usehooks-ts';
import { IDisposable } from 'xterm';
import { fileStorageWriteFile } from '../fileStorage/actions';
import { compile } from '../mpy/actions';
@@ -141,7 +141,7 @@ const Editor: React.VoidFunctionComponent = ({ onEditorChanged }) =
const dispatch = useDispatch();
const [editor, setEditor] = useState(null);
- const { isDarkMode } = useDarkMode();
+ const { isDarkMode } = useTernaryDarkMode();
const [i18n] = useI18n({ id: 'editor', translations: { en }, fallback: en });
diff --git a/src/settings/SettingsDrawer.test.tsx b/src/settings/SettingsDrawer.test.tsx
index a28c4c47..dbf20faa 100644
--- a/src/settings/SettingsDrawer.test.tsx
+++ b/src/settings/SettingsDrawer.test.tsx
@@ -39,6 +39,25 @@ describe('showDocs setting switch', () => {
});
});
+describe('darkMode setting switch', () => {
+ it('should toggle setting', async () => {
+ const [settings] = testRender(
+ undefined} />,
+ );
+
+ const darkMode = settings.getByLabelText('Dark mode');
+ expect(darkMode).not.toBeChecked();
+ expect(localStorage.getItem('usehooks-ts-ternary-dark-mode')).toBe(null);
+
+ userEvent.click(darkMode);
+ expect(darkMode).toBeChecked();
+ expect(localStorage.getItem('usehooks-ts-ternary-dark-mode')).toBe('"dark"');
+
+ userEvent.click(darkMode);
+ expect(darkMode).not.toBeChecked();
+ expect(localStorage.getItem('usehooks-ts-ternary-dark-mode')).toBe('"light"');
+ });
+});
describe('flashCurrentProgram setting switch', () => {
it('should toggle the setting', () => {
const [settings] = testRender(
diff --git a/src/settings/SettingsDrawer.tsx b/src/settings/SettingsDrawer.tsx
index 84bdb0cc..2d614746 100644
--- a/src/settings/SettingsDrawer.tsx
+++ b/src/settings/SettingsDrawer.tsx
@@ -21,7 +21,7 @@ import { Tooltip2 } from '@blueprintjs/popover2';
import { useI18n } from '@shopify/react-i18n';
import React, { useMemo, useState } from 'react';
import { useDispatch } from 'react-redux';
-import { useDarkMode } from 'usehooks-ts';
+import { useTernaryDarkMode } from 'usehooks-ts';
import AboutDialog from '../about/AboutDialog';
import { appCheckForUpdate, appReload, appShowInstallPrompt } from '../app/actions';
import {
@@ -59,7 +59,7 @@ const SettingsDrawer: React.VoidFunctionComponent = ({
toggleIsSettingShowDocsEnabled,
} = useSettingIsShowDocsEnabled();
const [isAboutDialogOpen, setIsAboutDialogOpen] = useState(false);
- const { isDarkMode, toggle: toggleDarkMode } = useDarkMode();
+ const { isDarkMode, setTernaryDarkMode } = useTernaryDarkMode();
const [isFlashCurrentProgramEnabled, setIsFlashCurrentProgramEnabled] =
useSettingFlashCurrentProgram();
@@ -153,7 +153,13 @@ const SettingsDrawer: React.VoidFunctionComponent = ({
SettingsStringId.AppearanceDarkModeLabel,
)}
checked={isDarkMode}
- onChange={toggleDarkMode}
+ onChange={(e) =>
+ setTernaryDarkMode(
+ (e.target as HTMLInputElement).checked
+ ? 'dark'
+ : 'light',
+ )
+ }
/>
diff --git a/src/terminal/Terminal.tsx b/src/terminal/Terminal.tsx
index fd7db5b1..09e1f025 100644
--- a/src/terminal/Terminal.tsx
+++ b/src/terminal/Terminal.tsx
@@ -6,7 +6,7 @@ import { ContextMenu2, ContextMenu2ContentProps } from '@blueprintjs/popover2';
import { useI18n } from '@shopify/react-i18n';
import React, { useContext, useEffect, useMemo, useRef } from 'react';
import { useDispatch } from 'react-redux';
-import { useDarkMode } from 'usehooks-ts';
+import { useTernaryDarkMode } from 'usehooks-ts';
import { Terminal as XTerm } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import { isMacOS } from '../utils/os';
@@ -100,7 +100,7 @@ function createContextMenu(
const Terminal: React.FC = (_props) => {
const { xterm, fitAddon } = useMemo(createXTerm, [createXTerm]);
const terminalRef = useRef(null);
- const { isDarkMode } = useDarkMode();
+ const { isDarkMode } = useTernaryDarkMode();
const dispatch = useDispatch();
const terminalStream = useContext(TerminalContext);