All checks were successful
CI - Build Tonehaus Docker image / tonehaus-ci-build (push) Successful in 1m57s
88 lines
3.3 KiB
Twig
88 lines
3.3 KiB
Twig
{% extends 'base.html.twig' %}
|
|
{% block title %}Settings{% endblock %}
|
|
{% block body %}
|
|
<h1 class="h4 mb-3">Settings</h1>
|
|
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<h2 class="h6">Appearance</h2>
|
|
<div class="form-check form-switch mt-2">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="themeToggle">
|
|
<label class="form-check-label" for="themeToggle">Dark mode</label>
|
|
</div>
|
|
<small class="text-secondary d-block mb-3">Theme and accent settings are stored in cookies.</small>
|
|
|
|
<div class="mt-2">
|
|
<label class="form-label mb-2" for="accentPicker">Accent colour</label>
|
|
<div class="d-flex align-items-center gap-3 flex-wrap">
|
|
<input class="form-control form-control-color" type="color" id="accentPicker" value="#6750a4" title="Choose accent colour">
|
|
<span class="text-secondary small">Matches the Material-inspired palette across buttons, links, and highlights.</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
(function(){
|
|
const root = document.documentElement;
|
|
const THEME_KEY = 'theme';
|
|
const ACCENT_KEY = 'accentColor';
|
|
const DEFAULT_ACCENT = '#6750a4';
|
|
const toggle = document.getElementById('themeToggle');
|
|
const accentPicker = document.getElementById('accentPicker');
|
|
|
|
function getCookie(name) {
|
|
const match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]+)'));
|
|
return match ? decodeURIComponent(match[1]) : '';
|
|
}
|
|
|
|
function persist(name, value) {
|
|
const d = new Date();
|
|
d.setFullYear(d.getFullYear() + 1);
|
|
document.cookie = name + '=' + encodeURIComponent(value) + '; path=/; SameSite=Lax; expires=' + d.toUTCString();
|
|
}
|
|
|
|
function accentContrast(hex) {
|
|
const normalized = hex.replace('#', '');
|
|
if (normalized.length !== 6) {
|
|
return '#ffffff';
|
|
}
|
|
const r = parseInt(normalized.substring(0, 2), 16);
|
|
const g = parseInt(normalized.substring(2, 4), 16);
|
|
const b = parseInt(normalized.substring(4, 6), 16);
|
|
const luminance = (0.299 * r) + (0.587 * g) + (0.114 * b);
|
|
return luminance > 180 ? '#1c1b20' : '#ffffff';
|
|
}
|
|
|
|
if (toggle) {
|
|
const initialTheme = getCookie(THEME_KEY) || root.getAttribute('data-bs-theme') || 'light';
|
|
toggle.checked = initialTheme === 'dark';
|
|
const setTheme = (theme) => {
|
|
root.setAttribute('data-bs-theme', theme);
|
|
persist(THEME_KEY, theme);
|
|
};
|
|
setTheme(initialTheme);
|
|
toggle.addEventListener('change', () => setTheme(toggle.checked ? 'dark' : 'light'));
|
|
}
|
|
|
|
if (accentPicker) {
|
|
const storedAccent = getCookie(ACCENT_KEY) || DEFAULT_ACCENT;
|
|
const validAccent = /^#([0-9a-f]{6})$/i.test(storedAccent) ? storedAccent : DEFAULT_ACCENT;
|
|
accentPicker.value = validAccent;
|
|
|
|
const applyAccent = (value) => {
|
|
const hex = /^#([0-9a-f]{6})$/i.test(value) ? value : DEFAULT_ACCENT;
|
|
root.style.setProperty('--accent-color', hex);
|
|
root.style.setProperty('--accent-on-color', accentContrast(hex));
|
|
persist(ACCENT_KEY, hex);
|
|
};
|
|
|
|
applyAccent(validAccent);
|
|
accentPicker.addEventListener('input', (event) => applyAccent(event.target.value));
|
|
}
|
|
})();
|
|
</script>
|
|
{% endblock %}
|
|
|
|
|