Skip to content

Commit 37796bb

Browse files
authored
Merge pull request #616 from maykinmedia/issue/oaf-149-admin-theme-toggle
💄 Fix light/dark themes for admin
2 parents 37d2f1d + 77d80b8 commit 37796bb

File tree

6 files changed

+250
-24
lines changed

6 files changed

+250
-24
lines changed

src/objects/scss/admin/_admin_theme.scss

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@ Generic admin styling overrides.
33
44
DO NOT PUT ANY TARGET APP-SPECIFIC RULES HERE.
55
*/
6+
@use './themes/dark' as dark-theme;
7+
@use './themes/light' as light-theme;
8+
69
@import "./vars";
710

11+
@include light-theme.styles;
12+
@include dark-theme.styles;
13+
14+
815
// override django CSS variables
916
// see admin/static/admin/css/base.css for a reference
1017
:root {
@@ -131,22 +138,59 @@ div.breadcrumbs {
131138
font-weight: bold !important;
132139
}
133140

141+
@mixin icon-override($iconUrl) {
142+
background: none;
143+
// display: inline-flex;
144+
// align-items: center;
145+
// padding-left: 0;
146+
color: var(--body-fg);
147+
position: relative;
148+
149+
// need to use pseudo element, otherwise the text in the same element is not visible
150+
// because of the mask clipping
151+
&:before {
152+
display: block;
153+
content: '';
154+
position: absolute;
155+
left: 0;
156+
top: 0;
157+
width: 14px;
158+
height: 14px;
159+
margin-right: 2px;
160+
background: var(--body-fg) !important;
161+
color: var(--body-fg);
162+
mask-image: url($iconUrl);
163+
mask-repeat: no-repeat;
164+
mask-size: 14px 14px;
165+
mask-position: 0px 0px;
166+
}
167+
}
168+
134169
/* Icons */
135170
.addlink {
136-
background: url("../img/admin/plus-square-regular.svg") 0 0/14px 14px no-repeat;
171+
@include icon-override('../img/admin/plus-square-regular.svg');
137172
}
173+
174+
.object-tools a.addlink {
175+
&:before {
176+
display: none;
177+
}
178+
}
179+
138180
.changelink,
139181
.inlinechangelink {
140-
background: url("../img/admin/edit-regular.svg") 0 0/14px 14px no-repeat;
182+
@include icon-override('../img/admin/edit-regular.svg');
141183
}
142184
.deletelink {
143-
background: url("../img/admin/trash-alt-regular.svg") 0 0/14px 14px no-repeat;
185+
background: url('../img/admin/trash-alt-regular.svg') 0 0/14px 14px no-repeat;
144186
}
145187
.datetimeshortcuts .clock-icon {
146-
background: url("../img/admin/clock-regular.svg") 0 0/14px 14px no-repeat !important;
188+
@include icon-override('../img/admin/clock-regular.svg');
189+
background: none !important;
147190
}
148191
.datetimeshortcuts .date-icon {
149-
background: url("../img/admin/calendar-alt-regular.svg") 0 0/14px 14px no-repeat !important;
192+
@include icon-override('../img/admin/calendar-alt-regular.svg');
193+
background: none !important;
150194
}
151195

152196
/**

src/objects/scss/admin/_app_overrides.scss

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ $djai-border-width: 8px;
3636
width: 100%;
3737

3838
/* Added to attach to body/breadcrumbs */
39-
border-bottom: $djai-border-width solid $color_secondary;
39+
border-bottom: var(--oz-djai-border-bottom-width) solid var(--oz-djai-border-bottom-color);
4040

4141
& &__drop {
4242
min-width: 250px !important;
@@ -70,6 +70,9 @@ $djai-border-width: 8px;
7070
}
7171
}
7272
}
73+
@at-root body.login #header {
74+
padding-bottom: 15px !important;
75+
}
7376
}
7477

7578
// TODO: check environment banner

