feat: allow forcing dark/light theme on apps

This commit is contained in:
Ruben Fiszel
2024-11-26 13:38:31 +01:00
parent 9e9fc9fb52
commit 60f5f8370c
5 changed files with 90 additions and 14 deletions
@@ -31,7 +31,10 @@
RefreshCw,
Save,
Smartphone,
FileClock
FileClock,
Sun,
Moon,
SunMoon
} from 'lucide-svelte'
import { createEventDispatcher, getContext } from 'svelte'
import { Pane, Splitpanes } from 'svelte-splitpanes'
@@ -140,7 +143,8 @@
staticExporter,
errorByComponent,
openDebugRun,
mode
mode,
darkMode
} = getContext<AppViewerContext>('AppViewerContext')
const { history, jobsDrawerOpen, refreshComponents } =
@@ -199,7 +203,7 @@
async function computeTriggerables() {
const items = allItems($app.grid, $app.subgrids)
console.log('items', items)
console.debug('items', items)
const allTriggers: ([string, TriggerableV2] | undefined)[] = (await Promise.all(
items
@@ -428,12 +432,14 @@
savedApp &&
$app &&
orderedJsonStringify(deployedValue) ===
orderedJsonStringify(replaceFalseWithUndefined({
summary: $summary,
value: $app,
path: newPath || savedApp.draft?.path || savedApp.path,
policy
}))
orderedJsonStringify(
replaceFalseWithUndefined({
summary: $summary,
value: $app,
path: newPath || savedApp.draft?.path || savedApp.path,
policy
})
)
) {
await updateApp(npath)
} else {
@@ -867,6 +873,21 @@
}
const dispatch = createEventDispatcher()
function setTheme(newDarkMode: boolean | undefined) {
if (
newDarkMode === true ||
(newDarkMode === null && window.localStorage.getItem('dark-mode') === 'dark')
) {
document.documentElement.classList.add('dark')
} else if (newDarkMode === false) {
document.documentElement.classList.remove('dark')
}
$darkMode = newDarkMode ?? false
}
let priorDarkMode = document.documentElement.classList.contains('dark')
setTheme($app?.darkMode)
</script>
<svelte:window on:keydown={onKeyDown} />
@@ -881,6 +902,9 @@
path: newPath || savedApp?.draft?.path || savedApp?.path,
policy
}}
additionalExitAction={() => {
setTheme(priorDarkMode)
}}
/>
<DeployOverrideConfirmationModal
@@ -1435,6 +1459,34 @@
/>
</ToggleButtonGroup>
{/if}
{#if $app}
<ToggleButtonGroup
class="h-[30px]"
on:selected={(e) => {
setTheme(e.detail)
}}
bind:selected={$app.darkMode}
>
<ToggleButton
icon={SunMoon}
value={undefined}
tooltip="The app mode between dark/light is automatic"
iconProps={{ size: 16 }}
/>
<ToggleButton
icon={Sun}
value={false}
tooltip="Force light mode"
iconProps={{ size: 16 }}
/>
<ToggleButton
tooltip="Force dark mode"
icon={Moon}
value={true}
iconProps={{ size: 16 }}
/>
</ToggleButtonGroup>
{/if}
<div class="flex flex-row gap-2">
<ToggleButtonGroup class="h-[30px]" bind:selected={$breakpoint}>
<ToggleButton
@@ -1,5 +1,5 @@
<script lang="ts">
import { getContext, setContext } from 'svelte'
import { getContext, onDestroy, setContext } from 'svelte'
import { get, writable, type Writable } from 'svelte/store'
import { buildWorld } from '../rx'
import type {
@@ -73,7 +73,26 @@
resizeWindow()
const parentWidth = writable(0)
const darkMode: Writable<boolean> = writable(document.documentElement.classList.contains('dark'))
let previousDarkMode = document.documentElement.classList.contains('dark')
const darkMode: Writable<boolean> = writable(app?.darkMode ?? previousDarkMode)
onDestroy(() => {
setTheme(previousDarkMode)
})
function setTheme(darkMode: boolean | undefined) {
if (
darkMode === true ||
(darkMode === null && window.localStorage.getItem('dark-mode') === 'dark')
) {
document.documentElement.classList.add('dark')
} else if (darkMode === false) {
document.documentElement.classList.remove('dark')
}
}
setTheme($darkMode)
const state = writable({})
@@ -156,9 +175,11 @@
? 'max-w-[640px]'
: 'w-full min-w-[768px]'
$: lockedClasses = isLocked ? '!max-h-[400px] overflow-hidden pointer-events-none' : ''
function onThemeChange() {
$darkMode = document.documentElement.classList.contains('dark')
$darkMode = app?.darkMode ?? document.documentElement.classList.contains('dark')
}
const cssId = 'wm-global-style'
let css: string | undefined = undefined
@@ -148,6 +148,7 @@ export type AppTheme =
export type App = {
grid: GridItem[]
darkMode?: boolean
fullscreen: boolean
norefreshbar?: boolean
unusedInlineScripts: Array<{
@@ -16,6 +16,7 @@
export let savedValue: Value | undefined = undefined
export let modifiedValue: Value | undefined = undefined
export let diffDrawer: DiffDrawer | undefined = undefined
export let additionalExitAction: () => void = () => {}
let bypassBeforeNavigate = false
let open = false
@@ -46,6 +47,7 @@
orderedJsonStringify(replaceFalseWithUndefined(current))
) {
bypassBeforeNavigate = true
additionalExitAction?.()
gotoUrl(goingTo)
} else {
open = true
@@ -69,6 +71,7 @@
on:confirmed={() => {
if (goingTo) {
bypassBeforeNavigate = true
additionalExitAction?.()
gotoUrl(goingTo)
}
}}
@@ -98,6 +101,7 @@
onClick: () => {
if (goingTo) {
bypassBeforeNavigate = true
additionalExitAction?.()
gotoUrl(goingTo)
}
}
@@ -117,8 +117,6 @@
sendUserToast(argError, true)
}
console.log(schema);
dispatch('change', schema)
}