Shrink UI controls and iconize language/edit/delete

This commit is contained in:
2026-02-04 15:25:04 +01:00
parent b91d8a42d3
commit 534fc41d33
4 changed files with 94 additions and 21 deletions

View File

@@ -45,13 +45,10 @@ function setupHandlers() {
loginUser.addEventListener("blur", () => { delete loginUser.dataset.userEditing; }); loginUser.addEventListener("blur", () => { delete loginUser.dataset.userEditing; });
} }
const langSelects = Array.from(document.querySelectorAll(".lang-select")); setupLanguageSwitchers();
const syncLanguageSelects = () => langSelects.forEach((sel) => (sel.value = getLanguage()));
syncLanguageSelects();
langSelects.forEach((sel) => sel.addEventListener("change", () => setLanguage(sel.value)));
onLanguageChange(() => { onLanguageChange(() => {
syncLanguageSelects(); updateLanguageButtons();
renderWelcome(); renderWelcome();
renderPhasePill(); renderPhasePill();
renderCounts(); renderCounts();
@@ -212,3 +209,47 @@ async function main() {
} }
main(); main();
function languageEmoji(lang) {
const map = { en: "🇬🇧", de: "🇩🇪" };
return map[lang] || "🌐";
}
function updateLanguageButtons() {
document.querySelectorAll(".lang-button").forEach((btn) => {
btn.textContent = languageEmoji(getLanguage());
btn.title = t("lang.label");
btn.setAttribute("aria-label", t("lang.label"));
});
}
function setupLanguageSwitchers() {
const switches = document.querySelectorAll(".lang-switch");
const closeAll = () =>
switches.forEach((wrap) => wrap.querySelector(".lang-menu")?.classList.add("hidden"));
switches.forEach((wrap) => {
const btn = wrap.querySelector(".lang-button");
const menu = wrap.querySelector(".lang-menu");
if (!btn || !menu) return;
btn.addEventListener("click", (e) => {
e.preventDefault();
const isHidden = menu.classList.contains("hidden");
closeAll();
if (isHidden) menu.classList.remove("hidden");
});
menu.querySelectorAll("[data-lang]").forEach((item) =>
item.addEventListener("click", () => {
const lang = item.dataset.lang;
if (lang) setLanguage(lang);
closeAll();
}),
);
});
document.addEventListener("click", (e) => {
if (!e.target.closest(".lang-switch")) closeAll();
});
updateLanguageButtons();
}

View File

@@ -21,11 +21,13 @@
<h2 id="auth-title" data-i18n="auth.loginHeading">Log in</h2> <h2 id="auth-title" data-i18n="auth.loginHeading">Log in</h2>
</div> </div>
<div class="stack lang-field"> <div class="stack lang-field">
<span class="label" data-i18n="lang.label">Language</span> <div class="lang-switch" id="lang-switch-auth">
<select class="lang-select"> <button class="lang-button" type="button" aria-label="Language" title="Language">🌐</button>
<option value="en" data-i18n="lang.en">English</option> <div class="lang-menu hidden">
<option value="de" data-i18n="lang.de">Deutsch</option> <button type="button" data-lang="en">🇬🇧 English</button>
</select> <button type="button" data-lang="de">🇩🇪 Deutsch</button>
</div>
</div>
</div> </div>
<form id="login-form" class="stack auth-form" data-mode="login"> <form id="login-form" class="stack auth-form" data-mode="login">
<label class="stack"> <label class="stack">
@@ -74,11 +76,13 @@
<span class="counts" id="counts"></span> <span class="counts" id="counts"></span>
</div> </div>
<div class="status-right"> <div class="status-right">
<span class="label" data-i18n="lang.label">Language</span> <div class="lang-switch" id="lang-switch-status">
<select class="lang-select compact-select"> <button class="lang-button" type="button" aria-label="Language" title="Language">🌐</button>
<option value="en" data-i18n="lang.en">English</option> <div class="lang-menu hidden">
<option value="de" data-i18n="lang.de">Deutsch</option> <button type="button" data-lang="en">🇬🇧 English</button>
</select> <button type="button" data-lang="de">🇩🇪 Deutsch</button>
</div>
</div>
</div> </div>
</section> </section>

View File

@@ -317,8 +317,8 @@ export function buildCard(
<h3 class="card-title" title="${s.name}">${s.name}</h3> <h3 class="card-title" title="${s.name}">${s.name}</h3>
<div class="title-meta"> <div class="title-meta">
${showAuthor && s.author ? `<span class="chip">${s.author}</span>` : ""} ${showAuthor && s.author ? `<span class="chip">${s.author}</span>` : ""}
${allowEdit ? `<button class="chip" data-edit="${s.id}" type="button">${t("card.edit")}</button>` : ""} ${allowEdit ? `<button class="chip" data-edit="${s.id}" type="button" title="${t("card.edit")}">✏️</button>` : ""}
${allowDelete ? `<button class="chip danger-chip" data-delete="${s.id}" type="button">${t("card.delete")}</button>` : ""} ${allowDelete ? `<button class="chip danger-chip" data-delete="${s.id}" type="button" title="${t("card.delete")}">🗑️</button>` : ""}
</div> </div>
</div> </div>
${hasExtraInfo ? `<p class="muted">` : ""} ${hasExtraInfo ? `<p class="muted">` : ""}

View File

@@ -48,11 +48,39 @@ html {
.lang-field { .lang-field {
margin-top: 8px; margin-top: 8px;
} }
.lang-field select { .lang-switch {
min-width: 160px; position: relative;
} }
.compact-select { .lang-button {
min-width: 120px; border: 1px solid #d5c7b5;
background: #fffaf3;
border-radius: 10px;
padding: 6px 10px;
font-size: 16px;
cursor: pointer;
min-width: 44px;
}
.lang-menu {
position: absolute;
right: 0;
top: calc(100% + 6px);
background: #fffaf3;
border: 1px solid #e3d4bd;
border-radius: 10px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
padding: 6px;
display: flex;
flex-direction: column;
gap: 4px;
z-index: 50;
}
.lang-menu button {
border: 1px solid #d5c7b5;
background: #ffffff;
border-radius: 8px;
padding: 6px 10px;
text-align: left;
cursor: pointer;
} }
.status-bar { .status-bar {