Lightweight, dependency-free JavaScript utility that manages Dark, Light, and System-default themes — it owns the logic, persistence, and cross-tab sync so you only have to write your styles.
Heads up: TrueShade handles the theme logic and synchronization — it does not ship dark/light CSS. You bring your own styles, keyed off the <html data-theme="dark|light"> attribute that TrueShade sets for you.
<html data-theme="dark|light">
TrueShade stores the user's theme preference per module, resolves system-default to the live OS setting, applies the result to <html data-theme>, and keeps every open tab in sync. Drop it in and it runs automatically.
system-default
<html data-theme>
dark
light
localStorage
$OS_<ModuleName>$layout-theme
Initialize
BroadcastChannel
storage
Theme.OnChange(cb)
{ immediate: true }
Initialize()
Dispose()
// Run once on app load (use a shared name if multiple modules should share the preference) TrueShade.Theme.Initialize('MyApp'); // Let the user switch TrueShade.Theme.SetLayoutColorScheme('dark'); // 'system-default' | 'dark' | 'light' // React to changes (effective = 'dark'|'light', raw = stored preference) TrueShade.Theme.OnChange(function (effective, raw) { console.log('Theme is now', effective, '(' + raw + ')'); }, { immediate: true });
Then style your app against the attribute TrueShade sets:
:root[data-theme="dark"] { /* your dark variables */ } :root[data-theme="light"] { /* your light variables */ }
Initialize(appName?)
GetLayoutColorScheme()
'dark'
'light'
GetStoredLayoutColorScheme()
'system-default'
SetLayoutColorScheme(mode)
OnChange(cb, { immediate })
GetStorageKey()
Add this synchronous snippet in your page <head>, before any stylesheet, so the correct theme is painted on first render. Replace MyApp with the name you pass to Initialize():
<head>
MyApp
<script> (function () { try { var raw = localStorage.getItem('MyApp$layout-theme') || 'system-default'; var dark = raw === 'dark' || (raw === 'system-default' && matchMedia('(prefers-color-scheme: dark)').matches); document.documentElement.dataset.theme = dark ? 'dark' : 'light'; } catch (e) { document.documentElement.dataset.theme = 'light'; } })(); </script>
matchMedia
New
$layout-theme
$OS_$layout-theme
TrueShade.Theme.GetStorageKey()
Improved
OnChange_Theme
(Raw)
(Effective, Raw)
OnChange
window.matchMedia
Migration / Breaking
Raw