Skip to content

Commit 3cdc848

Browse files
committed
feat(admin): improve dark theme in admin panel
1 parent 0579363 commit 3cdc848

12 files changed

Lines changed: 654 additions & 19 deletions

File tree

modules/admin/templates/sidebar-admin-menu.phtml

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ $library_counters = $counters->libraryCounters();
1818
$users_counters = $counters->usersCounters();
1919
$album_counters = $counters->albumCounters();
2020
$news_counters = $counters->news();
21+
$theme = di(\Johncms\System\View\Theme::class);
22+
$currentTheme = $theme->getCurrentTheme();
23+
$isDarkTheme = $theme->isDarkTheme($currentTheme);
24+
$themeToggleTitle = $isDarkTheme ? d__('system', 'Set Light Theme') : d__('system', 'Set Dark Theme');
25+
$themeToggleIcon = $isDarkTheme ? 'sun' : 'moon';
26+
$themeIconSprite = $this->asset('icons/sprite.svg', true);
2127
?>
2228
<div style="background-color: #bd0719; height: 5px">&nbsp;</div>
2329

@@ -295,12 +301,31 @@ $news_counters = $counters->news();
295301
</a>
296302
</div>
297303

298-
<?php if (count($config['lng_list']) > 1): ?>
304+
<div class="d-flex justify-content-between align-items-center">
305+
<?php if (count($config['lng_list']) > 1): ?>
306+
<div class="mt-1">
307+
<button class="btn btn-link ps-0" data-url="/language/" data-bs-toggle="modal" data-bs-target=".ajax_modal">
308+
<img class="icon icon-flag" src="<?= $this->asset('images/flags/' . strtolower($locale) . '.svg') ?>" alt="<?= $locale ?>">
309+
<?= $config['lng_list'][$locale]['name'] ?>
310+
</button>
311+
</div>
312+
<?php endif ?>
299313
<div class="mt-1">
300-
<button class="btn btn-link ps-0" data-url="/language/" data-bs-toggle="modal" data-bs-target=".ajax_modal">
301-
<img class="icon icon-flag" src="<?= $this->asset('images/flags/' . strtolower($locale) . '.svg') ?>" alt="<?= $locale ?>">
302-
<?= $config['lng_list'][$locale]['name'] ?>
314+
<button
315+
type="button"
316+
class="btn btn-link p-0"
317+
data-theme-toggle
318+
data-current-theme="<?= $this->e($currentTheme) ?>"
319+
data-icon-sprite="<?= $this->e($themeIconSprite) ?>"
320+
data-title-dark="<?= $this->e(d__('system', 'Set Dark Theme')) ?>"
321+
data-title-light="<?= $this->e(d__('system', 'Set Light Theme')) ?>"
322+
title="<?= $this->e($themeToggleTitle) ?>"
323+
aria-label="<?= $this->e($themeToggleTitle) ?>"
324+
>
325+
<svg class="icon m-0">
326+
<use xlink:href="<?= $themeIconSprite ?>#<?= $themeToggleIcon ?>"/>
327+
</svg>
303328
</button>
304329
</div>
305-
<?php endif ?>
330+
</div>
306331
</div>

themes/admin/assets/css/app.css

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

themes/admin/assets/css/app.rtl.css

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

themes/admin/assets/icons/sprite.svg

Lines changed: 10 additions & 0 deletions
Loading

themes/admin/assets/js/app.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

themes/admin/assets/js/manifest.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

themes/admin/assets/js/vendor.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

themes/admin/src/js/main.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,89 @@
66
* @link https://johncms.com JohnCMS Project
77
*/
88

9+
function initThemeToggle() {
10+
const toggle = document.querySelector('[data-theme-toggle]');
11+
12+
if (!toggle) {
13+
return;
14+
}
15+
16+
const validThemes = ['light', 'dark', 'auto'];
17+
const body = document.body;
18+
const iconUse = toggle.querySelector('use');
19+
const prefersDark = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
20+
21+
function isDark(theme) {
22+
if (theme === 'dark') {
23+
return true;
24+
}
25+
26+
return theme === 'auto' && prefersDark && prefersDark.matches;
27+
}
28+
29+
function normalizeTheme(theme) {
30+
return validThemes.includes(theme) ? theme : 'auto';
31+
}
32+
33+
function getCurrentTheme() {
34+
if (body.classList.contains('dark')) {
35+
return 'dark';
36+
}
37+
38+
if (body.classList.contains('light')) {
39+
return 'light';
40+
}
41+
42+
return 'auto';
43+
}
44+
45+
function updateToggleState(theme) {
46+
const darkMode = isDark(theme);
47+
const title = darkMode ? toggle.dataset.titleLight : toggle.dataset.titleDark;
48+
const icon = darkMode ? 'sun' : 'moon';
49+
const iconHref = toggle.dataset.iconSprite + '#' + icon;
50+
51+
toggle.setAttribute('title', title);
52+
toggle.setAttribute('aria-label', title);
53+
54+
if (iconUse) {
55+
iconUse.setAttribute('xlink:href', iconHref);
56+
iconUse.setAttribute('href', iconHref);
57+
}
58+
}
59+
60+
function applyTheme(theme) {
61+
const normalizedTheme = normalizeTheme(theme);
62+
body.classList.remove('light', 'dark', 'auto');
63+
body.classList.add(normalizedTheme);
64+
updateToggleState(normalizedTheme);
65+
}
66+
67+
function persistTheme(theme) {
68+
document.cookie = 'siteTheme=' + encodeURIComponent(theme) + '; path=/; max-age=31536000; SameSite=Lax';
69+
}
70+
71+
applyTheme(toggle.dataset.currentTheme || getCurrentTheme());
72+
73+
toggle.addEventListener('click', function () {
74+
const currentTheme = getCurrentTheme();
75+
const nextTheme = isDark(currentTheme) ? 'light' : 'dark';
76+
applyTheme(nextTheme);
77+
persistTheme(nextTheme);
78+
});
79+
80+
if (prefersDark && typeof prefersDark.addEventListener === 'function') {
81+
prefersDark.addEventListener('change', function () {
82+
if (getCurrentTheme() === 'auto') {
83+
updateToggleState('auto');
84+
}
85+
});
86+
}
87+
}
88+
989
$(function () {
90+
initThemeToggle();
91+
1092
const scroll_button = $('.to-top');
1193

1294
if ($(document).height() > $(window).height() && $(this).scrollTop() < 50) {

0 commit comments

Comments
 (0)