Add theme toggle to login screen

This commit is contained in:
2026-09-19 00:04:04 +03:00
parent c8190b7eec
commit 393c333794
5 changed files with 190 additions and 13 deletions
+10
View File
@@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 60" role="img" aria-label="Eternity Project">
<circle cx="30" cy="30" r="22" fill="none" stroke="#e7e2d3" stroke-width="2"/>
<circle cx="21" cy="21" r="3" fill="#e4632c"/>
<circle cx="38" cy="26" r="2" fill="#8fae3d"/>
<circle cx="26" cy="40" r="2.5" fill="#e4632c"/>
<line x1="21" y1="21" x2="38" y2="26" stroke="#e7e2d3" stroke-width="1"/>
<line x1="21" y1="21" x2="26" y2="40" stroke="#e7e2d3" stroke-width="1"/>
<text x="66" y="30" font-family="'Space Grotesk','Helvetica Neue',sans-serif" font-size="24" font-weight="700" letter-spacing="1" fill="#e7e2d3">ETERNITY</text>
<text x="67" y="46" font-family="'DM Mono','Courier New',monospace" font-size="11" letter-spacing="2" fill="#a89a86">PROJECT / FI</text>
</svg>

After

Width:  |  Height:  |  Size: 793 B

+90
View File
@@ -32,6 +32,17 @@
--border-radius: 0;
}
html[data-theme="light"] {
--ink: #11212b;
--paper: #f1f1e9;
--acid: #c7ef4b;
--orange: #ff6b35;
--line: #b9c5bc;
--muted: #59706b;
--field: #fbfbf6;
--flash-error: #ffe3d9;
}
html,
body,
#layout,
@@ -49,6 +60,10 @@ body {
background-size: 70px 70px, 7px 7px;
}
html[data-theme="light"] body {
background-image: linear-gradient(90deg, transparent 49.5%, rgb(17 33 43 / 5%) 50%, transparent 50.5%), linear-gradient(rgb(17 33 43 / 4%) 1px, transparent 1px);
}
body > #layout,
#layout {
position: relative;
@@ -64,6 +79,10 @@ body > #layout,
background: rgb(22 18 16 / 82%);
}
html[data-theme="light"] #layout::before {
background: rgb(241 241 233 / 82%);
}
body a,
body .link,
#taskmenu a,
@@ -281,6 +300,77 @@ select:focus,
box-sizing: border-box;
}
/* Elastic's login controls use more specific component rules than the shared
form selectors above, so set the Wasteland surfaces at the login boundary. */
body.task-login,
body.task-login #layout-content,
body.task-login #login-form,
body.task-login #login-footer {
color: var(--ink);
}
body.task-login #login-form .form-control,
body.task-login #login-form .input-group-text,
body.task-login #login-form .input-group .icon {
background-color: var(--field) !important;
color: var(--ink) !important;
}
body.task-login #login-form .form-control::placeholder {
color: var(--muted);
opacity: 1;
}
.theme-toggle {
display: inline-flex;
align-items: center;
gap: 0.5rem;
margin-top: 1rem;
color: var(--muted);
cursor: pointer;
font-family: var(--font-family-monospace);
font-size: 11px;
letter-spacing: 0.5px;
text-transform: uppercase;
}
.theme-toggle input {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0 0 0 0);
}
.theme-toggle-track {
position: relative;
width: 2.5rem;
height: 1.25rem;
border: 1px solid var(--ink);
background: var(--field);
}
.theme-toggle-track::after {
content: "";
position: absolute;
top: 0.1875rem;
left: 0.1875rem;
width: 0.75rem;
height: 0.75rem;
background: var(--orange);
transition: transform 150ms ease, background-color 150ms ease;
}
.theme-toggle input:checked + .theme-toggle-track::after {
transform: translateX(1.25rem);
background: var(--acid);
}
.theme-toggle input:focus-visible + .theme-toggle-track {
outline: 3px solid var(--acid);
outline-offset: 2px;
}
body.task-login #messagestack {
top: auto;
bottom: 1rem;
+51
View File
@@ -0,0 +1,51 @@
<roundcube:include file="includes/layout.html" />
<script>
(function () {
var lightMode = document.cookie.indexOf('colorMode=light') > -1;
document.documentElement.setAttribute('data-theme', lightMode ? 'light' : 'dark');
}());
</script>
<h1 class="voice"><roundcube:object name="productname" /> <roundcube:label name="login" /></h1>
<div id="layout-content" class="selected no-navbar" role="main">
<roundcube:object name="logo" src="/images/logo.svg" id="logo" alt="Logo" />
<roundcube:form id="login-form" name="login-form" method="post" class="propform">
<roundcube:object name="loginform" form="login-form" size="40" submit=true class="form-control" />
<label class="theme-toggle" for="login-theme-toggle">
<input id="login-theme-toggle" type="checkbox" role="switch" aria-label="Use dark theme" checked>
<span class="theme-toggle-track" aria-hidden="true"></span>
<span class="theme-toggle-label">Dark mode</span>
</label>
<div id="login-footer" role="contentinfo">
<roundcube:object name="productname" condition="config:display_product_info &gt; 0" />
<roundcube:object name="version" condition="config:display_product_info == 2" />
<roundcube:if condition="config:support_url" />
&nbsp;&bull;&nbsp; <a href="<roundcube:var name='config:support_url' />" target="_blank" rel="noopener" class="support-link"><roundcube:label name="support" /></a>
<roundcube:endif />
<roundcube:container name="loginfooter" id="login-footer" />
</div>
</roundcube:form>
</div>
<script>
(function () {
var toggle = document.getElementById('login-theme-toggle');
var root = document.documentElement;
var darkMode = root.getAttribute('data-theme') !== 'light';
toggle.checked = darkMode;
toggle.addEventListener('change', function () {
var mode = toggle.checked ? 'dark' : 'light';
root.setAttribute('data-theme', mode);
document.cookie = 'colorMode=' + mode + '; path=/; max-age=31536000; samesite=lax';
});
}());
</script>
<noscript>
<p class="noscriptwarning"><roundcube:label name="noscriptwarning" /></p>
</noscript>
<roundcube:include file="includes/footer.html" />
+16 -2
View File
@@ -7,10 +7,24 @@
html, body { height: 100%; overflow: hidden; }
body {
background-color: #161210;
background-image: linear-gradient(90deg, transparent 49.5%, rgb(228 98 44 / 7%) 50%, transparent 50.5%), linear-gradient(rgb(228 98 44 / 5%) 1px, transparent 1px);
background-size: 70px 70px, 7px 7px;
background-image: url(images/logo.svg), linear-gradient(90deg, transparent 49.5%, rgb(228 98 44 / 7%) 50%, transparent 50.5%), linear-gradient(rgb(228 98 44 / 5%) 1px, transparent 1px);
background-position: center, 0 0, 0 0;
background-repeat: no-repeat, repeat, repeat;
background-size: 30%, 70px 70px, 7px 7px;
}
html[data-theme="light"] body {
background-color: #f1f1e9;
background-image: url(images/logo.svg), linear-gradient(90deg, transparent 49.5%, rgb(17 33 43 / 5%) 50%, transparent 50.5%), linear-gradient(rgb(17 33 43 / 4%) 1px, transparent 1px);
}
</style>
<script>
try {
if (document.cookie.indexOf('colorMode=light') > -1) {
document.documentElement.setAttribute('data-theme', 'light');
}
} catch (error) { }
</script>
</head>
<body></body>
</html>