trueshade
Reactive icon

TrueShade

Stable version 1.5.1 (Compatible with OutSystems 11)
Uploaded
 on 9 Jun (yesterday)
 by 
5.0
 (9 ratings)
trueshade

TrueShade

Details
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.
Read more

TrueShade — Dark / Light / System theme engine for OutSystems


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.


What it does

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.


Key features

  • Three theme modes: system-default, dark, light.
  • OS integration: when set to system-default, it auto-follows the operating system's dark/light mode and reacts the instant the user changes it.
  • Per-module persistence: the preference is saved in localStorage under $OS_<ModuleName>$layout-theme — or under a name you choose, so several front-ends can share one preference (see Initialize).
  • Cross-tab & cross-window sync: uses BroadcastChannel where available, with an automatic storage-event fallback for older browsers — no tab is ever left out of sync.
  • Real-time subscriptions: Theme.OnChange(cb) notifies you of every change with both the resolved theme and the raw preference; pass { immediate: true } to also get the current value on subscribe.
  • Clean lifecycle: Initialize() wires everything up; Dispose() removes every listener (without clearing the saved preference).
  • Tiny & self-contained: no dependencies, no framework, strict-mode JavaScript.


Quick start

// 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 */ }

API

  • Initialize(appName?) — start the engine; optional shared name for the storage key.
  • GetLayoutColorScheme() — the effective theme: 'dark' or 'light'.
  • GetStoredLayoutColorScheme() — the raw preference: 'system-default', 'dark', or 'light'.
  • SetLayoutColorScheme(mode) — set and apply a preference.
  • OnChange(cb, { immediate }) — subscribe; returns an unsubscribe function.
  • GetStorageKey() — the resolved localStorage key (handy for the snippet below).
  • Dispose() — tear down listeners.


Recommended: prevent the theme flash (FOUC)

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():

<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>

Requirements & notes

  • Provides the logic and sync layer only — dark/light CSS is yours to define.
  • Browser-based; uses localStorage and matchMedia (with legacy-Safari fallbacks).
  • No external dependencies.
Release notes (1.5.1)

New

  • GetStorageKey() client action — returns the localStorage key TrueShade uses to persist the theme preference for the current module ($layout-theme, or the derived $OS_$layout-theme). Useful for debugging or for reading the stored value directly in an anti-FOUC script. Backed by a new TrueShade.Theme.GetStorageKey() function.


Improved

  • The theme-change callback now exposes both values. The block's OnChange_Theme handler signature changed from (Raw) to (Effective, Raw). Consumers now receive both the effective theme (resolved light/dark — e.g. after applying the system preference) and the raw user selection (which may be system-default). This is backed by the underlying OnChange now delivering both arguments.
  • Initialization is idempotent and self-syncing. On Ready now unsubscribes any pre-existing listener before re-subscribing (preventing duplicate listeners on re-render / re-initialization) and subscribes with { immediate: true }, so the handler runs once on load to sync the initial theme.
  • Safe load when matchMedia is unavailable. The script no longer throws at load in environments that lack window.matchMedia (old/stripped webviews, some test harnesses). It degrades gracefully to light, with OS reactivity disabled; persistence, manual selection, and cross-tab sync still work.
  • Immutable configuration. The script's internal config constants are now frozen, preventing accidental runtime mutation.


Migration / Breaking

  • OnChange_Theme is a breaking signature change ((Raw) → (Effective, Raw)). Any block or screen that binds or overrides this handler must be updated to the two-parameter form.
  • Argument order matters: the first parameter is now the effective theme (resolved light/dark), whereas the old single argument was the raw value. Logic that relied on that one argument as the user's selection should now read the second parameter (Raw). Review and rebind accordingly.
License (1.5.1)
Reviews (1)
by 
2025-08-25
in version 1.1.0
Powerful engine for effortless theme management.
Team
Other assets in this category