I’ll build this as a standalone advanced dark-mode chunk for RX Theme, designed to work safely even before the rest of your theme is finished. It will include system preference detection, localStorage, buttons/toggles, keyboard support, meta theme-color updates, CSS variable hooks, accessibility, and WordPress-friendly events.
Yes my dear friend — create this file:
assets/static-js/static-chunks-js/chunk-005-dark-mode.js
Paste this full advanced code inside it.
/*!
* RX Theme - Advanced Dark Mode Chunk
* File: assets/static-js/static-chunks-js/chunk-005-dark-mode.js
*
* Purpose:
* - Advanced dark / light / system theme controller
* - WordPress theme friendly
* - LocalStorage support
* - System preference support
* - Accessible buttons and toggles
* - Meta theme-color update
* - CSS variable friendly
* - Custom events for future RX Theme modules
*
* Required CSS idea:
* html[data-rx-theme="dark"] { color-scheme: dark; }
* html[data-rx-theme="light"] { color-scheme: light; }
*/
(function RXDarkModeChunk(window, document) {
'use strict';
if (!window || !document) return;
/**
* Prevent duplicate loading.
*/
if (window.RX_DARK_MODE_CHUNK_LOADED) {
return;
}
window.RX_DARK_MODE_CHUNK_LOADED = true;
/**
* Main namespace.
*/
var RX = window.RXTheme || {};
window.RXTheme = RX;
/**
* Configuration.
*/
var CONFIG = {
storageKey: 'rx-theme-color-mode',
previousStorageKey: 'rx-theme-previous-color-mode',
defaultMode: 'system',
allowedModes: ['light', 'dark', 'system'],
htmlAttribute: 'data-rx-theme',
htmlModeAttribute: 'data-rx-theme-mode',
htmlResolvedAttribute: 'data-rx-theme-resolved',
bodyClassPrefix: 'rx-theme-',
toggleSelector: '[data-rx-dark-toggle]',
buttonSelector: '[data-rx-theme-button]',
selectSelector: '[data-rx-theme-select]',
checkboxSelector: '[data-rx-theme-checkbox]',
iconSelector: '[data-rx-theme-icon]',
labelSelector: '[data-rx-theme-label]',
statusSelector: '[data-rx-theme-status]',
darkClass: 'is-dark-mode',
lightClass: 'is-light-mode',
systemClass: 'is-system-mode',
activeClass: 'is-active',
loadingClass: 'rx-theme-changing',
transitionClass: 'rx-theme-transition',
noTransitionClass: 'rx-theme-no-transition',
metaThemeColorLight: '#ffffff',
metaThemeColorDark: '#0b0f19',
eventPrefix: 'rx:theme:',
transitionDuration: 250,
enableKeyboardShortcut: true,
keyboardShortcutKey: 'd',
keyboardShortcutAlt: true,
keyboardShortcutShift: true,
enableMetaThemeColor: true,
enableColorScheme: true,
enableViewTransition: false,
debug: false
};
/**
* State.
*/
var state = {
initialized: false,
currentMode: CONFIG.defaultMode,
resolvedMode: 'light',
previousMode: null,
mediaQuery: null,
observers: [],
callbacks: {
change: [],
beforeChange: [],
afterChange: []
}
};
/**
* Helpers.
*/
function log() {
if (!CONFIG.debug || !window.console) return;
try {
window.console.log.apply(window.console, ['[RX Dark Mode]'].concat(Array.prototype.slice.call(arguments)));
} catch (error) {}
}
function warn() {
if (!window.console) return;
try {
window.console.warn.apply(window.console, ['[RX Dark Mode]'].concat(Array.prototype.slice.call(arguments)));
} catch (error) {}
}
function isString(value) {
return typeof value === 'string';
}
function normalizeMode(mode) {
if (!isString(mode)) return CONFIG.defaultMode;
mode = mode.toLowerCase().trim();
if (CONFIG.allowedModes.indexOf(mode) !== -1) {
return mode;
}
if (mode === 'auto') return 'system';
if (mode === 'night') return 'dark';
if (mode === 'day') return 'light';
return CONFIG.defaultMode;
}
function isAllowedMode(mode) {
return CONFIG.allowedModes.indexOf(mode) !== -1;
}
function safeLocalStorageGet(key) {
try {
return window.localStorage.getItem(key);
} catch (error) {
return null;
}
}
function safeLocalStorageSet(key, value) {
try {
window.localStorage.setItem(key, value);
return true;
} catch (error) {
return false;
}
}
function safeLocalStorageRemove(key) {
try {
window.localStorage.removeItem(key);
return true;
} catch (error) {
return false;
}
}
function getDocumentElement() {
return document.documentElement;
}
function getBody() {
return document.body;
}
function getSystemPreference() {
if (!window.matchMedia) {
return 'light';
}
try {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
} catch (error) {
return 'light';
}
}
function getMediaQuery() {
if (!window.matchMedia) return null;
if (!state.mediaQuery) {
try {
state.mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
} catch (error) {
state.mediaQuery = null;
}
}
return state.mediaQuery;
}
function resolveMode(mode) {
mode = normalizeMode(mode);
if (mode === 'system') {
return getSystemPreference();
}
return mode;
}
function getStoredMode() {
var stored = safeLocalStorageGet(CONFIG.storageKey);
return normalizeMode(stored || CONFIG.defaultMode);
}
function setStoredMode(mode) {
mode = normalizeMode(mode);
if (mode === CONFIG.defaultMode) {
safeLocalStorageSet(CONFIG.storageKey, mode);
return;
}
safeLocalStorageSet(CONFIG.storageKey, mode);
}
function getInitialMode() {
var html = getDocumentElement();
var attrMode =
html.getAttribute(CONFIG.htmlModeAttribute) ||
html.getAttribute(CONFIG.htmlAttribute);
if (attrMode && isAllowedMode(normalizeMode(attrMode))) {
return normalizeMode(attrMode);
}
return getStoredMode();
}
function createEvent(name, detail) {
var eventName = CONFIG.eventPrefix + name;
try {
return new CustomEvent(eventName, {
bubbles: true,
cancelable: false,
detail: detail || {}
});
} catch (error) {
var event = document.createEvent('CustomEvent');
event.initCustomEvent(eventName, true, false, detail || {});
return event;
}
}
function dispatchThemeEvent(name, detail) {
var event = createEvent(name, detail);
document.dispatchEvent(event);
return event;
}
function runCallbacks(type, payload) {
var list = state.callbacks[type];
if (!list || !list.length) return;
list.forEach(function runCallback(callback) {
try {
callback(payload);
} catch (error) {
warn('Callback error:', error);
}
});
}
function getMetaThemeColor() {
var meta = document.querySelector('meta[name="theme-color"]');
if (!meta) {
meta = document.createElement('meta');
meta.setAttribute('name', 'theme-color');
if (document.head) {
document.head.appendChild(meta);
}
}
return meta;
}
function updateMetaThemeColor(resolvedMode) {
if (!CONFIG.enableMetaThemeColor) return;
var meta = getMetaThemeColor();
if (!meta) return;
var color = resolvedMode === 'dark'
? CONFIG.metaThemeColorDark
: CONFIG.metaThemeColorLight;
meta.setAttribute('content', color);
}
function updateColorScheme(resolvedMode) {
if (!CONFIG.enableColorScheme) return;
var html = getDocumentElement();
try {
html.style.colorScheme = resolvedMode === 'dark' ? 'dark' : 'light';
} catch (error) {}
}
function removeBodyThemeClasses() {
var body = getBody();
if (!body) return;
body.classList.remove(CONFIG.darkClass);
body.classList.remove(CONFIG.lightClass);
body.classList.remove(CONFIG.systemClass);
CONFIG.allowedModes.forEach(function removeModeClass(mode) {
body.classList.remove(CONFIG.bodyClassPrefix + mode);
});
}
function applyBodyClasses(mode, resolvedMode) {
var body = getBody();
if (!body) return;
removeBodyThemeClasses();
body.classList.add(CONFIG.bodyClassPrefix + mode);
if (resolvedMode === 'dark') {
body.classList.add(CONFIG.darkClass);
} else {
body.classList.add(CONFIG.lightClass);
}
if (mode === 'system') {
body.classList.add(CONFIG.systemClass);
}
}
function applyHtmlAttributes(mode, resolvedMode) {
var html = getDocumentElement();
html.setAttribute(CONFIG.htmlModeAttribute, mode);
html.setAttribute(CONFIG.htmlResolvedAttribute, resolvedMode);
/**
* Important:
* data-rx-theme should hold the resolved visual mode.
* Example:
* selected mode = system
* system says dark
* data-rx-theme = dark
*/
html.setAttribute(CONFIG.htmlAttribute, resolvedMode);
}
function setPressedState(element, active) {
if (!element) return;
if (
element.tagName === 'BUTTON' ||
element.getAttribute('role') === 'button' ||
element.hasAttribute('aria-pressed')
) {
element.setAttribute('aria-pressed', active ? 'true' : 'false');
}
}
function setCheckedState(element, checked) {
if (!element) return;
if (element.type === 'checkbox') {
element.checked = !!checked;
}
element.setAttribute('aria-checked', checked ? 'true' : 'false');
}
function getReadableModeLabel(mode, resolvedMode) {
if (mode === 'system') {
return resolvedMode === 'dark'
? 'System dark mode'
: 'System light mode';
}
if (mode === 'dark') return 'Dark mode';
return 'Light mode';
}
function getNextMode(mode) {
mode = normalizeMode(mode);
if (mode === 'light') return 'dark';
if (mode === 'dark') return 'system';
return 'light';
}
function getOppositeResolvedMode() {
return state.resolvedMode === 'dark' ? 'light' : 'dark';
}
function updateIcons(mode, resolvedMode) {
var icons = document.querySelectorAll(CONFIG.iconSelector);
if (!icons || !icons.length) return;
icons.forEach(function updateIcon(icon) {
var iconMode = icon.getAttribute('data-rx-theme-icon');
icon.classList.remove(CONFIG.activeClass);
icon.setAttribute('aria-hidden', 'true');
if (iconMode === mode || iconMode === resolvedMode) {
icon.classList.add(CONFIG.activeClass);
}
if (iconMode === 'dark' && resolvedMode === 'dark') {
icon.classList.add(CONFIG.activeClass);
}
if (iconMode === 'light' && resolvedMode === 'light') {
icon.classList.add(CONFIG.activeClass);
}
if (iconMode === 'system' && mode === 'system') {
icon.classList.add(CONFIG.activeClass);
}
});
}
function updateLabels(mode, resolvedMode) {
var labels = document.querySelectorAll(CONFIG.labelSelector);
var text = getReadableModeLabel(mode, resolvedMode);
if (!labels || !labels.length) return;
labels.forEach(function updateLabel(label) {
var labelType = label.getAttribute('data-rx-theme-label');
if (!labelType || labelType === 'current') {
label.textContent = text;
}
if (labelType === 'next') {
label.textContent = getReadableModeLabel(getNextMode(mode), resolveMode(getNextMode(mode)));
}
if (labelType === 'resolved') {
label.textContent = resolvedMode === 'dark' ? 'Dark' : 'Light';
}
if (labelType === 'selected') {
label.textContent = mode.charAt(0).toUpperCase() + mode.slice(1);
}
});
}
function updateStatus(mode, resolvedMode) {
var statuses = document.querySelectorAll(CONFIG.statusSelector);
var text = getReadableModeLabel(mode, resolvedMode) + ' enabled';
if (!statuses || !statuses.length) return;
statuses.forEach(function updateStatusText(status) {
status.textContent = text;
});
}
function updateButtons(mode, resolvedMode) {
var buttons = document.querySelectorAll(CONFIG.buttonSelector);
if (!buttons || !buttons.length) return;
buttons.forEach(function updateButton(button) {
var buttonMode = normalizeMode(button.getAttribute('data-rx-theme-button'));
var active = buttonMode === mode;
button.classList.toggle(CONFIG.activeClass, active);
setPressedState(button, active);
button.setAttribute('data-rx-active', active ? 'true' : 'false');
button.setAttribute('data-rx-resolved', resolvedMode);
if (!button.getAttribute('aria-label')) {
button.setAttribute('aria-label', 'Set ' + buttonMode + ' mode');
}
});
}
function updateToggles(mode, resolvedMode) {
var toggles = document.querySelectorAll(CONFIG.toggleSelector);
if (!toggles || !toggles.length) return;
toggles.forEach(function updateToggle(toggle) {
var isDark = resolvedMode === 'dark';
toggle.classList.toggle(CONFIG.activeClass, isDark);
toggle.setAttribute('data-rx-active', isDark ? 'true' : 'false');
toggle.setAttribute('data-rx-mode', mode);
toggle.setAttribute('data-rx-resolved', resolvedMode);
setPressedState(toggle, isDark);
if (!toggle.getAttribute('aria-label')) {
toggle.setAttribute('aria-label', 'Toggle dark mode');
}
toggle.setAttribute(
'title',
isDark ? 'Switch theme mode' : 'Switch theme mode'
);
});
}
function updateCheckboxes(mode, resolvedMode) {
var checkboxes = document.querySelectorAll(CONFIG.checkboxSelector);
if (!checkboxes || !checkboxes.length) return;
checkboxes.forEach(function updateCheckbox(checkbox) {
var isDark = resolvedMode === 'dark';
setCheckedState(checkbox, isDark);
checkbox.setAttribute('data-rx-mode', mode);
checkbox.setAttribute('data-rx-resolved', resolvedMode);
});
}
function updateSelects(mode) {
var selects = document.querySelectorAll(CONFIG.selectSelector);
if (!selects || !selects.length) return;
selects.forEach(function updateSelect(select) {
select.value = mode;
});
}
function updateControls(mode, resolvedMode) {
updateButtons(mode, resolvedMode);
updateToggles(mode, resolvedMode);
updateCheckboxes(mode, resolvedMode);
updateSelects(mode);
updateIcons(mode, resolvedMode);
updateLabels(mode, resolvedMode);
updateStatus(mode, resolvedMode);
}
function disableTransitionsTemporarily() {
var html = getDocumentElement();
html.classList.add(CONFIG.noTransitionClass);
window.setTimeout(function removeNoTransition() {
html.classList.remove(CONFIG.noTransitionClass);
}, 50);
}
function addTransitionClass() {
var html = getDocumentElement();
html.classList.add(CONFIG.transitionClass);
html.classList.add(CONFIG.loadingClass);
window.setTimeout(function removeTransitionClass() {
html.classList.remove(CONFIG.loadingClass);
}, CONFIG.transitionDuration);
}
function applyTheme(mode, options) {
options = options || {};
mode = normalizeMode(mode);
var previousMode = state.currentMode;
var previousResolvedMode = state.resolvedMode;
var resolvedMode = resolveMode(mode);
var payload = {
mode: mode,
resolvedMode: resolvedMode,
previousMode: previousMode,
previousResolvedMode: previousResolvedMode,
source: options.source || 'api',
timestamp: Date.now()
};
runCallbacks('beforeChange', payload);
dispatchThemeEvent('before-change', payload);
if (options.disableTransition) {
disableTransitionsTemporarily();
} else {
addTransitionClass();
}
applyHtmlAttributes(mode, resolvedMode);
applyBodyClasses(mode, resolvedMode);
updateMetaThemeColor(resolvedMode);
updateColorScheme(resolvedMode);
updateControls(mode, resolvedMode);
state.previousMode = previousMode;
state.currentMode = mode;
state.resolvedMode = resolvedMode;
if (options.save !== false) {
setStoredMode(mode);
safeLocalStorageSet(CONFIG.previousStorageKey, previousMode);
}
runCallbacks('change', payload);
dispatchThemeEvent('change', payload);
window.setTimeout(function afterChange() {
runCallbacks('afterChange', payload);
dispatchThemeEvent('after-change', payload);
}, CONFIG.transitionDuration);
log('Theme applied:', payload);
return payload;
}
function setMode(mode, options) {
return applyTheme(mode, options || {});
}
function toggleMode(options) {
options = options || {};
var nextMode;
/**
* Simple toggle:
* dark -> light
* light -> dark
* system -> opposite of resolved mode
*/
if (options.cycle === true) {
nextMode = getNextMode(state.currentMode);
} else {
nextMode = getOppositeResolvedMode();
}
return setMode(nextMode, {
source: options.source || 'toggle'
});
}
function cycleMode(options) {
return setMode(getNextMode(state.currentMode), {
source: options && options.source ? options.source : 'cycle'
});
}
function resetMode(options) {
safeLocalStorageRemove(CONFIG.storageKey);
return setMode(CONFIG.defaultMode, {
source: options && options.source ? options.source : 'reset',
save: true
});
}
function isDark() {
return state.resolvedMode === 'dark';
}
function isLight() {
return state.resolvedMode === 'light';
}
function isSystem() {
return state.currentMode === 'system';
}
function on(type, callback) {
if (!state.callbacks[type]) {
state.callbacks[type] = [];
}
if (typeof callback === 'function') {
state.callbacks[type].push(callback);
}
return function unsubscribe() {
off(type, callback);
};
}
function off(type, callback) {
if (!state.callbacks[type]) return;
state.callbacks[type] = state.callbacks[type].filter(function removeCallback(item) {
return item !== callback;
});
}
/**
* Event handlers.
*/
function handleToggleClick(event) {
var target = event.target.closest(CONFIG.toggleSelector);
if (!target) return;
event.preventDefault();
var cycle = target.getAttribute('data-rx-cycle') === 'true';
if (cycle) {
cycleMode({ source: 'toggle-click' });
} else {
toggleMode({ source: 'toggle-click' });
}
}
function handleButtonClick(event) {
var target = event.target.closest(CONFIG.buttonSelector);
if (!target) return;
event.preventDefault();
var mode = normalizeMode(target.getAttribute('data-rx-theme-button'));
setMode(mode, {
source: 'button-click'
});
}
function handleSelectChange(event) {
var target = event.target;
if (!target || !target.matches(CONFIG.selectSelector)) return;
var mode = normalizeMode(target.value);
setMode(mode, {
source: 'select-change'
});
}
function handleCheckboxChange(event) {
var target = event.target;
if (!target || !target.matches(CONFIG.checkboxSelector)) return;
var mode = target.checked ? 'dark' : 'light';
setMode(mode, {
source: 'checkbox-change'
});
}
function handleKeyboardShortcut(event) {
if (!CONFIG.enableKeyboardShortcut) return;
var tagName = event.target && event.target.tagName
? event.target.tagName.toLowerCase()
: '';
var isTyping =
tagName === 'input' ||
tagName === 'textarea' ||
tagName === 'select' ||
event.target.isContentEditable;
if (isTyping) return;
var keyMatches = String(event.key || '').toLowerCase() === CONFIG.keyboardShortcutKey;
var altMatches = CONFIG.keyboardShortcutAlt ? event.altKey : true;
var shiftMatches = CONFIG.keyboardShortcutShift ? event.shiftKey : true;
if (keyMatches && altMatches && shiftMatches) {
event.preventDefault();
cycleMode({ source: 'keyboard-shortcut' });
}
}
function handleSystemPreferenceChange() {
if (state.currentMode !== 'system') return;
applyTheme('system', {
source: 'system-preference',
save: false
});
}
function bindSystemPreferenceListener() {
var mediaQuery = getMediaQuery();
if (!mediaQuery) return;
if (typeof mediaQuery.addEventListener === 'function') {
mediaQuery.addEventListener('change', handleSystemPreferenceChange);
} else if (typeof mediaQuery.addListener === 'function') {
mediaQuery.addListener(handleSystemPreferenceChange);
}
}
function unbindSystemPreferenceListener() {
var mediaQuery = getMediaQuery();
if (!mediaQuery) return;
if (typeof mediaQuery.removeEventListener === 'function') {
mediaQuery.removeEventListener('change', handleSystemPreferenceChange);
} else if (typeof mediaQuery.removeListener === 'function') {
mediaQuery.removeListener(handleSystemPreferenceChange);
}
}
function bindEvents() {
document.addEventListener('click', handleToggleClick, false);
document.addEventListener('click', handleButtonClick, false);
document.addEventListener('change', handleSelectChange, false);
document.addEventListener('change', handleCheckboxChange, false);
document.addEventListener('keydown', handleKeyboardShortcut, false);
bindSystemPreferenceListener();
}
function unbindEvents() {
document.removeEventListener('click', handleToggleClick, false);
document.removeEventListener('click', handleButtonClick, false);
document.removeEventListener('change', handleSelectChange, false);
document.removeEventListener('change', handleCheckboxChange, false);
document.removeEventListener('keydown', handleKeyboardShortcut, false);
unbindSystemPreferenceListener();
}
/**
* Mutation observer:
* If new toggle/buttons are loaded later by AJAX,
* update them automatically.
*/
function setupMutationObserver() {
if (!window.MutationObserver) return;
var observer = new MutationObserver(function onMutation(mutations) {
var shouldUpdate = false;
mutations.forEach(function checkMutation(mutation) {
if (mutation.type !== 'childList') return;
if (mutation.addedNodes && mutation.addedNodes.length) {
shouldUpdate = true;
}
});
if (shouldUpdate) {
updateControls(state.currentMode, state.resolvedMode);
}
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
state.observers.push(observer);
}
function disconnectObservers() {
state.observers.forEach(function disconnect(observer) {
try {
observer.disconnect();
} catch (error) {}
});
state.observers = [];
}
/**
* Public API.
*/
var API = {
config: CONFIG,
state: state,
init: function init(customConfig) {
if (state.initialized) {
updateControls(state.currentMode, state.resolvedMode);
return API;
}
if (customConfig && typeof customConfig === 'object') {
Object.keys(customConfig).forEach(function mergeConfig(key) {
CONFIG[key] = customConfig[key];
});
}
var initialMode = getInitialMode();
applyTheme(initialMode, {
source: 'init',
save: false,
disableTransition: true
});
bindEvents();
setupMutationObserver();
state.initialized = true;
dispatchThemeEvent('ready', {
mode: state.currentMode,
resolvedMode: state.resolvedMode,
timestamp: Date.now()
});
log('Initialized');
return API;
},
destroy: function destroy() {
unbindEvents();
disconnectObservers();
state.initialized = false;
dispatchThemeEvent('destroy', {
timestamp: Date.now()
});
return API;
},
set: function set(mode) {
return setMode(mode, {
source: 'api-set'
});
},
setMode: function setModeAlias(mode) {
return setMode(mode, {
source: 'api-set-mode'
});
},
light: function light() {
return setMode('light', {
source: 'api-light'
});
},
dark: function dark() {
return setMode('dark', {
source: 'api-dark'
});
},
system: function system() {
return setMode('system', {
source: 'api-system'
});
},
toggle: function toggle() {
return toggleMode({
source: 'api-toggle'
});
},
cycle: function cycle() {
return cycleMode({
source: 'api-cycle'
});
},
reset: function reset() {
return resetMode({
source: 'api-reset'
});
},
getMode: function getMode() {
return state.currentMode;
},
getResolvedMode: function getResolvedMode() {
return state.resolvedMode;
},
getSystemPreference: getSystemPreference,
isDark: isDark,
isLight: isLight,
isSystem: isSystem,
on: on,
off: off,
refresh: function refresh() {
updateControls(state.currentMode, state.resolvedMode);
return API;
}
};
/**
* Attach to RX Theme namespace.
*/
RX.DarkMode = API;
RX.darkMode = API;
/**
* Early theme apply:
* This reduces flash between light/dark during loading.
*/
try {
var earlyMode = getInitialMode();
var earlyResolved = resolveMode(earlyMode);
applyHtmlAttributes(earlyMode, earlyResolved);
updateMetaThemeColor(earlyResolved);
updateColorScheme(earlyResolved);
state.currentMode = earlyMode;
state.resolvedMode = earlyResolved;
} catch (error) {}
/**
* DOM ready helper.
*/
function domReady(callback) {
if (
document.readyState === 'interactive' ||
document.readyState === 'complete'
) {
callback();
} else {
document.addEventListener('DOMContentLoaded', callback, {
once: true
});
}
}
domReady(function startDarkModeChunk() {
API.init();
});
})(window, document);
Use these HTML controls anywhere in your theme:
<button type="button" data-rx-dark-toggle>
<span data-rx-theme-icon="light">☀️</span>
<span data-rx-theme-icon="dark">🌙</span>
<span data-rx-theme-label="current">Theme</span>
</button>
For three buttons:
<button type="button" data-rx-theme-button="light">Light</button>
<button type="button" data-rx-theme-button="dark">Dark</button>
<button type="button" data-rx-theme-button="system">System</button>
For select dropdown:
<select data-rx-theme-select aria-label="Choose theme mode">
<option value="light">Light</option>
<option value="dark">Dark</option>
<option value="system">System</option>
</select>
Add this small CSS support in your main CSS:
html[data-rx-theme="light"] {
color-scheme: light;
}
html[data-rx-theme="dark"] {
color-scheme: dark;
}
html.rx-theme-no-transition *,
html.rx-theme-no-transition *::before,
html.rx-theme-no-transition *::after {
transition: none !important;
}
html.rx-theme-transition body {
transition:
background-color 250ms ease,
color 250ms ease,
border-color 250ms ease;
}
[data-rx-theme-icon] {
display: none;
}
[data-rx-theme-icon].is-active {
display: inline-flex;
}
[data-rx-theme-button].is-active,
[data-rx-dark-toggle].is-active {
font-weight: 700;
}
Best CSS variable system for RX Theme:
:root {
--rx-color-bg: #ffffff;
--rx-color-surface: #f8fafc;
--rx-color-text: #111827;
--rx-color-muted: #64748b;
--rx-color-border: #e5e7eb;
--rx-color-primary: #2563eb;
}
html[data-rx-theme="dark"] {
--rx-color-bg: #0b0f19;
--rx-color-surface: #111827;
--rx-color-text: #f9fafb;
--rx-color-muted: #94a3b8;
--rx-color-border: #243244;
--rx-color-primary: #60a5fa;
}
body {
background: var(--rx-color-bg);
color: var(--rx-color-text);
}
Then enqueue it after your main JS or as a static chunk:
wp_enqueue_script(
'rx-theme-dark-mode',
get_template_directory_uri() . '/assets/static-js/static-chunks-js/chunk-005-dark-mode.js',
array(),
wp_get_theme()->get('Version'),
true
);
For better anti-flash performance, load this file early in the header later, but for now this normal enqueue is safe.