Second commit
This commit is contained in:
@@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* Dark palette for Twenty Twenty-Five default style variation.
|
||||||
|
* Overrides theme preset CSS variables when html.tt5-ldt-dark is set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html.tt5-ldt-dark {
|
||||||
|
color-scheme: dark;
|
||||||
|
|
||||||
|
--wp--preset--color--base: #111111;
|
||||||
|
--wp--preset--color--contrast: #f5f5f5;
|
||||||
|
--wp--preset--color--accent-1: #ffee58;
|
||||||
|
--wp--preset--color--accent-2: #d4a8d0;
|
||||||
|
--wp--preset--color--accent-3: #9b8fd4;
|
||||||
|
--wp--preset--color--accent-4: #a3a3a3;
|
||||||
|
--wp--preset--color--accent-5: #1c1c1a;
|
||||||
|
--wp--preset--color--accent-6: color-mix(in srgb, currentColor 25%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark body,
|
||||||
|
html.tt5-ldt-dark .wp-site-blocks {
|
||||||
|
background-color: var(--wp--preset--color--base) !important;
|
||||||
|
color: var(--wp--preset--color--contrast) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Blocks that use preset background/text colors */
|
||||||
|
html.tt5-ldt-dark .has-base-background-color {
|
||||||
|
background-color: var(--wp--preset--color--base) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-contrast-background-color {
|
||||||
|
background-color: var(--wp--preset--color--contrast) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-base-color {
|
||||||
|
color: var(--wp--preset--color--base) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-contrast-color {
|
||||||
|
color: var(--wp--preset--color--contrast) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-accent-1-color {
|
||||||
|
color: var(--wp--preset--color--accent-1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-accent-2-color {
|
||||||
|
color: var(--wp--preset--color--accent-2) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-accent-3-color {
|
||||||
|
color: var(--wp--preset--color--accent-3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-accent-4-color {
|
||||||
|
color: var(--wp--preset--color--accent-4) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-accent-5-color {
|
||||||
|
color: var(--wp--preset--color--accent-5) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-accent-1-background-color {
|
||||||
|
background-color: var(--wp--preset--color--accent-1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-accent-2-background-color {
|
||||||
|
background-color: var(--wp--preset--color--accent-2) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-accent-3-background-color {
|
||||||
|
background-color: var(--wp--preset--color--accent-3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-accent-4-background-color {
|
||||||
|
background-color: var(--wp--preset--color--accent-4) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .has-accent-5-background-color {
|
||||||
|
background-color: var(--wp--preset--color--accent-5) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form controls follow dark scheme */
|
||||||
|
html.tt5-ldt-dark input:not([type="submit"]):not([type="button"]):not([type="reset"]),
|
||||||
|
html.tt5-ldt-dark textarea,
|
||||||
|
html.tt5-ldt-dark select {
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
color: var(--wp--preset--color--contrast);
|
||||||
|
border-color: var(--wp--preset--color--accent-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark ::selection {
|
||||||
|
background: var(--wp--preset--color--accent-3);
|
||||||
|
color: var(--wp--preset--color--contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Smooth transition when toggling */
|
||||||
|
html.tt5-ldt-animate,
|
||||||
|
html.tt5-ldt-animate body,
|
||||||
|
html.tt5-ldt-animate .wp-site-blocks {
|
||||||
|
transition: background-color 0.25s ease, color 0.25s ease;
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
.tt5-ldt-toggle {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 99999;
|
||||||
|
right: 1.25rem;
|
||||||
|
bottom: 1.25rem;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.65rem 1rem;
|
||||||
|
border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: var(--wp--preset--color--base, #fff);
|
||||||
|
color: var(--wp--preset--color--contrast, #111);
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||||
|
font: 600 0.875rem/1 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tt5-ldt-toggle:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tt5-ldt-toggle:focus-visible {
|
||||||
|
outline: 2px solid var(--wp--preset--color--accent-3, #503aa8);
|
||||||
|
outline-offset: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tt5-ldt-toggle__icon {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
html:not(.tt5-ldt-dark) .tt5-ldt-toggle__icon--moon,
|
||||||
|
html.tt5-ldt-dark .tt5-ldt-toggle__icon--sun {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.tt5-ldt-dark .tt5-ldt-toggle {
|
||||||
|
background: #1a1a1a;
|
||||||
|
color: #f5f5f5;
|
||||||
|
border-color: rgba(255, 255, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.tt5-ldt-toggle__label {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tt5-ldt-toggle {
|
||||||
|
padding: 0.75rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var config = window.tt5Ldt || {};
|
||||||
|
var btn = document.getElementById('tt5-ldt-toggle');
|
||||||
|
if (!btn) return;
|
||||||
|
|
||||||
|
var storageKey = config.storageKey || 'tt5_ldt_scheme';
|
||||||
|
var cookieName = config.cookieName || 'tt5_ldt_scheme';
|
||||||
|
var prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
|
|
||||||
|
function getStoredScheme() {
|
||||||
|
try {
|
||||||
|
var stored = localStorage.getItem(storageKey);
|
||||||
|
if (stored === 'light' || stored === 'dark') {
|
||||||
|
return stored;
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
var match = document.cookie.match(
|
||||||
|
new RegExp('(?:^|; )' + cookieName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '=([^;]*)')
|
||||||
|
);
|
||||||
|
if (match) {
|
||||||
|
var cookieVal = decodeURIComponent(match[1]);
|
||||||
|
if (cookieVal === 'light' || cookieVal === 'dark') {
|
||||||
|
return cookieVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getScheme() {
|
||||||
|
var stored = getStoredScheme();
|
||||||
|
if (stored) {
|
||||||
|
return stored;
|
||||||
|
}
|
||||||
|
return document.documentElement.classList.contains('tt5-ldt-dark')
|
||||||
|
? 'dark'
|
||||||
|
: 'light';
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCookie(scheme) {
|
||||||
|
var path = config.cookiePath || '/';
|
||||||
|
var domain = config.cookieDomain ? '; domain=' + config.cookieDomain : '';
|
||||||
|
var maxAge = 60 * 60 * 24 * 365;
|
||||||
|
document.cookie =
|
||||||
|
cookieName +
|
||||||
|
'=' +
|
||||||
|
encodeURIComponent(scheme) +
|
||||||
|
';path=' +
|
||||||
|
path +
|
||||||
|
domain +
|
||||||
|
';max-age=' +
|
||||||
|
maxAge +
|
||||||
|
';SameSite=Lax';
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyScheme(scheme, animate) {
|
||||||
|
var root = document.documentElement;
|
||||||
|
var isDark = scheme === 'dark';
|
||||||
|
|
||||||
|
if (animate) {
|
||||||
|
root.classList.add('tt5-ldt-animate');
|
||||||
|
window.setTimeout(function () {
|
||||||
|
root.classList.remove('tt5-ldt-animate');
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
root.classList.toggle('tt5-ldt-dark', isDark);
|
||||||
|
root.setAttribute('data-tt5-scheme', scheme);
|
||||||
|
|
||||||
|
try {
|
||||||
|
localStorage.setItem(storageKey, scheme);
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
setCookie(scheme);
|
||||||
|
updateButton(isDark);
|
||||||
|
|
||||||
|
if (config.isLoggedIn && config.ajaxUrl && config.nonce) {
|
||||||
|
var body = new FormData();
|
||||||
|
body.append('action', 'tt5_ldt_save_scheme');
|
||||||
|
body.append('nonce', config.nonce);
|
||||||
|
body.append('scheme', scheme);
|
||||||
|
fetch(config.ajaxUrl, { method: 'POST', body: body, credentials: 'same-origin' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateButton(isDark) {
|
||||||
|
var i18n = config.i18n || {};
|
||||||
|
btn.setAttribute('aria-pressed', isDark ? 'true' : 'false');
|
||||||
|
btn.setAttribute(
|
||||||
|
'aria-label',
|
||||||
|
isDark ? i18n.light || 'Switch to light mode' : i18n.dark || 'Switch to dark mode'
|
||||||
|
);
|
||||||
|
btn.setAttribute(
|
||||||
|
'title',
|
||||||
|
isDark ? i18n.lightLabel || 'Light mode' : i18n.darkLabel || 'Dark mode'
|
||||||
|
);
|
||||||
|
|
||||||
|
var label = btn.querySelector('.tt5-ldt-toggle__label');
|
||||||
|
if (label) {
|
||||||
|
label.textContent = isDark ? i18n.lightLabel || 'Light' : i18n.darkLabel || 'Dark';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.addEventListener('click', function () {
|
||||||
|
var next = getScheme() === 'dark' ? 'light' : 'dark';
|
||||||
|
applyScheme(next, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// First visit: no saved preference — follow system setting until user toggles.
|
||||||
|
if (!getStoredScheme() && !document.documentElement.getAttribute('data-tt5-scheme')) {
|
||||||
|
applyScheme(prefersDark.matches ? 'dark' : 'light', false);
|
||||||
|
} else {
|
||||||
|
updateButton(document.documentElement.classList.contains('tt5-ldt-dark'));
|
||||||
|
}
|
||||||
|
|
||||||
|
prefersDark.addEventListener('change', function (event) {
|
||||||
|
if (getStoredScheme()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
applyScheme(event.matches ? 'dark' : 'light', true);
|
||||||
|
});
|
||||||
|
})();
|
||||||
@@ -0,0 +1,253 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Main plugin bootstrap.
|
||||||
|
*
|
||||||
|
* @package TT5_Light_Dark_Toggle
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined( 'ABSPATH' ) || exit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TT5 Light/Dark Toggle plugin.
|
||||||
|
*/
|
||||||
|
class TT5_LDT {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize hooks.
|
||||||
|
*/
|
||||||
|
public static function init() {
|
||||||
|
add_action( 'plugins_loaded', array( __CLASS__, 'bootstrap' ) );
|
||||||
|
add_action( 'admin_notices', array( __CLASS__, 'admin_theme_notice' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load frontend assets when the active theme is Twenty Twenty-Five.
|
||||||
|
*/
|
||||||
|
public static function bootstrap() {
|
||||||
|
if ( ! self::is_target_theme() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_assets' ) );
|
||||||
|
add_action( 'wp_footer', array( __CLASS__, 'render_toggle' ), 5 );
|
||||||
|
add_action( 'wp_head', array( __CLASS__, 'inline_preference_script' ), 0 );
|
||||||
|
|
||||||
|
add_action( 'wp_ajax_tt5_ldt_save_scheme', array( __CLASS__, 'ajax_save_scheme' ) );
|
||||||
|
add_action( 'wp_ajax_nopriv_tt5_ldt_save_scheme', array( __CLASS__, 'ajax_save_scheme' ) );
|
||||||
|
|
||||||
|
add_action( 'show_user_profile', array( __CLASS__, 'render_profile_field' ) );
|
||||||
|
add_action( 'edit_user_profile', array( __CLASS__, 'render_profile_field' ) );
|
||||||
|
add_action( 'personal_options_update', array( __CLASS__, 'save_profile_field' ) );
|
||||||
|
add_action( 'edit_user_profile_update', array( __CLASS__, 'save_profile_field' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether Twenty Twenty-Five (or a child of it) is active.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function is_target_theme() {
|
||||||
|
$theme = wp_get_theme();
|
||||||
|
return 'twentytwentyfive' === $theme->get_template();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warn in admin if the theme is not supported.
|
||||||
|
*/
|
||||||
|
public static function admin_theme_notice() {
|
||||||
|
if ( self::is_target_theme() || ! current_user_can( 'switch_themes' ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
|
||||||
|
if ( $screen && 'plugins' !== $screen->id ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '<div class="notice notice-warning"><p>';
|
||||||
|
echo esc_html__(
|
||||||
|
'TT5 Light/Dark Toggle is active but Twenty Twenty-Five is not the current theme. The toggle only appears with that theme.',
|
||||||
|
'tt5-light-dark-toggle'
|
||||||
|
);
|
||||||
|
echo '</p></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent flash of wrong theme by applying class before paint.
|
||||||
|
*/
|
||||||
|
public static function inline_preference_script() {
|
||||||
|
$scheme = self::get_initial_scheme();
|
||||||
|
$storage_key = esc_js( TT5_LDT_STORAGE );
|
||||||
|
$cookie_name = esc_js( TT5_LDT_COOKIE );
|
||||||
|
|
||||||
|
?>
|
||||||
|
<script id="tt5-ldt-init">
|
||||||
|
(function () {
|
||||||
|
var storageKey = <?php echo wp_json_encode( TT5_LDT_STORAGE ); ?>;
|
||||||
|
var cookieName = <?php echo wp_json_encode( TT5_LDT_COOKIE ); ?>;
|
||||||
|
var serverScheme = <?php echo wp_json_encode( $scheme ); ?>;
|
||||||
|
var stored = '';
|
||||||
|
try {
|
||||||
|
stored = localStorage.getItem(storageKey) || '';
|
||||||
|
} catch (e) {}
|
||||||
|
if (!stored && document.cookie.indexOf(cookieName + '=') !== -1) {
|
||||||
|
var match = document.cookie.match(new RegExp(cookieName + '=([^;]+)'));
|
||||||
|
stored = match ? decodeURIComponent(match[1]) : '';
|
||||||
|
}
|
||||||
|
var scheme = stored === 'dark' || stored === 'light' ? stored : serverScheme;
|
||||||
|
if (scheme === 'dark') {
|
||||||
|
document.documentElement.classList.add('tt5-ldt-dark');
|
||||||
|
}
|
||||||
|
if (scheme === 'light' || scheme === 'dark') {
|
||||||
|
document.documentElement.setAttribute('data-tt5-scheme', scheme);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve saved scheme for first paint (cookie or user meta only).
|
||||||
|
*
|
||||||
|
* @return string light|dark|empty string when none saved.
|
||||||
|
*/
|
||||||
|
public static function get_initial_scheme() {
|
||||||
|
if ( isset( $_COOKIE[ TT5_LDT_COOKIE ] ) ) {
|
||||||
|
$cookie = sanitize_key( wp_unslash( $_COOKIE[ TT5_LDT_COOKIE ] ) );
|
||||||
|
if ( in_array( $cookie, array( 'light', 'dark' ), true ) ) {
|
||||||
|
return $cookie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_user_logged_in() ) {
|
||||||
|
$meta = get_user_meta( get_current_user_id(), TT5_LDT_STORAGE, true );
|
||||||
|
if ( in_array( $meta, array( 'light', 'dark' ), true ) ) {
|
||||||
|
return $meta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue styles and toggle script.
|
||||||
|
*/
|
||||||
|
public static function enqueue_assets() {
|
||||||
|
wp_enqueue_style(
|
||||||
|
'tt5-ldt-dark',
|
||||||
|
TT5_LDT_URL . 'assets/css/dark-theme.css',
|
||||||
|
array(),
|
||||||
|
TT5_LDT_VERSION
|
||||||
|
);
|
||||||
|
|
||||||
|
wp_enqueue_style(
|
||||||
|
'tt5-ldt-toggle',
|
||||||
|
TT5_LDT_URL . 'assets/css/toggle.css',
|
||||||
|
array(),
|
||||||
|
TT5_LDT_VERSION
|
||||||
|
);
|
||||||
|
|
||||||
|
wp_enqueue_script(
|
||||||
|
'tt5-ldt-toggle',
|
||||||
|
TT5_LDT_URL . 'assets/js/toggle.js',
|
||||||
|
array(),
|
||||||
|
TT5_LDT_VERSION,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
wp_localize_script(
|
||||||
|
'tt5-ldt-toggle',
|
||||||
|
'tt5Ldt',
|
||||||
|
array(
|
||||||
|
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
|
||||||
|
'nonce' => wp_create_nonce( 'tt5_ldt_save' ),
|
||||||
|
'storageKey' => TT5_LDT_STORAGE,
|
||||||
|
'cookieName' => TT5_LDT_COOKIE,
|
||||||
|
'cookiePath' => COOKIEPATH ? COOKIEPATH : '/',
|
||||||
|
'cookieDomain' => COOKIE_DOMAIN,
|
||||||
|
'isLoggedIn' => is_user_logged_in(),
|
||||||
|
'i18n' => array(
|
||||||
|
'light' => __( 'Switch to light mode', 'tt5-light-dark-toggle' ),
|
||||||
|
'dark' => __( 'Switch to dark mode', 'tt5-light-dark-toggle' ),
|
||||||
|
'lightLabel' => __( 'Light mode', 'tt5-light-dark-toggle' ),
|
||||||
|
'darkLabel' => __( 'Dark mode', 'tt5-light-dark-toggle' ),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output floating toggle button.
|
||||||
|
*/
|
||||||
|
public static function render_toggle() {
|
||||||
|
$saved = self::get_initial_scheme();
|
||||||
|
$is_dark = 'dark' === $saved;
|
||||||
|
?>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
id="tt5-ldt-toggle"
|
||||||
|
class="tt5-ldt-toggle"
|
||||||
|
aria-pressed="<?php echo $is_dark ? 'true' : 'false'; ?>"
|
||||||
|
aria-label="<?php echo esc_attr( $is_dark ? __( 'Switch to light mode', 'tt5-light-dark-toggle' ) : __( 'Switch to dark mode', 'tt5-light-dark-toggle' ) ); ?>"
|
||||||
|
title="<?php echo esc_attr( $is_dark ? __( 'Light mode', 'tt5-light-dark-toggle' ) : __( 'Dark mode', 'tt5-light-dark-toggle' ) ); ?>"
|
||||||
|
>
|
||||||
|
<span class="tt5-ldt-toggle__icon tt5-ldt-toggle__icon--sun" aria-hidden="true">☀</span>
|
||||||
|
<span class="tt5-ldt-toggle__icon tt5-ldt-toggle__icon--moon" aria-hidden="true">☾</span>
|
||||||
|
<span class="tt5-ldt-toggle__label"><?php echo esc_html( $is_dark ? __( 'Light', 'tt5-light-dark-toggle' ) : __( 'Dark', 'tt5-light-dark-toggle' ) ); ?></span>
|
||||||
|
</button>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persist preference for logged-in users.
|
||||||
|
*/
|
||||||
|
public static function ajax_save_scheme() {
|
||||||
|
check_ajax_referer( 'tt5_ldt_save', 'nonce' );
|
||||||
|
|
||||||
|
$scheme = isset( $_POST['scheme'] ) ? sanitize_key( wp_unslash( $_POST['scheme'] ) ) : '';
|
||||||
|
if ( ! in_array( $scheme, array( 'light', 'dark' ), true ) ) {
|
||||||
|
wp_send_json_error( array( 'message' => 'Invalid scheme' ), 400 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_user_logged_in() ) {
|
||||||
|
update_user_meta( get_current_user_id(), TT5_LDT_STORAGE, $scheme );
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_send_json_success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional profile field (read-only info).
|
||||||
|
*
|
||||||
|
* @param WP_User $user User object.
|
||||||
|
*/
|
||||||
|
public static function render_profile_field( $user ) {
|
||||||
|
$value = get_user_meta( $user->ID, TT5_LDT_STORAGE, true );
|
||||||
|
if ( ! $value ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<h2><?php esc_html_e( 'Color scheme preference', 'tt5-light-dark-toggle' ); ?></h2>
|
||||||
|
<table class="form-table" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<th><label><?php esc_html_e( 'Site appearance', 'tt5-light-dark-toggle' ); ?></label></th>
|
||||||
|
<td>
|
||||||
|
<?php echo esc_html( 'dark' === $value ? __( 'Dark mode', 'tt5-light-dark-toggle' ) : __( 'Light mode', 'tt5-light-dark-toggle' ) ); ?>
|
||||||
|
<p class="description"><?php esc_html_e( 'Saved when you use the front-end light/dark toggle.', 'tt5-light-dark-toggle' ); ?></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Profile save noop (preference saved via AJAX).
|
||||||
|
*
|
||||||
|
* @param int $user_id User ID.
|
||||||
|
*/
|
||||||
|
public static function save_profile_field( $user_id ) {
|
||||||
|
if ( ! current_user_can( 'edit_user', $user_id ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin Name: TT5 Light/Dark Toggle
|
||||||
|
* Plugin URI: https://github.com/example/tt5-light-dark-toggle
|
||||||
|
* Description: Adds a light/dark mode toggle for the Twenty Twenty-Five WordPress theme.
|
||||||
|
* Version: 1.0.0
|
||||||
|
* Requires at least: 6.4
|
||||||
|
* Requires PHP: 7.4
|
||||||
|
* Author: TT5 Light/Dark Toggle
|
||||||
|
* License: GPL-2.0-or-later
|
||||||
|
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
* Text Domain: tt5-light-dark-toggle
|
||||||
|
*
|
||||||
|
* @package TT5_Light_Dark_Toggle
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined( 'ABSPATH' ) || exit;
|
||||||
|
|
||||||
|
define( 'TT5_LDT_VERSION', '1.0.0' );
|
||||||
|
define( 'TT5_LDT_FILE', __FILE__ );
|
||||||
|
define( 'TT5_LDT_DIR', plugin_dir_path( __FILE__ ) );
|
||||||
|
define( 'TT5_LDT_URL', plugin_dir_url( __FILE__ ) );
|
||||||
|
define( 'TT5_LDT_COOKIE', 'tt5_ldt_scheme' );
|
||||||
|
define( 'TT5_LDT_STORAGE', 'tt5_ldt_scheme' );
|
||||||
|
|
||||||
|
require_once TT5_LDT_DIR . 'includes/class-tt5-ldt.php';
|
||||||
|
|
||||||
|
TT5_LDT::init();
|
||||||
Reference in New Issue
Block a user