Add support for system theme (#245)
* Add support for 'system' theme value * Add ability to set theme to 'system' in settings * Fix tsc errors for Theme
This commit is contained in:
13
src/App.tsx
13
src/App.tsx
@ -19,7 +19,7 @@ import {
|
||||
lineHighlightField,
|
||||
addLineHighlight,
|
||||
} from './editor/highlightextension'
|
||||
import { PaneType, Selections, useStore } from './useStore'
|
||||
import { PaneType, Selections, Themes, useStore } from './useStore'
|
||||
import { Logs, KCLErrors } from './components/Logs'
|
||||
import { CollapsiblePanel } from './components/CollapsiblePanel'
|
||||
import { MemoryPanel } from './components/MemoryPanel'
|
||||
@ -42,6 +42,7 @@ import {
|
||||
import { useHotkeys } from 'react-hotkeys-hook'
|
||||
import { TEST } from './env'
|
||||
import { getNormalisedCoordinates } from './lib/utils'
|
||||
import { getSystemTheme } from './lib/getSystemTheme'
|
||||
|
||||
export function App() {
|
||||
const streamRef = useRef<HTMLDivElement>(null)
|
||||
@ -127,6 +128,8 @@ export function App() {
|
||||
streamDimensions: s.streamDimensions,
|
||||
}))
|
||||
|
||||
const editorTheme = theme === Themes.System ? getSystemTheme() : theme
|
||||
|
||||
// Pane toggling keyboard shortcuts
|
||||
const togglePane = useCallback(
|
||||
(newPane: PaneType) =>
|
||||
@ -460,26 +463,26 @@ export function App() {
|
||||
]}
|
||||
onChange={onChange}
|
||||
onUpdate={onUpdate}
|
||||
theme={theme}
|
||||
theme={editorTheme}
|
||||
onCreateEditor={(_editorView) => setEditorView(_editorView)}
|
||||
/>
|
||||
</div>
|
||||
</CollapsiblePanel>
|
||||
<section className="flex flex-col">
|
||||
<MemoryPanel
|
||||
theme={theme}
|
||||
theme={editorTheme}
|
||||
open={openPanes.includes('variables')}
|
||||
title="Variables"
|
||||
icon={faSquareRootVariable}
|
||||
/>
|
||||
<Logs
|
||||
theme={theme}
|
||||
theme={editorTheme}
|
||||
open={openPanes.includes('logs')}
|
||||
title="Logs"
|
||||
icon={faCodeCommit}
|
||||
/>
|
||||
<KCLErrors
|
||||
theme={theme}
|
||||
theme={editorTheme}
|
||||
open={openPanes.includes('kclErrors')}
|
||||
title="KCL Errors"
|
||||
iconClassNames={{ icon: 'group-open:text-destroy-30' }}
|
||||
|
@ -1,15 +1,15 @@
|
||||
import ReactJson from 'react-json-view'
|
||||
import { useEffect } from 'react'
|
||||
import { useStore } from '../useStore'
|
||||
import { Themes, useStore } from '../useStore'
|
||||
import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel'
|
||||
|
||||
const ReactJsonTypeHack = ReactJson as any
|
||||
|
||||
interface LogPanelProps extends CollapsiblePanelProps {
|
||||
theme?: 'light' | 'dark'
|
||||
theme?: Exclude<Themes, Themes.System>
|
||||
}
|
||||
|
||||
export const Logs = ({ theme = 'light', ...props }: LogPanelProps) => {
|
||||
export const Logs = ({ theme = Themes.Light, ...props }: LogPanelProps) => {
|
||||
const { logs } = useStore(({ logs }) => ({
|
||||
logs,
|
||||
}))
|
||||
@ -42,7 +42,10 @@ export const Logs = ({ theme = 'light', ...props }: LogPanelProps) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const KCLErrors = ({ theme = 'light', ...props }: LogPanelProps) => {
|
||||
export const KCLErrors = ({
|
||||
theme = Themes.Light,
|
||||
...props
|
||||
}: LogPanelProps) => {
|
||||
const { kclErrors } = useStore(({ kclErrors }) => ({
|
||||
kclErrors,
|
||||
}))
|
||||
|
@ -1,15 +1,15 @@
|
||||
import ReactJson from 'react-json-view'
|
||||
import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel'
|
||||
import { useStore } from '../useStore'
|
||||
import { Themes, useStore } from '../useStore'
|
||||
import { useMemo } from 'react'
|
||||
import { ProgramMemory } from '../lang/executor'
|
||||
|
||||
interface MemoryPanelProps extends CollapsiblePanelProps {
|
||||
theme?: 'light' | 'dark'
|
||||
theme?: Exclude<Themes, Themes.System>
|
||||
}
|
||||
|
||||
export const MemoryPanel = ({
|
||||
theme = 'light',
|
||||
theme = Themes.Light,
|
||||
...props
|
||||
}: MemoryPanelProps) => {
|
||||
const { programMemory } = useStore((s) => ({
|
||||
|
@ -2,13 +2,15 @@ import ReactDOM from 'react-dom/client'
|
||||
import './index.css'
|
||||
import reportWebVitals from './reportWebVitals'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import { useStore } from './useStore'
|
||||
import { Themes, useStore } from './useStore'
|
||||
import { Router } from './Router'
|
||||
import { HotkeysProvider } from 'react-hotkeys-hook'
|
||||
import { getSystemTheme } from './lib/getSystemTheme'
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
|
||||
function setThemeClass(state: Partial<{ theme: string }>) {
|
||||
if (state.theme === 'dark') {
|
||||
function setThemeClass(state: Partial<{ theme: Themes }>) {
|
||||
const systemTheme = state.theme === Themes.System && getSystemTheme()
|
||||
if (state.theme === Themes.Dark || systemTheme === Themes.Dark) {
|
||||
document.body.classList.add('dark')
|
||||
} else {
|
||||
document.body.classList.remove('dark')
|
||||
|
9
src/lib/getSystemTheme.ts
Normal file
9
src/lib/getSystemTheme.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Themes } from '../useStore'
|
||||
|
||||
export function getSystemTheme(): Exclude<Themes, 'system'> {
|
||||
return typeof window !== 'undefined' &&
|
||||
'matchMedia' in window &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
? Themes.Dark
|
||||
: Themes.Light
|
||||
}
|
@ -6,7 +6,7 @@ import {
|
||||
import { ActionButton } from '../components/ActionButton'
|
||||
import { AppHeader } from '../components/AppHeader'
|
||||
import { open } from '@tauri-apps/api/dialog'
|
||||
import { baseUnits, useStore } from '../useStore'
|
||||
import { Themes, baseUnits, useStore } from '../useStore'
|
||||
import { useRef } from 'react'
|
||||
import { toast } from 'react-hot-toast'
|
||||
import { Toggle } from '../components/Toggle/Toggle'
|
||||
@ -184,21 +184,25 @@ export const Settings = () => {
|
||||
title="Editor Theme"
|
||||
description="Apply a light or dark theme to the editor"
|
||||
>
|
||||
<Toggle
|
||||
name="settings-theme"
|
||||
offLabel="Dark"
|
||||
onLabel="Light"
|
||||
checked={theme === 'light'}
|
||||
<select
|
||||
id="settings-theme"
|
||||
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
|
||||
value={theme}
|
||||
onChange={(e) => {
|
||||
const newTheme = e.target.checked ? 'light' : 'dark'
|
||||
setTheme(newTheme)
|
||||
setTheme(e.target.value as Themes)
|
||||
toast.success(
|
||||
newTheme.slice(0, 1).toLocaleUpperCase() +
|
||||
newTheme.slice(1) +
|
||||
' mode activated'
|
||||
'Theme changed to ' +
|
||||
e.target.value.slice(0, 1).toLocaleUpperCase() +
|
||||
e.target.value.slice(1)
|
||||
)
|
||||
}}
|
||||
/>
|
||||
>
|
||||
{Object.entries(Themes).map(([label, value]) => (
|
||||
<option key={value} value={value}>
|
||||
{label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</SettingsSection>
|
||||
<SettingsSection
|
||||
title="Onboarding"
|
||||
|
@ -97,6 +97,11 @@ export type GuiModes =
|
||||
}
|
||||
|
||||
type UnitSystem = 'imperial' | 'metric'
|
||||
export enum Themes {
|
||||
Light = 'light',
|
||||
Dark = 'dark',
|
||||
System = 'system',
|
||||
}
|
||||
|
||||
export const baseUnits: Record<UnitSystem, string[]> = {
|
||||
imperial: ['in', 'ft'],
|
||||
@ -204,8 +209,8 @@ export interface StoreState {
|
||||
setHomeShowMenu: (showMenu: boolean) => void
|
||||
onboardingStatus: string
|
||||
setOnboardingStatus: (status: string) => void
|
||||
theme: 'light' | 'dark'
|
||||
setTheme: (theme: 'light' | 'dark') => void
|
||||
theme: Themes
|
||||
setTheme: (theme: Themes) => void
|
||||
openPanes: PaneType[]
|
||||
setOpenPanes: (panes: PaneType[]) => void
|
||||
homeMenuItems: {
|
||||
@ -409,12 +414,7 @@ export const useStore = create<StoreState>()(
|
||||
setDefaultBaseUnit: (defaultBaseUnit) => set({ defaultBaseUnit }),
|
||||
onboardingStatus: '',
|
||||
setOnboardingStatus: (onboardingStatus) => set({ onboardingStatus }),
|
||||
theme:
|
||||
typeof window !== 'undefined' &&
|
||||
'matchMedia' in window &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
? 'dark'
|
||||
: 'light',
|
||||
theme: Themes.System,
|
||||
setTheme: (theme) => set({ theme }),
|
||||
openPanes: ['code'],
|
||||
setOpenPanes: (openPanes) => set({ openPanes }),
|
||||
|
Reference in New Issue
Block a user