diff --git a/assets/dark-mode.svg b/assets/dark-mode.svg new file mode 100644 index 0000000..caeb069 --- /dev/null +++ b/assets/dark-mode.svg @@ -0,0 +1,12 @@ + + + + ic_fluent_dark_theme_24_regular + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 4998314..9b94430 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -114,6 +114,8 @@ export default function App() { const [deviceInfoState, setDeviceInfoState] = useState( [] as DeviceInfoState[], ); + // Dark Mode UI State + const [isDarkMode, setIsDarkMode] = useState(false); const changeActiveModal = (newModalName: string) => { if (document.activeElement instanceof HTMLElement) { @@ -177,6 +179,9 @@ export default function App() { window.electron.ipcRenderer.sendMessage('main-update-robot-mode', mode); setRobotRunning(mode !== RobotRunMode.IDLE); }; + const toggleDarkMode = () => { + setIsDarkMode((prev) => !prev); + }; const closeWindow = useCallback(() => { window.electron.ipcRenderer.sendMessage('main-quit', { @@ -418,6 +423,7 @@ export default function App() { dawnVersion={dawnVersion} robotLatencyMs={robotLatencyMs} robotBatteryVoltage={robotBatteryVoltage} + // isDarkMode={isDarkMode} />
- +
{consoleIsOpen && ( <> @@ -473,7 +481,11 @@ export default function App() { onEndResize={endColsResize} axis="y" /> - + )}
diff --git a/src/renderer/AppConsole.css b/src/renderer/AppConsole.css index 3c9daa2..9b82830 100644 --- a/src/renderer/AppConsole.css +++ b/src/renderer/AppConsole.css @@ -7,7 +7,17 @@ flex-shrink: 0; user-select: text; } -.AppConsole-inner { + +/* Light Mode */ +.AppConsole-message-robot-info-light { + padding-left: 4px; + border-left: 6px solid var(--window-accent-color); +} +.AppConsole-message-light { + padding: 2px; + text-wrap: wrap; +} +.AppConsole-inner-light { height: 100%; background-color: #eee; overflow-y: scroll; @@ -17,19 +27,42 @@ min-height: 0; scroll-behavior: smooth; } -.AppConsole-message { - padding: 2px; - text-wrap: wrap; -} -.AppConsole-message-dawn-err { +.AppConsole-message-dawn-err-light { color: red; } -.AppConsole-message-robot-err { +.AppConsole-message-robot-err-light { background-color: salmon; padding-left: 4px; border-left: 6px solid crimson; } -.AppConsole-message-robot-info { + +/* Dark Mode */ +.AppConsole-message-robot-info-dark { padding-left: 4px; border-left: 6px solid var(--window-accent-color); + color: #FFFFFF +} +.AppConsole-message-dark { + padding: 2px; + text-wrap: wrap; + color: #FFFFFF; +} +.AppConsole-inner-dark { + height: 100%; + background-color: #121212; + overflow-y: scroll; + word-break: break-word; + margin: 0; + margin-bottom: 50px; + min-height: 0; + scroll-behavior: smooth; +} +.AppConsole-message-dawn-err-dark { + color: #f44336; +} +.AppConsole-message-robot-err-dark { + background-color: #ED6C02; + padding-left: 4px; + border-left: 6px solid crimson; } + diff --git a/src/renderer/AppConsole.tsx b/src/renderer/AppConsole.tsx index 3aaf10e..c74aa8b 100644 --- a/src/renderer/AppConsole.tsx +++ b/src/renderer/AppConsole.tsx @@ -1,4 +1,4 @@ -import { useRef, useEffect } from 'react'; +import { useRef, useEffect, useCallback } from 'react'; import AppConsoleMessage from '../common/AppConsoleMessage'; import './AppConsole.css'; @@ -7,13 +7,16 @@ import './AppConsole.css'; * @param props - props * @param props.height - the height of the console in pixels * @param props.messages - array of console messages to display + * @param props.isDarkMode - whether UI is in dark mode */ export default function AppConsole({ height, messages, + isDarkMode, }: { height: number; messages: AppConsoleMessage[]; + isDarkMode: boolean; }) { // Add autoscroll feature to AppConsole by setting the current scrollTop prop to the current scrollHeight value const consoleRef = useRef(null); @@ -26,11 +29,16 @@ export default function AppConsole({ return (
-
+      
         {messages.map((msg: AppConsoleMessage) => (
           
{msg.text}
diff --git a/src/renderer/editor/Editor.tsx b/src/renderer/editor/Editor.tsx index 977ac24..b71a3d4 100644 --- a/src/renderer/editor/Editor.tsx +++ b/src/renderer/editor/Editor.tsx @@ -31,6 +31,7 @@ import startRobot from '../../../assets/start-robot.svg'; import stopRobot from '../../../assets/stop-robot.svg'; import keyboardKeySvg from '../../../assets/keyboard-key.svg'; import themeSvg from '../../../assets/theme.svg'; +import darkModeSvg from '../../../assets/dark-mode.svg'; import './Editor.css'; @@ -108,6 +109,9 @@ const ACE_THEMES = { * @param props.onToggleConsole - handler called when the user wants to toggle the AppConsole's * visibility * @param props.onClearConsole - handler called when the user wants to clear the AppConsole + * dark mode + * @param props.isDarkMode - whether UI is in dark mode + * @param props.onToggleDarkMode - handler called when user wans to toggle UI's dark mode. */ export default function Editor({ width, @@ -120,6 +124,7 @@ export default function Editor({ keyboardControlsStatus, robotConnected, robotRunning, + isDarkMode, onOpen, onSave, onNewFile, @@ -131,6 +136,7 @@ export default function Editor({ onToggleConsole, onClearConsole, onToggleKeyboardControls, + onToggleDarkMode, }: { width: number; /** @@ -146,6 +152,7 @@ export default function Editor({ keyboardControlsStatus: KeyboardControlsStatus; robotConnected: boolean; robotRunning: boolean; + isDarkMode: boolean; onOpen: () => void; /** * handler called when the user wants to save the contents of the editor @@ -165,6 +172,7 @@ export default function Editor({ onToggleConsole: () => void; onClearConsole: () => void; onToggleKeyboardControls: () => void; + onToggleDarkMode: () => void; }) { const [opmode, setOpmode] = useState('auto'); const [fontSize, setFontSize] = useState(12); @@ -298,6 +306,16 @@ export default function Editor({ ))}
+
+ +