src/objects/scss/admin/_vars.scss

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
/* Colors */
2-
$color-primary: #04a5bb;
3-
$color-primary-dark: #017092;
4-
$color-primary-light: #c3eaef;
2+
$color_primary: #04a5bb;
3+
$color_primary_dark: #017092;
4+
$color_primary_light: #c3eaef;
55

6-
$color-secondary: #f3f3f3;
7-
$color-secondary-dark: #ddd;
8-
$color-secondary-light: #fff;
6+
$color_secondary: #f3f3f3;
7+
$color_secondary_dark: #ddd;
8+
$color_secondary_light: #fff;
99

10-
$color-link: #017092;
11-
$color-link-hover: #051f31;
10+
$color_link: #017092;
11+
$color_link_hover: #051f31;
1212

13-
$color-darkest: #000;
14-
$color-dark: #333;
15-
$color-lightest: #fff;
13+
$color_darkest: #000;
14+
$color_dark: #333;
15+
$color_lightest: #fff;
1616

17-
$color-error: #ba2121; // default django admin color
17+
$color_error: #ba2121; // default django admin color
1818

19-
$color-tooltip-background: #fffeaa;
20-
$color-tooltip-border: #f7f071;
21-
$color-tooltip-text: #000;
19+
$color_tooltip_background: #fffeaa;
20+
$color_tooltip_border: #f7f071;
21+
$color_tooltip_text: #000;
2222

2323
/* Dimensions */
24-
$input-field-size: 20em; // django-original: 20em;
24+
$input_field_size: 20em; // django-original: 20em;
2525

