Fixed #33690 -- Added switch button for dark mode in the admin.
This commit is contained in:
parent
5028a02352
commit
bc7aa2a5e9
|
@ -5,6 +5,7 @@
|
||||||
@import url(fonts.css);
|
@import url(fonts.css);
|
||||||
|
|
||||||
/* VARIABLE DEFINITIONS */
|
/* VARIABLE DEFINITIONS */
|
||||||
|
html[data-theme="light"],
|
||||||
:root {
|
:root {
|
||||||
--primary: #79aec8;
|
--primary: #79aec8;
|
||||||
--secondary: #417690;
|
--secondary: #417690;
|
||||||
|
@ -900,7 +901,7 @@ a.deletelink:focus, a.deletelink:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
#branding {
|
#branding {
|
||||||
float: left;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
#branding h1 {
|
#branding h1 {
|
||||||
|
|
|
@ -31,3 +31,87 @@
|
||||||
--close-button-hover-bg: #666666;
|
--close-button-hover-bg: #666666;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
html[data-theme="dark"] {
|
||||||
|
--primary: #264b5d;
|
||||||
|
--primary-fg: #f7f7f7;
|
||||||
|
|
||||||
|
--body-fg: #eeeeee;
|
||||||
|
--body-bg: #121212;
|
||||||
|
--body-quiet-color: #e0e0e0;
|
||||||
|
--body-loud-color: #ffffff;
|
||||||
|
|
||||||
|
--breadcrumbs-link-fg: #e0e0e0;
|
||||||
|
--breadcrumbs-bg: var(--primary);
|
||||||
|
|
||||||
|
--link-fg: #81d4fa;
|
||||||
|
--link-hover-color: #4ac1f7;
|
||||||
|
--link-selected-fg: #6f94c6;
|
||||||
|
|
||||||
|
--hairline-color: #272727;
|
||||||
|
--border-color: #353535;
|
||||||
|
|
||||||
|
--error-fg: #e35f5f;
|
||||||
|
--message-success-bg: #006b1b;
|
||||||
|
--message-warning-bg: #583305;
|
||||||
|
--message-error-bg: #570808;
|
||||||
|
|
||||||
|
--darkened-bg: #212121;
|
||||||
|
--selected-bg: #1b1b1b;
|
||||||
|
--selected-row: #00363a;
|
||||||
|
|
||||||
|
--close-button-bg: #333333;
|
||||||
|
--close-button-hover-bg: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* THEME SWITCH */
|
||||||
|
.theme-toggle {
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
background: transparent;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle svg {
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 1rem;
|
||||||
|
width: 1rem;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ICONS */
|
||||||
|
.theme-toggle svg.theme-icon-when-auto,
|
||||||
|
.theme-toggle svg.theme-icon-when-dark,
|
||||||
|
.theme-toggle svg.theme-icon-when-light {
|
||||||
|
fill: var(--header-link-color);
|
||||||
|
color: var(--header-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="auto"] .theme-toggle svg.theme-icon-when-auto {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="dark"] .theme-toggle svg.theme-icon-when-dark {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme="light"] .theme-toggle svg.theme-icon-when-light {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visually-hidden {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0,0,0,0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border: 0;
|
||||||
|
color: var(--body-fg);
|
||||||
|
background-color: var(--body-bg);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
'use strict';
|
||||||
|
{
|
||||||
|
window.addEventListener('load', function(e) {
|
||||||
|
|
||||||
|
function setTheme(mode) {
|
||||||
|
if (mode !== "light" && mode !== "dark" && mode !== "auto") {
|
||||||
|
console.error(`Got invalid theme mode: ${mode}. Resetting to auto.`);
|
||||||
|
mode = "auto";
|
||||||
|
}
|
||||||
|
document.documentElement.dataset.theme = mode;
|
||||||
|
localStorage.setItem("theme", mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cycleTheme() {
|
||||||
|
const currentTheme = localStorage.getItem("theme") || "auto";
|
||||||
|
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||||
|
|
||||||
|
if (prefersDark) {
|
||||||
|
// Auto (dark) -> Light -> Dark
|
||||||
|
if (currentTheme === "auto") {
|
||||||
|
setTheme("light");
|
||||||
|
} else if (currentTheme === "light") {
|
||||||
|
setTheme("dark");
|
||||||
|
} else {
|
||||||
|
setTheme("auto");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Auto (light) -> Dark -> Light
|
||||||
|
if (currentTheme === "auto") {
|
||||||
|
setTheme("dark");
|
||||||
|
} else if (currentTheme === "dark") {
|
||||||
|
setTheme("light");
|
||||||
|
} else {
|
||||||
|
setTheme("auto");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initTheme() {
|
||||||
|
// set theme defined in localStorage if there is one, or fallback to auto mode
|
||||||
|
const currentTheme = localStorage.getItem("theme");
|
||||||
|
currentTheme ? setTheme(currentTheme) : setTheme("auto");
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupTheme() {
|
||||||
|
// Attach event handlers for toggling themes
|
||||||
|
const buttons = document.getElementsByClassName("theme-toggle");
|
||||||
|
Array.from(buttons).forEach((btn) => {
|
||||||
|
btn.addEventListener("click", cycleTheme);
|
||||||
|
});
|
||||||
|
initTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupTheme();
|
||||||
|
});
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
<link rel="stylesheet" href="{% block stylesheet %}{% static "admin/css/base.css" %}{% endblock %}">
|
<link rel="stylesheet" href="{% block stylesheet %}{% static "admin/css/base.css" %}{% endblock %}">
|
||||||
{% block dark-mode-vars %}
|
{% block dark-mode-vars %}
|
||||||
<link rel="stylesheet" href="{% static "admin/css/dark_mode.css" %}">
|
<link rel="stylesheet" href="{% static "admin/css/dark_mode.css" %}">
|
||||||
|
<script src="{% static "admin/js/theme.js" %}" defer></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% if not is_popup and is_nav_sidebar_enabled %}
|
{% if not is_popup and is_nav_sidebar_enabled %}
|
||||||
<link rel="stylesheet" href="{% static "admin/css/nav_sidebar.css" %}">
|
<link rel="stylesheet" href="{% static "admin/css/nav_sidebar.css" %}">
|
||||||
|
@ -59,6 +60,7 @@
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button type="submit">{% translate 'Log out' %}</button>
|
<button type="submit">{% translate 'Log out' %}</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% include "admin/color_theme_toggle.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -107,5 +109,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- END Container -->
|
<!-- END Container -->
|
||||||
|
|
||||||
|
<!-- SVGs -->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<symbol viewBox="0 0 24 24" width="16" height="16" id="icon-auto"><path d="M0 0h24v24H0z" fill="currentColor"/><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2V4a8 8 0 1 0 0 16z"/></symbol>
|
||||||
|
<symbol viewBox="0 0 24 24" width="16" height="16" id="icon-moon"><path d="M0 0h24v24H0z" fill="currentColor"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol>
|
||||||
|
<symbol viewBox="0 0 24 24" width="16" height="16" id="icon-sun"><path d="M0 0h24v24H0z" fill="currentColor"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol>
|
||||||
|
</svg>
|
||||||
|
<!-- END SVGs -->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
|
|
||||||
{% block branding %}
|
{% block branding %}
|
||||||
<h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('Django administration') }}</a></h1>
|
<h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('Django administration') }}</a></h1>
|
||||||
|
{% if user.is_anonymous %}
|
||||||
|
{% include "admin/color_theme_toggle.html" %}
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block nav-global %}{% endblock %}
|
{% block nav-global %}{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<button class="theme-toggle">
|
||||||
|
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
||||||
|
<svg class="theme-icon-when-auto">
|
||||||
|
<use xlink:href="#icon-auto" />
|
||||||
|
</svg>
|
||||||
|
<svg class="theme-icon-when-dark">
|
||||||
|
<use xlink:href="#icon-moon" />
|
||||||
|
</svg>
|
||||||
|
<svg class="theme-icon-when-light">
|
||||||
|
<use xlink:href="#icon-sun" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
|
@ -6,6 +6,7 @@
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button type="submit">{% translate 'Log out' %}</button>
|
<button type="submit">{% translate 'Log out' %}</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% include "admin/color_theme_toggle.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
<div class="breadcrumbs">
|
<div class="breadcrumbs">
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button type="submit">{% translate 'Log out' %}</button>
|
<button type="submit">{% translate 'Log out' %}</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% include "admin/color_theme_toggle.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
<div class="breadcrumbs">
|
<div class="breadcrumbs">
|
||||||
|
|
|
@ -32,7 +32,8 @@ Minor features
|
||||||
:mod:`django.contrib.admin`
|
:mod:`django.contrib.admin`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* The light or dark color theme of the admin can now be toggled in the UI, as
|
||||||
|
well as being set to follow the system setting.
|
||||||
|
|
||||||
:mod:`django.contrib.admindocs`
|
:mod:`django.contrib.admindocs`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
Loading…
Reference in New Issue