further things around login
This commit is contained in:
@@ -550,6 +550,59 @@
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* ── Logo ── */
|
||||
|
||||
.login-logo {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.login-logo-img {
|
||||
max-height: 2.5rem;
|
||||
max-width: 10rem;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
/* ── Password toggle ── */
|
||||
|
||||
.login-password-wrapper {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.login-password-wrapper > input {
|
||||
padding-right: 2.75rem;
|
||||
}
|
||||
|
||||
.login-password-toggle {
|
||||
position: absolute;
|
||||
right: 0.5rem;
|
||||
top: calc(50% - 8px);
|
||||
transform: translateY(-50%);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: var(--app-muted-color);
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
border-radius: var(--app-border-radius);
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
.login-password-toggle:hover {
|
||||
color: var(--app-contrast);
|
||||
}
|
||||
|
||||
.login-password-toggle:focus-visible {
|
||||
outline: 2px solid var(--app-primary-focus);
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
main.login-main {
|
||||
min-height: 100dvh;
|
||||
display: grid;
|
||||
@@ -693,7 +746,7 @@
|
||||
display: inline-block;
|
||||
padding: 0 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--app-muted);
|
||||
color: var(--app-muted-color);
|
||||
background: var(--app-card-background-color);
|
||||
}
|
||||
|
||||
@@ -754,14 +807,6 @@
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.login-tenant-context-title {
|
||||
margin: 0;
|
||||
font-size: 0.78rem;
|
||||
letter-spacing: 0.02em;
|
||||
text-transform: uppercase;
|
||||
color: var(--app-muted);
|
||||
}
|
||||
|
||||
.login-tenant-context-name {
|
||||
margin: 0;
|
||||
font-size: 11px;
|
||||
@@ -788,6 +833,8 @@
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
gap: 10px;
|
||||
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
|
||||
@@ -798,20 +845,10 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.login-help-links-item + .login-help-links-item::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 1px;
|
||||
height: 0.85em;
|
||||
margin-right: 0.8rem;
|
||||
background: color-mix(in srgb, var(--app-muted) 55%, transparent);
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
.login-security-note {
|
||||
font-size: 0.72rem;
|
||||
margin-bottom: 1px;
|
||||
color: color-mix(in srgb, var(--app-contrast) 78%, var(--app-muted));
|
||||
color: color-mix(in srgb, var(--app-contrast) 78%, var(--app-muted-color));
|
||||
}
|
||||
|
||||
.login-security-note i {
|
||||
@@ -823,7 +860,7 @@
|
||||
width: 100%;
|
||||
display: block;
|
||||
font-size: 9px;
|
||||
color: color-mix(in srgb, var(--app-muted) 75%, transparent);
|
||||
color: color-mix(in srgb, var(--app-muted-color) 75%, transparent);
|
||||
}
|
||||
|
||||
form[aria-busy="true"] button[type="submit"],
|
||||
@@ -832,10 +869,6 @@
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
.login-secondary-action {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html[data-theme="dark"] #gradient {
|
||||
animation: none;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import './core/app-telemetry.js';
|
||||
import './components/app-flash-auto-dismiss.js';
|
||||
import './components/app-password-hints.js';
|
||||
import './components/app-password-toggle.js';
|
||||
|
||||
const focusPrimaryErrorNotice = () => {
|
||||
const errorNotice = document.querySelector(
|
||||
@@ -29,6 +30,7 @@ const lockLoginSubmitButtons = () => {
|
||||
return;
|
||||
}
|
||||
submitButton.disabled = true;
|
||||
submitButton.setAttribute('aria-busy', 'true');
|
||||
submitButton.dataset.submitState = 'loading';
|
||||
});
|
||||
});
|
||||
|
||||
40
web/js/components/app-password-toggle.js
Normal file
40
web/js/components/app-password-toggle.js
Normal file
@@ -0,0 +1,40 @@
|
||||
export function initPasswordToggles() {
|
||||
const inputs = document.querySelectorAll('input[type="password"]');
|
||||
if (!inputs.length) {return;}
|
||||
|
||||
inputs.forEach((input) => {
|
||||
if (!(input instanceof HTMLInputElement)) {return;}
|
||||
const label = input.closest('label');
|
||||
if (!label) {return;}
|
||||
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'login-password-wrapper';
|
||||
|
||||
const toggle = document.createElement('button');
|
||||
toggle.type = 'button';
|
||||
toggle.className = 'login-password-toggle';
|
||||
toggle.setAttribute('aria-label', 'Show password');
|
||||
toggle.tabIndex = -1;
|
||||
toggle.innerHTML = '<i class="bi bi-eye" aria-hidden="true"></i>';
|
||||
|
||||
input.replaceWith(wrapper);
|
||||
wrapper.appendChild(input);
|
||||
wrapper.appendChild(toggle);
|
||||
|
||||
toggle.addEventListener('click', () => {
|
||||
const isPassword = input.type === 'password';
|
||||
input.type = isPassword ? 'text' : 'password';
|
||||
toggle.innerHTML = isPassword
|
||||
? '<i class="bi bi-eye-slash" aria-hidden="true"></i>'
|
||||
: '<i class="bi bi-eye" aria-hidden="true"></i>';
|
||||
toggle.setAttribute('aria-label', isPassword ? 'Hide password' : 'Show password');
|
||||
input.focus();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initPasswordToggles);
|
||||
} else {
|
||||
initPasswordToggles();
|
||||
}
|
||||
Reference in New Issue
Block a user