feat: Refactor session management UI and enhance accessibility features

This commit is contained in:
Andre Beging
2025-10-07 15:33:45 +02:00
parent ddf29c1d36
commit f3b30d46c9
3 changed files with 85 additions and 23 deletions

View File

@@ -1,9 +1,10 @@
const sessionSectionEl = document.querySelector("#session-section");
const sessionStatusEl = document.querySelector("#session-status"); const sessionStatusEl = document.querySelector("#session-status");
const sessionUserEl = document.querySelector("#session-user"); const sessionUserEl = document.querySelector("#session-user");
const loginFeedbackEl = document.querySelector("#login-feedback"); const loginFeedbackEl = document.querySelector("#login-feedback");
const sessionSummaryTextEl = document.querySelector("#session-summary-text"); const sessionSummaryTextEl = document.querySelector("#session-summary-text");
const sessionDetailsEl = document.querySelector("#session-details");
const toggleSessionBtn = document.querySelector("#toggle-session"); const toggleSessionBtn = document.querySelector("#toggle-session");
const sessionCardToggleBtn = document.querySelector("#session-card-toggle");
const startLoginForm = document.querySelector("#start-login-form"); const startLoginForm = document.querySelector("#start-login-form");
const verifyLoginForm = document.querySelector("#verify-login-form"); const verifyLoginForm = document.querySelector("#verify-login-form");
const logoutButton = document.querySelector("#logout-button"); const logoutButton = document.querySelector("#logout-button");
@@ -18,8 +19,8 @@ const recentChatsListEl = document.querySelector("#recent-chats-list");
const closeRecentChatsBtn = document.querySelector("#close-recent-chats"); const closeRecentChatsBtn = document.querySelector("#close-recent-chats");
const recentChatsSearchEl = document.querySelector("#recent-chats-search"); const recentChatsSearchEl = document.querySelector("#recent-chats-search");
let sessionDetailsVisible = false; let sessionCardVisible = false;
let sessionDetailsTouched = false; let sessionCardTouched = false;
let createFormVisible = false; let createFormVisible = false;
let createFormTouched = false; let createFormTouched = false;
let lastFocusedElement = null; let lastFocusedElement = null;
@@ -39,15 +40,37 @@ if (recentChatsSearchEl) {
}); });
} }
function setSessionDetailsVisibility(show, { fromUser = false } = {}) { function setSessionCardVisibility(show, { fromUser = false } = {}) {
if (!toggleSessionBtn || !sessionDetailsEl) return; if (!sessionSectionEl || !sessionCardToggleBtn) return;
sessionDetailsVisible = show; sessionCardVisible = show;
if (fromUser) { if (fromUser) {
sessionDetailsTouched = true; sessionCardTouched = true;
} }
sessionDetailsEl.classList.toggle("hidden", !show); sessionSectionEl.classList.toggle("hidden", !show);
toggleSessionBtn.setAttribute("aria-expanded", String(show)); sessionCardToggleBtn.setAttribute("aria-expanded", String(show));
toggleSessionBtn.textContent = show ? "Hide session controls" : "Manage session"; sessionCardToggleBtn.setAttribute("aria-label", show ? "Hide session controls" : "Show session controls");
if (show && fromUser && toggleSessionBtn) {
toggleSessionBtn.focus({ preventScroll: true });
} else if (!show && fromUser) {
sessionCardToggleBtn.focus({ preventScroll: true });
}
updateSessionCardToggleLabel();
}
function updateSessionCardToggleLabel(status) {
if (!sessionCardToggleBtn) return;
const statusText = status?.authorized
? "Authorized"
: status?.code_sent
? "Awaiting code"
: status?.phone_number
? "Phone pending"
: status?.authorized === false
? "Not authorized"
: sessionStatusEl?.textContent?.trim() || "Status";
const statusColor = sessionStatusEl?.style?.color || "inherit";
sessionCardToggleBtn.innerHTML = `<span class="session-card-toggle-status" style="color: ${statusColor}">${statusText}</span><span class="session-card-toggle-text">Manage</span>`;
} }
function setCreateFormVisibility(show, { fromUser = false } = {}) { function setCreateFormVisibility(show, { fromUser = false } = {}) {
@@ -74,11 +97,17 @@ if (toggleCreateBtn) {
setCreateFormVisibility(false); setCreateFormVisibility(false);
} }
if (sessionCardToggleBtn) {
sessionCardToggleBtn.addEventListener("click", () => {
setSessionCardVisibility(!sessionCardVisible, { fromUser: true });
});
updateSessionCardToggleLabel();
}
if (toggleSessionBtn) { if (toggleSessionBtn) {
toggleSessionBtn.addEventListener("click", () => { toggleSessionBtn.addEventListener("click", () => {
setSessionDetailsVisibility(!sessionDetailsVisible, { fromUser: true }); setSessionCardVisibility(false, { fromUser: true });
}); });
setSessionDetailsVisibility(false);
} }
async function fetchJSON(url, options = {}) { async function fetchJSON(url, options = {}) {
@@ -150,12 +179,13 @@ function updateSessionUI(status) {
startLoginForm.classList.remove("hidden"); startLoginForm.classList.remove("hidden");
} }
const shouldShowDetails = !status.authorized || status.code_sent; if (!status.authorized || status.code_sent) {
if (!sessionDetailsTouched) { if (!sessionCardVisible) {
setSessionDetailsVisibility(shouldShowDetails); setSessionCardVisibility(true);
} else if (shouldShowDetails && !sessionDetailsVisible) {
setSessionDetailsVisibility(true);
} }
}
updateSessionCardToggleLabel(status);
setRecentChatsAvailability(status.authorized); setRecentChatsAvailability(status.authorized);
if (!status.authorized) { if (!status.authorized) {
closeRecentChatsDialog(); closeRecentChatsDialog();

View File

@@ -73,11 +73,28 @@ main {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
gap: 1rem; gap: 1rem;
flex-wrap: wrap;
} }
.helper-button { .helper-button {
min-width: 14rem; min-width: 14rem;
font-weight: 600; font-weight: 600;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.45rem;
}
.session-card-toggle-status {
display: inline-flex;
align-items: center;
font-weight: 600;
line-height: 1.1;
}
.session-card-toggle-text {
font-weight: 500;
color: var(--muted);
} }
.card { .card {
@@ -143,8 +160,7 @@ main {
} }
.session-toggle { .session-toggle {
align-self: center; align-self: flex-start;
white-space: nowrap;
} }
.session-details { .session-details {

View File

@@ -19,7 +19,7 @@
</header> </header>
<main> <main>
<section id="session-section" class="card" aria-label="Telegram session"> <section id="session-section" class="card hidden" aria-label="Telegram session">
<div class="session-summary"> <div class="session-summary">
<div class="session-summary-main"> <div class="session-summary-main">
<div class="session-status-row"> <div class="session-status-row">
@@ -27,11 +27,19 @@
<p id="session-summary-text" class="session-summary-text">Preparing session details…</p> <p id="session-summary-text" class="session-summary-text">Preparing session details…</p>
</div> </div>
</div> </div>
<button type="button" id="toggle-session" class="secondary session-toggle" aria-expanded="false"> <button
Manage session type="button"
id="toggle-session"
class="secondary icon-button session-toggle"
aria-label="Hide session controls"
>
<svg class="icon icon-close" viewBox="0 0 24 24" aria-hidden="true">
<path d="M18.3 5.71 12 12l6.3 6.29-1.41 1.42L10.59 13.4 4.3 19.71 2.89 18.3 9.17 12 2.89 5.71 4.3 4.3l6.3 6.29 6.29-6.3z" />
</svg>
<span class="sr-only">Hide session controls</span>
</button> </button>
</div> </div>
<div id="session-details" class="session-details hidden"> <div id="session-details" class="session-details">
<div id="session-user" class="user-info"></div> <div id="session-user" class="user-info"></div>
<div id="login-forms"> <div id="login-forms">
<form id="start-login-form" class="form-grid"> <form id="start-login-form" class="form-grid">
@@ -54,6 +62,14 @@
</section> </section>
<div class="helper-row"> <div class="helper-row">
<button
type="button"
id="session-card-toggle"
class="secondary helper-button"
aria-expanded="false"
>
Manage session
</button>
<button <button
type="button" type="button"
id="recent-chats-btn" id="recent-chats-btn"