feat: Toggle dark mode without redirect if JS is enabled, store user preference
Some checks failed
Build and Deploy Dark-theme Static Site / build (push) Successful in 1m31s
Build and Deploy Pride-Theme Static Site / build (push) Successful in 1m29s
Build and Deploy Static Site / build (push) Failing after 1m38s
Build and Deploy Development Static Site / build (push) Successful in 1m11s

Fixes #11
This commit is contained in:
Kumi 2025-05-28 08:56:00 +02:00
parent d7771573e7
commit 9a3fde8ae6
Signed by: kumi
GPG key ID: ECBCC9082395383F
3 changed files with 111 additions and 21 deletions

4
.snapshotignore Normal file
View file

@ -0,0 +1,4 @@
/assets/dist
/assets/img
/assets/*.asc
/blog/

74
assets/js/theme-toggle.js Normal file
View file

@ -0,0 +1,74 @@
document.addEventListener('DOMContentLoaded', function() {
// Get the theme toggle button
const themeToggleBtn = document.querySelector('.theme-toggle-btn');
if (!themeToggleBtn) return; // Exit if button not found
const lightIcon = themeToggleBtn.querySelector('.light-icon');
const darkIcon = themeToggleBtn.querySelector('.dark-icon');
const themeStylesheet = document.getElementById('theme-stylesheet');
const relativePath = themeStylesheet.href.substring(0, themeStylesheet.href.lastIndexOf('/') + 1);
const timestamp = themeStylesheet.href.split('?v=')[1] || '';
// Function to toggle theme
function toggleTheme(e) {
e.preventDefault(); // Prevent the default link behavior
const currentTheme = document.documentElement.getAttribute('data-bs-theme') || 'light';
const newTheme = (currentTheme === 'dark') ? 'plain' : 'dark';
// Update HTML attribute
document.documentElement.setAttribute('data-bs-theme', newTheme);
// Update the theme stylesheet
themeStylesheet.href = relativePath + newTheme + '.css?v=' + timestamp;
// Update button icon visibility and aria-label
if (newTheme === 'dark') {
lightIcon.style.display = '';
darkIcon.style.display = 'none';
themeToggleBtn.setAttribute('aria-label', 'Switch to light theme');
themeToggleBtn.href = 'https://private.coffee' + window.location.pathname;
} else {
lightIcon.style.display = 'none';
darkIcon.style.display = '';
themeToggleBtn.setAttribute('aria-label', 'Switch to dark theme');
themeToggleBtn.href = 'https://dark.private.coffee' + window.location.pathname;
}
// Store preference in localStorage
localStorage.setItem('privateCoffeeTheme', newTheme);
}
// Add click event listener to toggle theme
themeToggleBtn.addEventListener('click', toggleTheme);
// Check for saved theme preference and apply it
const savedTheme = localStorage.getItem('privateCoffeeTheme');
if (savedTheme) {
// Get the current theme from the stylesheet filename
const currentThemeMatch = themeStylesheet.href.match(/\/theme\/([^.]+)\.css/);
const currentTheme = currentThemeMatch ? currentThemeMatch[1] : 'plain';
// Only apply the saved theme if it's different from the current theme
if (savedTheme !== currentTheme) {
document.documentElement.setAttribute('data-bs-theme', savedTheme);
// Update the theme stylesheet
themeStylesheet.href = relativePath + savedTheme + '.css?v=' + timestamp;
// Update button icon visibility and aria-label based on saved theme
if (savedTheme === 'dark') {
lightIcon.style.display = '';
darkIcon.style.display = 'none';
themeToggleBtn.setAttribute('aria-label', 'Switch to light theme');
themeToggleBtn.href = 'https://private.coffee' + window.location.pathname;
} else {
lightIcon.style.display = 'none';
darkIcon.style.display = '';
themeToggleBtn.setAttribute('aria-label', 'Switch to dark theme');
themeToggleBtn.href = 'https://dark.private.coffee' + window.location.pathname;
}
}
}
});

View file

@ -35,11 +35,12 @@
{% endblock title %}
- Private.coffee</title>
<link rel="stylesheet"
href="{{ relative_path }}assets/dist/css/bootstrap.min.css" />
href="{{ relative_path }}assets/dist/css/bootstrap.min.css?v={{ timestamp }}" />
<link rel="stylesheet"
href="{{ relative_path }}assets/css/base.css?v={{ timestamp }}" />
<link rel="stylesheet"
href="{{ relative_path }}assets/css/theme/{{ theme }}.css?v={{ timestamp }}" />
href="{{ relative_path }}assets/css/theme/{{ theme }}.css?v={{ timestamp }}"
id="theme-stylesheet">
<link rel="stylesheet"
href="{{ relative_path }}assets/dist/fonts/fonts.css?v={{ timestamp }}" />
</head>
@ -67,37 +68,45 @@
<div class="navbar" id="navcol-1">
<ul class="navbar-nav mx-auto">
<li class="nav-item">
<a class="nav-link active" href="/index.html">Home</a>
<a class="nav-link active" href="{{ relative_path }}index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/services.html">Services</a>
<a class="nav-link" href="{{ relative_path }}services.html">Services</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/blog/">Blog</a>
<a class="nav-link" href="{{ relative_path }}blog/">Blog</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://status.private.coffee/">Status</a>
</li>
</ul>
<div class="theme-toggle-container me-2">
{% if theme == 'dark' %}
<a href="https://private.coffee{{ request.path }}"
class="btn btn-outline-primary"
aria-label="Switch to light theme">{{ "sun" | icon | safe }}</a>
{% else %}
<a href="https://dark.private.coffee{{ request.path }}"
class="btn btn-outline-primary"
aria-label="Switch to dark theme">{{ "moon" | icon | safe }}</a>
{% endif %}
</div>
{% if theme == 'plain' or theme == 'dark' %}
<div class="theme-toggle-container me-2">
{% if theme == 'dark' %}
<a href="https://private.coffee{{ request.path }}"
class="btn btn-outline-primary theme-toggle-btn"
aria-label="Switch to light theme">
<span class="theme-icon light-icon">{{ "sun" | icon | safe }}</span>
</a>
{% else %}
<a href="https://dark.private.coffee{{ request.path }}"
class="btn btn-outline-primary theme-toggle-btn"
aria-label="Switch to dark theme">
<span class="theme-icon dark-icon">{{ "moon" | icon | safe }}</span>
<span class="theme-icon light-icon" style="display: none;">{{ "sun" | icon | safe }}</span>
</a>
{% endif %}
</div>
{% endif %}
<a class="btn btn-primary shadow navbar-btn"
role="button"
href="/membership.html">JOIN &amp; SUPPORT</a>
href="{{ relative_path }}membership.html">JOIN &amp; SUPPORT</a>
</div>
</div>
</nav>
{% if warning %}{{ warning|safe }}{% endif %}
{% block content %}{% endblock %}
{% block content %}
{% endblock content %}
<footer class="bg-primary-gradient">
<div class="container py-4 py-lg-5">
<div class="row justify-content-center">
@ -105,13 +114,13 @@
<h3 class="fs-6 fw-bold">Legal Stuff</h3>
<ul class="list-unstyled">
<li>
<a href="/legal.html">Legal Notice</a>
<a href="{{ relative_path }}legal.html">Legal Notice</a>
</li>
<li>
<a href="/privacy.html">Privacy Notice</a>
<a href="{{ relative_path }}privacy.html">Privacy Notice</a>
</li>
<li>
<a href="/terms.html">Terms of Service</a>
<a href="{{ relative_path }}terms.html">Terms of Service</a>
</li>
</ul>
</div>
@ -138,5 +147,8 @@
</div>
</div>
</footer>
{% if theme == "plain" %}
<script src="{{ relative_path }}assets/js/theme-toggle.js?v={{ timestamp }}"></script>
{% endif %}
</body>
</html>