Dark Mode

DarkMode is a standalone dark mode manager that handles theme switching, persistent state, system preference sync, and custom toggle support. The theme is applied through the fa-theme="dark" attribute on the root element — the CSS handles visual output while DarkMode manages interaction and storage automatically.

DarkMode is suited for any application that needs a reliable, accessible, and React-compatible dark mode system without third-party dependencies.


Getting Started

Import DarkMode and create an instance. By default, a toggle button is auto-created and appended to body.

import {DarkMode} from 'frontalign';
const darkMode = new DarkMode();

After the instance is created, DarkMode restores the saved theme from localStorage, syncs with the system preference if no saved value exists, and activates the toggle button.

Structure

DarkMode applies the theme directly to document.documentElement using a data attribute.

ElementClass / attributePurpose
Rootdocument.documentElementReceives the fa-theme="dark" attribute when dark mode is active.
Theme attributefa-theme="dark"Marks dark mode as active on the HTML root element.
Toggle buttondark-mode-togglerAuto-created label element that wraps the checkbox input and icon track.
Fixed modifieris-fixedPositions the auto-created toggle button in a fixed corner when container is body.
Custom button stateis-darkApplied to a custom toggle button when dark mode is active.
Storage keydarkModeKey used in localStorage to persist the theme preference.

Basic Example

const darkMode = new DarkMode({
          container: '.darkmode-toggler-container',
          autoCreateBtn: true,
        });

This creates a toggle button appended to body and immediately restores the saved or system-preferred theme.

Configuration Options

DarkMode accepts an options object in the constructor.

OptionDefaultDescription
container'body'CSS selector for the element the auto-created toggle button is appended to.
customBtnfalseCSS selector for an existing button element to use as the toggle trigger instead of the auto-created one.
autoCreateBtntrueWhen true, DarkMode creates and appends the default toggle button. Set to false when using a custom button.

Custom Toggle Button

Set autoCreateBtn: false and pass a customBtn selector to wire DarkMode to an existing element in your markup.

<button id="my-toggle">Toggle Dark Mode</button>
{
  autoCreateBtn: false,
  customBtn: '#my-toggle'
};

DarkMode adds the is-dark class to the custom button when dark mode is active and removes it when switched back to light mode.

Custom Container

By default the auto-created toggle button is appended to body and positioned in a fixed corner. Pass a container selector to mount it inside a specific element instead.

{
  container: '#header-controls'
};

onChange Callback

Use onChange to run a function whenever the theme changes. The callback receives a boolean: true for dark, false for light.


const darkMode = new DarkMode();

darkMode.onChange((isDark) => {
  console.log(isDark ? 'Dark mode on' : 'Light mode on');
});

Multiple callbacks can be registered. All registered callbacks are called on each toggle.

darkModeChange Event

In addition to the onChange callback, DarkMode dispatches a native CustomEvent on document.documentElement after every theme change.

EventDispatched onDetail
darkModeChangedocument.documentElement
document.documentElement.addEventListener('darkModeChange', (event) => {
  console.log('Theme changed. Dark:', event.detail.isDark);
});

isDark Method

Call isDark() on the instance to read the current theme state at any time.

const darkMode = new DarkMode();

if (darkMode.isDark()) {
  console.log('Currently in dark mode');
}

System Preference Sync

When no value is stored in localStorage, DarkMode automatically matches the system preference via window.matchMedia('(prefers-color-scheme: dark)').

ConditionBehavior
No saved preferenceApplies the current system preference on initialization.
System preference changesFollows the new system preference if no manual override is stored.
Saved preference existsIgnores system preference changes and preserves the stored value.

Once the user manually toggles the theme, localStorage is updated and system sync is paused.

Storage Behavior

DarkMode reads and writes to localStorage using the key darkMode.

Stored valueMeaning
"enabled"Dark mode is explicitly enabled by the user.
"disabled"Light mode is explicitly set by the user.
nullNo manual preference — system preference is followed.

Dispose

Call dispose() to remove all event listeners, the auto-created toggle button, and all registered callbacks.

const darkMode = new DarkMode();

// Later, when cleanup is needed:
darkMode.dispose();

dispose() is required in environments where components are mounted and unmounted, such as single-page applications and React components.

Runtime Behavior

BehaviorDescription
SSR safeThe constructor exits early when window or document is not available.
Theme attributeDark mode is toggled by setting or removing fa-theme="dark" on document.documentElement.
PersistenceTheme choice is written to localStorage on every toggle.
System syncFollows prefers-color-scheme until the user makes a manual selection.
Custom eventDispatches darkModeChange on the root element after every toggle.
Multiple callbacksAny number of onChange listeners can be registered on a single instance.

Accessibility

The auto-created toggle button uses a <label> wrapping a checkbox <input> with appropriate ARIA attributes.

  • The input carries role="switch" and an aria-label.
  • The label carries aria-label="Dark Mode Toggle Button".
  • Sun and moon icons use aria-hidden="true" to stay out of the accessibility tree.

When using a customBtn, add descriptive text or an accessible label to the button element yourself.

<button id="theme-toggle" aria-label="Toggle dark mode">
  Dark Mode
</button>

Class Reference

ClassRole
dark-mode-togglerRoot label element wrapping the checkbox and icon track.
is-fixedFixed-position modifier applied when container is body.
dark-mode-toggler-trackThe visual track element of the toggle button.
dark-mode-toggler-thumbThe sliding thumb element inside the track.
dark-mode-toggler-sunSun icon shown in light mode.
dark-mode-toggler-moonMoon icon shown in dark mode.
is-darkState class applied to the custom button when dark mode is active.

Notes

  • DarkMode requires no markup changes — only a JavaScript import.
  • The fa-theme="dark" attribute on <html> drives all CSS theming.
  • Call dispose() when the instance is no longer needed to prevent memory leaks.
  • Use autoCreateBtn: false whenever you supply a customBtn selector.
  • onChange callbacks and the darkModeChange event both fire on every toggle and on system preference changes when no saved value exists.
  • Use the React hook only in React or Next.js applications.
  • Continue with the React Integration guide for provider setup and runtime helpers.

FrontAlign