trueshade
Reactive icon

TrueShade

Stable version 1.1.1 (Compatible with OutSystems 11)
Uploaded
 on 4 Sep (11 days ago)
 by 
5.0
 (5 ratings)
trueshade

TrueShade

Documentation
1.1.1
Overview
TrueShade is a lightweight, dependency-free JavaScript module designed to manage UI color schemes (dark/light modes) for web applications. It persists user theme preferences in localStorage, applies them to the <html> element via the data-theme attribute, and responds to system color scheme changes. The module supports three theme modes: system-default, dark, and light.
Purpose
  • Manage UI Themes: Seamlessly switch between dark and light modes based on user preference or system settings.
  • Persistence: Store theme preferences in localStorage using a module-specific key.
  • System Integration: React to OS-level color scheme changes via prefers-color-scheme.
  • Cross-Tab Sync: Use BroadcastChannel for theme synchronization across tabs.
  • Event-Driven: Notify subscribers of theme changes via a callback system.
Key Features
  • Idempotent Lifecycle: Safe initialization and disposal without side effects.
  • Theme Persistence: Stores preferences under a module-specific key ($OS_<name>$layout-theme).
  • System Default Support: Resolves system-default to the OS’s current color scheme.
  • Minimal Footprint: No external dependencies, optimized for performance.
  • Error Resilience: Handles storage errors gracefully (e.g., in privacy modes).
  • Event Subscription: Allows components to react to theme changes dynamically.
Installation
Install TrueShade from the OutSystems Forge here.
Usage
Initialization

To set up the theme system, you can choose one of two approaches:

  • Manual setup
    • Run the client action Initialize in the On Ready event of your application’s Layout Block.
    • In the On Destroy event, call the client action Dispose to remove all listeners and clean up broadcasts and variables.
  • Simpler setup
    • Add the TrueShade Block directly to your Layout Block.
    • This automatically handles initialization and disposal without requiring extra logic.
Getting the Current Theme

Retrieve the effective theme (dark or light):

Client Action: GetLayoutColorScheme

Retrieve the raw stored preference (dark, light or system-default):

Client Action: GetStoredLayoutColorScheme
Setting a Theme

Set and persist a new theme (dark, light or system-default):

Client Action: SetLayoutColorScheme

Invalid theme values are rejected with a console error.

Subscribing to Theme Changes

Register a callback to handle theme changes (receives dark or light):

const unsubscribe = TrueShade.Theme.OnChange((effectiveTheme) => {
  console.log('Theme changed to:', effectiveTheme);
});
// Later, to unsubscribe:
unsubscribe();
Clean Up

Dispose of the module to remove event listeners (does not clear stored preference):

TrueShade.Theme.Dispose();
API Reference
TrueShade.Theme.Initialize()
  • Purpose: Initializes the theme system (idempotent).
  • Behavior:
    • Seeds localStorage with system-default if no preference exists.
    • Applies the current theme to <html data-theme>.
    • Sets up listeners for OS color scheme changes and cross-tab updates.
  • Returns: void
TrueShade.Theme.GetLayoutColorScheme()
  • Purpose: Returns the effective theme (dark or light).
  • Behavior: Resolves system-default to the current OS preference.
  • Returns: 'dark' | 'light'
TrueShade.Theme.GetStoredLayoutColorScheme()
  • Purpose: Returns the raw stored theme preference.
  • Behavior: Ensures the preference is seeded, returning system-default if unset.
  • Returns: 'system-default' | 'dark' | 'light'
TrueShade.Theme.SetLayoutColorScheme(theme)
  • Purpose: Sets and persists a new theme.
  • Parameters:
    • theme: 'system-default' | 'dark' | 'light'
  • Behavior:
    • Validates the input theme; logs an error for invalid values.
    • Persists to localStorage and applies to <html data-theme>.
    • Notifies subscribers and other tabs via BroadcastChannel.
  • Returns: void
TrueShade.Theme.Dispose()
  • Purpose: Cleans up resources (idempotent).
  • Behavior:
    • Removes OS and channel event listeners.
    • Clears internal listener array.
    • Preserves stored preference.
  • Returns: void
TrueShade.Theme.OnChange(callback)
  • Purpose: Subscribes to theme change events.
  • Parameters:
    • callback: (effective: string) => void - Receives 'dark' or 'light'.
  • Behavior: Adds the callback to the listener list; does not fire immediately.
  • Returns: () => void - Unsubscribe function.
Internal Mechanics
Storage Key
  • Format: $OS_<moduleName>$layout-theme
  • moduleName: Derived from the URL’s pathname (first segment) or hostname (first label), wrapped as $OS_<name>$.
  • Example: For https://example.com/app, the key might be $OS_app$layout-theme.