2626
/* Responsive breakpoints used int the Django admin */
27-
$breakpoint-tablet: 768px;
28-
$breakpoint-laptop: 1025px;
27+
$breakpoint_tablet: 768px;
28+
$breakpoint_laptop: 1025px;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/* SPDX-License-Identifier: EUPL-1.2 */
2+
/* Copyright (C) 2025 Dimpact */
3+
/**
4+
* Dark theme implementation.
5+
*
6+
* Use this as:
7+
*
8+
* @use './themes/dark' as dark-theme;
9+
*
10+
* @include dark-theme.styles;
11+
*/
12+
13+
/**
14+
* Define the CSS properties overriding default admin theme.
15+
*/
16+
@mixin variables {
17+
--primary: #037383 !important;
18+
--secondary: #037383 !important;
19+
20+
--breadcrumbs-fg: #2fc0ec;
21+
--breadcrumbs-link-hover: #888;
22+
--breadcrumbs-bg: #333;
23+
24+
--link-fg: #04a5bb;
25+
--link-hover-color: #b2cddf;
26+
27+
--hairline-color: #686868;
28+
29+
--button-hover-bg: #04a5bb;
30+
--default-button-bg: #04a5bb;
31+
--default-button-hover-bg: #888;
32+
}
33+
34+
@mixin djai-variables {
35+
36+
// use a more specific selector so that the dark theme overrides the default,
37+
// less specific selector.
38+
.djai-dropdown-menu {
39+
--djai-tab-bg--hover: #04a5bb;
40+
--djai-tab-fg--active: #fff;
41+
--djai-dropdown-bg--hover: #04a5bb;
42+
43+
--oz-djai-border-bottom-color: #333;
44+
}
45+
}
46+
47+
@mixin bootstrap {
48+
49+
.btn,
50+
.btn:hover {
51+
color: var(--body-fg);
52+
}
53+
54+
pre {
55+
color: var(--body-fg);
56+
}
57+
}
58+
59+
60+
/**
61+
* Aggregate the bits and pieces to define the dark theme style rules.
62+
*/
63+
@mixin styles {
64+
65+
// Include the relevant variables
66+
@media (prefers-color-scheme: dark) {
67+
68+
// This either gets overridden by the more specific light theme selector, or applies
69+
// in auto mode through the media query.
70+
:root {
71+
@include variables;
72+
}
73+
74+
// only apply based on browser preferences if the theme is not explicitly set to
75+
// light or dark
76+
html[data-theme='auto'] {
77+
@include variables;
78+
@include djai-variables;
79+
@include bootstrap;
80+
}
81+
}
82+
83+
// explicit dark-mode -> apply all relevant styles
84+
html[data-theme='dark'] {
85+
@include variables;
86+
@include djai-variables;
87+
@include bootstrap;
88+
}
89+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* SPDX-License-Identifier: EUPL-1.2 */
2+
/* Copyright (C) 2025 Dimpact */
3+
/**
4+
* Light/default theme implementation.
5+
*
6+
* Use this as:
7+
*
8+
* @use './themes/light' as light-theme;
9+
*
10+
* @include light-theme.styles;
11+
*/
12+
13+
/**
14+
* Define the CSS properties overriding default admin theme.
15+
*
16+
* @todo - check if the !important's are still needed?
17+
*
18+
* See `admin/static/admin/css/base.css` for a reference of available variables.
19+
*/
20+
@mixin variables {
21+
--primary: #04a5bb !important;
22+
--accent: #f3f3f3;
23+
--secondary: #04a5bb !important;
24+
--primary-fg: #fff;
25+
26+
--header-color: #fff;
27+
28+
--breadcrumbs-fg: #04a5bb;
29+
--breadcrumbs-link-fg: var(--body-fg);
30+
--breadcrumbs-link-hover: #000; // not in the core django vars
31+
--breadcrumbs-bg: #f3f3f3;
32+
33+
--link-fg: #017092;
34+
--link-hover-color: #051f31;
35+
--link-selected-fg: #5b80b2;
36+
37+
// #748 client requested increased contrast for form-row borders
38+
// here we override a django admin style
39+
--hairline-color: #e5e5e5;
40+
41+
// --button-bg: var(--primary);
42+
--button-fg: #fff;
43+
--button-hover-bg: #017092;
44+
--default-button-bg: #017092;
45+
--default-button-hover-bg: #000;
46+
--close-button-bg: #888;
47+
--close-button-hover-bg: #333;
48+
49+
--object-tools-bg: #888;
50+
--object-tools-hover-bg: #333;
51+
}
52+
53+
@mixin djai-variables {
54+
--djai-tab-bg: var(--primary); // no fallback to default admin vars
55+
--djai-tab-bg--active: var(--breadcrumbs-bg);
56+
--djai-tab-bg--hover: #017092;
57+
--djai-tab-fg--active: var(--secondary);
58+
--djai-dropdown-bg--active: #017092;
59+
--djai-dropdown-bg--hover: #017092;
60+
61+
// custom properties
62+
--oz-djai-border-bottom-width: 8px;
63+
--oz-djai-border-bottom-color: #f3f3f3;
64+
}
65+
66+
/**
67+
* Aggregate the bits and pieces to define the light theme style rules.
68+
*
69+
* The light theme styles are not guarded by a media query to make sure they're the
70+
* default that is applied.
71+
*/
72+
@mixin styles {
73+
74+
html[data-theme='light'],
75+
:root {
76+
@include variables;
77+
}
78+
79+
// generic selector to be more specific than the library itself, but less specific
80+
// than the dark theme styles
81+
body {
82+
@include djai-variables;
83+
}
84+
}

src/objects/templates/admin/base_site.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313

1414
{% block branding %}
1515
<h1 id="site-name"><a href="{% url 'admin:index' %}">{{ settings.PROJECT_NAME }} {% trans 'Administration' %}</a></h1>
16+
17+
{% if user.is_anonymous %}
18+
{% include "admin/color_theme_toggle.html" %}
19+
{% endif %}
1620
{% endblock %}
1721

1822
{% block welcome-msg %}
@@ -35,6 +39,8 @@ <h1 id="site-name"><a href="{% url 'admin:index' %}">{{ settings.PROJECT_NAME }}
3539
{% csrf_token %}
3640
<button type="submit">{% trans 'Log out' %}</button>
3741
</form>
42+
43+
{% include "admin/color_theme_toggle.html" %}
3844
{% endblock %}
3945

4046
{% block nav-global %}{% endblock %}

0 commit comments

Comments
 (0)