Files
mainty/views/partials/theme.php
T

226 lines
5.9 KiB
PHP

<?php
$themeSection = $themeSection ?? null;
if ($themeSection === 'head'):
?>
<script>
(function () {
function readThemeCookie() {
var cookieParts = document.cookie ? document.cookie.split(';') : [];
for (var i = 0; i < cookieParts.length; i++) {
var part = cookieParts[i].trim();
if (part.indexOf('theme=') === 0) {
var value = decodeURIComponent(part.substring(6));
if (value === 'dark' || value === 'light') {
return value;
}
return null;
}
}
return null;
}
function resolveTheme() {
var cookieTheme = readThemeCookie();
if (cookieTheme) {
return cookieTheme;
}
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
}
var resolvedTheme = resolveTheme();
var html = document.documentElement;
html.classList.toggle('dark', resolvedTheme === 'dark');
html.setAttribute('data-theme', resolvedTheme);
})();
</script>
<style>
:root {
--theme-bg: #f3f4f6;
--theme-surface: #ffffff;
--theme-surface-alt: #f9fafb;
--theme-text: #111827;
--theme-text-muted: #6b7280;
--theme-border: #d1d5db;
}
html.dark {
--theme-bg: #111827;
--theme-surface: #1f2937;
--theme-surface-alt: #111827;
--theme-text: #f3f4f6;
--theme-text-muted: #9ca3af;
--theme-border: #374151;
}
.theme-page {
background-color: var(--theme-bg);
color: var(--theme-text);
}
.theme-surface {
background-color: var(--theme-surface);
color: var(--theme-text);
}
.theme-surface-alt {
background-color: var(--theme-surface-alt);
}
.theme-text {
color: var(--theme-text);
}
.theme-text-muted {
color: var(--theme-text-muted);
}
.theme-border {
border-color: var(--theme-border);
}
.theme-row-dividers > tr {
border-bottom: 1px solid var(--theme-border);
}
.theme-row-dividers > tr:last-child {
border-bottom-width: 0;
}
.theme-input {
background-color: var(--theme-surface);
border-color: var(--theme-border);
color: var(--theme-text);
}
.theme-input::placeholder {
color: var(--theme-text-muted);
}
#themeToggle {
position: fixed;
top: calc(1rem + env(safe-area-inset-top));
right: 1rem;
z-index: 50;
}
@media (max-width: 640px) {
#themeToggle {
top: calc(4.75rem + env(safe-area-inset-top));
}
}
#themeToggle:focus-visible {
outline: 3px solid #2563eb;
outline-offset: 2px;
}
</style>
<?php
endif;
if ($themeSection === 'body'):
?>
<button
id="themeToggle"
type="button"
class="bg-blue-600 hover:bg-blue-700 text-white p-3 rounded-full shadow-md transition"
aria-label="Switch to dark mode"
title="Switch to dark mode"
>
<i id="themeToggleIcon" class="bi bi-moon-stars-fill" aria-hidden="true"></i>
</button>
<noscript>
<style>
#themeToggle {
display: none !important;
}
</style>
</noscript>
<script>
(function () {
var html = document.documentElement;
var toggleButton = document.getElementById('themeToggle');
var toggleIcon = document.getElementById('themeToggleIcon');
if (!toggleButton || !toggleIcon) {
return;
}
function readThemeCookie() {
var cookieParts = document.cookie ? document.cookie.split(';') : [];
for (var i = 0; i < cookieParts.length; i++) {
var part = cookieParts[i].trim();
if (part.indexOf('theme=') === 0) {
var value = decodeURIComponent(part.substring(6));
if (value === 'dark' || value === 'light') {
return value;
}
return null;
}
}
return null;
}
function writeThemeCookie(theme) {
document.cookie = 'theme=' + encodeURIComponent(theme) + '; max-age=31536000; path=/; SameSite=Lax';
}
function applyTheme(theme) {
var validTheme = theme === 'dark' ? 'dark' : 'light';
html.classList.toggle('dark', validTheme === 'dark');
html.setAttribute('data-theme', validTheme);
return validTheme;
}
function syncToggle(theme) {
var isDark = theme === 'dark';
var label = isDark ? 'Switch to light mode' : 'Switch to dark mode';
var iconClass = isDark ? 'bi-sun-fill' : 'bi-moon-stars-fill';
toggleButton.setAttribute('aria-label', label);
toggleButton.setAttribute('title', label);
toggleButton.setAttribute('aria-pressed', isDark ? 'true' : 'false');
toggleIcon.className = 'bi ' + iconClass;
}
var initialTheme;
if (html.classList.contains('dark')) {
initialTheme = 'dark';
} else {
initialTheme = readThemeCookie() || 'light';
}
var currentTheme = applyTheme(initialTheme);
syncToggle(currentTheme);
toggleButton.addEventListener('click', function () {
var nextTheme = currentTheme === 'dark' ? 'light' : 'dark';
currentTheme = applyTheme(nextTheme);
try {
writeThemeCookie(currentTheme);
} catch (error) {
// Visual switch remains active if cookie storage is restricted.
}
syncToggle(currentTheme);
});
})();
</script>
<?php
endif;