Theme Modes
  • system-default: Resolves to the OS’s prefers-color-scheme (dark or light).
  • dark: Forces dark mode.
  • light: Forces light mode.
Event Handling
  • OS Changes: Listens to prefers-color-scheme changes via window.matchMedia. Updates the theme only if the preference is system-default.
  • Cross-Tab Sync: Uses BroadcastChannel (if available) to synchronize theme changes across tabs.
  • Local Listeners: Notifies registered callbacks with the effective theme (dark or light) on changes.
Error Handling
  • Ignores localStorage errors (e.g., in privacy modes) and falls back to system-default.
  • Swallows listener and channel errors to ensure stability.
  • Validates theme inputs to prevent invalid states.
Notes
  • No Dependencies: Works in any modern browser without external libraries.
  • Performance: Minimizes DOM updates and allocations (e.g., caches storage keys).
  • Privacy: Gracefully handles localStorage restrictions.
  • Extensibility: The onChange system allows easy integration with UI frameworks.
Limitations
  • Requires modern browser support for window.matchMedia and BroadcastChannel (falls back gracefully if unavailable).
  • Does not clear localStorage on Dispose to preserve user preferences.
  • Theme application is limited to the <html data-theme> attribute; custom styling must be implemented via CSS.

1.1.0
Overview
TrueShade is a lightweight, dependency-free JavaScript module designed to manage UI color schemes (dark/light modes) for web applications. It persists user theme preferences in localStorage, applies them to the <html> element via the data-theme attribute, and responds to system color scheme changes. The module supports three theme modes: system-defaultdark, and light.
Purpose
  • Manage UI Themes: Seamlessly switch between dark and light modes based on user preference or system settings.
  • Persistence: Store theme preferences in localStorage using a module-specific key.
  • System Integration: React to OS-level color scheme changes via prefers-color-scheme.
  • Cross-Tab Sync: Use BroadcastChannel for theme synchronization across tabs.
  • Event-Driven: Notify subscribers of theme changes via a callback system.
Key Features
  • Idempotent Lifecycle: Safe initialization and disposal without side effects.
  • Theme Persistence: Stores preferences under a module-specific key ($OS_<name>$layout-theme).
  • System Default Support: Resolves system-default to the OS’s current color scheme.
  • Minimal Footprint: No external dependencies, optimized for performance.
  • Error Resilience: Handles storage errors gracefully (e.g., in privacy modes).
  • Event Subscription: Allows components to react to theme changes dynamically.
Installation
Install TrueShade from the OutSystems Forge here.
Usage
Initialization

To set up the theme system, you can choose one of two approaches:

  • Manual setup
    • Run the client action Initialize in the On Ready event of your application’s Layout Block.
    • In the On Destroy event, call the client action Dispose to remove all listeners and clean up broadcasts and variables.
  • Simpler setup
    • Add the TrueShade Block directly to your Layout Block.
    • This automatically handles initialization and disposal without requiring extra logic.
Getting the Current Theme

Retrieve the effective theme (dark or light):

Client Action: GetLayoutColorScheme

Retrieve the raw stored preference (darklight or system-default):

Client Action: GetStoredLayoutColorScheme
Setting a Theme

Set and persist a new theme (darklight or system-default):

Client Action: SetLayoutColorScheme

Invalid theme values are rejected with a console error.

Subscribing to Theme Changes

Register a callback to handle theme changes (receives dark or light):

const unsubscribe = TrueShade.Theme.OnChange((effectiveTheme) => {
  console.log('Theme changed to:', effectiveTheme);
});
// Later, to unsubscribe:
unsubscribe();
Clean Up

Dispose of the module to remove event listeners (does not clear stored preference):

TrueShade.Theme.Dispose();
API Reference
TrueShade.Theme.Initialize()
  • Purpose: Initializes the theme system (idempotent).
  • Behavior:
    • Seeds localStorage with system-default if no preference exists.
    • Applies the current theme to <html data-theme>.
    • Sets up listeners for OS color scheme changes and cross-tab updates.
  • Returnsvoid
TrueShade.Theme.GetLayoutColorScheme()
  • Purpose: Returns the effective theme (dark or light).
  • Behavior: Resolves system-default to the current OS preference.
  • Returns'dark' | 'light'
TrueShade.Theme.GetStoredLayoutColorScheme()
  • Purpose: Returns the raw stored theme preference.
  • Behavior: Ensures the preference is seeded, returning system-default if unset.
  • Returns'system-default' | 'dark' | 'light'
TrueShade.Theme.SetLayoutColorScheme(theme)
  • Purpose: Sets and persists a new theme.
  • Parameters:
    • theme'system-default' | 'dark' | 'light'
  • Behavior:
    • Validates the input theme; logs an error for invalid values.
    • Persists to localStorage and applies to <html data-theme>.
    • Notifies subscribers and other tabs via BroadcastChannel.
  • Returnsvoid
TrueShade.Theme.Dispose()
  • Purpose: Cleans up resources (idempotent).
  • Behavior:
    • Removes OS and channel event listeners.
    • Clears internal listener array.
    • Preserves stored preference.
  • Returnsvoid
TrueShade.Theme.OnChange(callback)
  • Purpose: Subscribes to theme change events.
  • Parameters:
    • callback(effective: string) => void - Receives 'dark' or 'light'.
  • Behavior: Adds the callback to the listener list; does not fire immediately.
  • Returns() => void - Unsubscribe function.
Internal Mechanics
Storage Key
  • Format$OS_<moduleName>$layout-theme
  • moduleName: Derived from the URL’s pathname (first segment) or hostname (first label), wrapped as $OS_<name>$.
  • Example: For https://example.com/app, the key might be $OS_app$layout-theme.
Theme Modes
  • system-default: Resolves to the OS’s prefers-color-scheme (dark or light).
  • dark: Forces dark mode.
  • light: Forces light mode.
Event Handling
  • OS Changes: Listens to prefers-color-scheme changes via window.matchMedia. Updates the theme only if the preference is system-default.
  • Cross-Tab Sync: Uses BroadcastChannel (if available) to synchronize theme changes across tabs.
  • Local Listeners: Notifies registered callbacks with the effective theme (dark or light) on changes.
Error Handling
  • Ignores localStorage errors (e.g., in privacy modes) and falls back to system-default.
  • Swallows listener and channel errors to ensure stability.
  • Validates theme inputs to prevent invalid states.
Notes
  • No Dependencies: Works in any modern browser without external libraries.
  • Performance: Minimizes DOM updates and allocations (e.g., caches storage keys).
  • Privacy: Gracefully handles localStorage restrictions.
  • Extensibility: The onChange system allows easy integration with UI frameworks.
Limitations
  • Requires modern browser support for window.matchMedia and BroadcastChannel (falls back gracefully if unavailable).
  • Does not clear localStorage on Dispose to preserve user preferences.
  • Theme application is limited to the <html data-theme> attribute; custom styling must be implemented via CSS.

1.0.2

Lightweight JavaScript utility to manage Dark / Light / System-default theme in OutSystems apps.

It works by toggling the <html data-theme> attribute and persisting the user’s choice (per module) in localStorage.



Highlights

  • Modes: system-default | dark | light

  • Auto-follows OS dark mode when set to system-default

  • Per-module key: $OS_<ModuleName>$layout-theme

  • Minimal DOM writes & zero external dependencies

  • Safe no-op if localStorage is unavailable

  • Public API exposed under TrueShade.Theme.*




Use Cases


  • Consistent Dark / Light theme switching across screens

  • Respect user’s OS preference unless explicitly overridden

  • Cross-tab synchronization via storage event




Installation


  1. Install the asset from the Forge.

  2. Call the Initialize client action in your Layout’s OnReady event.




Example of Minimal CSS (add to Theme)


html[data-theme="dark"] {

  color-scheme: dark;

  background: #111;

  color: #eee;

}


html[data-theme="light"] {

  color-scheme: light;

  background: #fff;

  color: #111;

}




Public APIs


  • TrueShade.Theme.Initialize()

  • TrueShade.Theme.GetLayoutColorScheme()

  • TrueShade.Theme.GetStoredLayoutColorScheme()

  • TrueShade.Theme.SetLayoutColorScheme(mode)

  • TrueShade.Theme.Dispose()




Behavior Details


  • Initialize()

    Idempotent. Seeds localStorage with system-default if absent, applies theme, attaches listeners for OS changes and storage events.

  • GetLayoutColorScheme()

    Returns the effective mode. If stored value is system-default, it resolves to the current OS mode (dark or light).

  • GetStoredLayoutColorScheme()

    Returns the literal stored string or null (before initialization).

  • SetLayoutColorScheme(mode)

    Accepts only system-default | dark | light. Logs console.error on invalid input.

  • Dispose()

    Removes listeners; does not delete stored preference.




Storage Key Format


  • Computed key: $OS_<ModuleName>$layout-theme


Where ModuleName is derived as follows:

  • First non-empty path segment (e.g. /Sales/Home → Sales)

  • Else first hostname label (e.g. admin.example.com → admin)

  • If empty, fallback ⇒ layout-theme




DOM Contract


  • <html data-theme="dark|light"> is always kept in sync.

  • When user selects system-default, the attribute automatically tracks OS changes.




1.0.1

TrueShade Theme Controller

Lightweight JavaScript utility to manage Dark / Light / OS‑default theme in OutSystems apps by toggling the <html data-theme> attribute and persisting the user choice (per module) in localStorage.


Highlights
   •   Modes: os-default | dark | light
   •   Auto-follows OS dark mode when set to os-default
   •   Per‑module key: $OS_<ModuleName>$layout-theme
   •   Minimal DOM writes & zero external dependencies
   •   Safe no-op if localStorage unavailable
   •   Public API exposed under TrueShade.Theme.*


Use Cases
   •   Consistent dark / light theme switching across screens
   •   Respect user’s OS preference unless explicitly overridden
   •   Cross‑tab synchronization (storage event)


Installation

  1. Install the asset from the forge.
  2. Call the Initialize client action in your Layout's OnReady event.


Minimal CSS (place in Theme)

html[data-theme="dark"] {

  color-scheme: dark;

  background: #111;

  color: #eee;

}

html[data-theme="light"] {

  color-scheme: light;

  background: #fff;

  color: #111;

}


Public APIs

TrueShade.Theme.Initialize()

TrueShade.Theme.GetLayoutColorScheme()

TrueShade.Theme.GetStoredLayoutColorScheme()

TrueShade.Theme.SetLayoutColorScheme(ThemeId)

TrueShade.Theme.Dispose()


Behavior Details

Initialize(): Idempotent. Seeds localStorage with os-default if absent, applies theme, attaches listeners for OS changes + storage.

GetLayoutColorScheme(): Returns the effective mode; if stored is os-default it resolves to current OS (dark or light).

GetStoredLayoutColorScheme(): Returns literal stored string or null (before initialization seed).

SetLayoutColorScheme(mode): Accepts only os-default | dark | light; invalid logs console.error.

Dispose(): Removes listeners; does not delete stored preference.

Storage Key Format

Computed key: $OS_<ModuleName>$layout-theme


ModuleName is derived:

  1. First non-empty path segment (e.g. /Sales/Home → Sales)
  2. Else first hostname label (admin.example.com → admin)
  3. Empty fallback ⇒ plain layout-theme


DOM Contract

<html data-theme="dark|light"> is maintained. When user selects os-default the attribute auto tracks OS changes.


1.0.0

TrueShade Theme Controller

Lightweight JavaScript utility to manage Dark / Light / OS‑default theme in OutSystems apps by toggling the <html data-theme> attribute and persisting the user choice (per module) in localStorage.


Highlights
   •   Modes: os-default | dark | light
   •   Auto-follows OS dark mode when set to os-default
   •   Per‑module key: $OS_<ModuleName>$layout-theme
   •   Minimal DOM writes & zero external dependencies
   •   Safe no-op if localStorage unavailable
   •   Public API exposed under TrueShade.Theme.*


Use Cases
   •   Consistent dark / light theme switching across screens
   •   Respect user’s OS preference unless explicitly overridden
   •   Cross‑tab synchronization (storage event)


Installation

  1. Install the asset from the forge.
  2. Call the Initialize client action in your Layout's OnReady event.


Minimal CSS (place in Theme)

html[data-theme="dark"] {

  color-scheme: dark;

  background: #111;

  color: #eee;

}

html[data-theme="light"] {

  color-scheme: light;

  background: #fff;

  color: #111;

}


Public APIs

TrueShade.Theme.Initialize()

TrueShade.Theme.GetLayoutColorScheme()

TrueShade.Theme.GetStoredLayoutColorScheme()

TrueShade.Theme.SetLayoutColorScheme(ThemeId)

TrueShade.Theme.Dispose()


Behavior Details

Initialize(): Idempotent. Seeds localStorage with os-default if absent, applies theme, attaches listeners for OS changes + storage.

GetLayoutColorScheme(): Returns the effective mode; if stored is os-default it resolves to current OS (dark or light).

GetStoredLayoutColorScheme(): Returns literal stored string or null (before initialization seed).

SetLayoutColorScheme(mode): Accepts only os-default | dark | light; invalid logs console.error.

Dispose(): Removes listeners; does not delete stored preference.

Storage Key Format

Computed key: $OS_<ModuleName>$layout-theme


ModuleName is derived:

  1. First non-empty path segment (e.g. /Sales/Home → Sales)
  2. Else first hostname label (admin.example.com → admin)
  3. Empty fallback ⇒ plain layout-theme


DOM Contract

<html data-theme="dark|light"> is maintained. When user selects os-default the attribute auto tracks OS changes.