From fb71854238c89c594fb908e9cbaca6e5d9f83211 Mon Sep 17 00:00:00 2001 From: Giorgio Gilestro Date: Wed, 27 May 2026 18:14:23 +0200 Subject: [PATCH] i18n: style the settings select + add a topbar lang toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two issues addressed: 1. The /settings language used in the Settings page. Native + * browser chrome stripped; we render a small chevron via crossed + * linear-gradients so the control matches the rest of the panel. */ +.settings-select { + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background: transparent; + border: 1px solid var(--border); + color: var(--text); + padding: 4px 28px 4px 8px; + font-family: var(--font-mono); + font-size: 12px; + border-radius: 2px; + cursor: pointer; + background-image: + linear-gradient(45deg, transparent 50%, var(--dim) 50%), + linear-gradient(-45deg, transparent 50%, var(--dim) 50%); + background-position: calc(100% - 13px) 50%, calc(100% - 9px) 50%; + background-size: 5px 5px, 5px 5px; + background-repeat: no-repeat; + transition: border-color 120ms ease-out, color 120ms ease-out; +} +.settings-select:hover, +.settings-select:focus { + outline: none; + border-color: var(--accent); + color: var(--text); +} +.settings-select option { color: var(--text); background: var(--surface); } +.settings-select option:disabled { color: var(--dim); } + +.settings-status { + font-family: var(--font-mono); + font-size: 11px; + color: var(--muted); + letter-spacing: 0.04em; +} +.settings-status:empty { display: none; } + /* Sections are
elements — collapsed by default to keep the settings page scannable. Click the summary to expand. */ .settings-section { diff --git a/app/templates/base.html b/app/templates/base.html index 9fdb0d1..29c8290 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -134,6 +134,34 @@ if (el && window.htmx) window.htmx.trigger(el, 'tone-changed'); }); }; + + window.cassandraSetLang = async function (newLang) { + var pill = document.getElementById('lang-toggle'); + if (!pill) return; + var prev = pill.dataset.lang; + if (prev === newLang) return; + // Optimistic update — flip the pill immediately so the click feels + // responsive. Revert on PATCH failure. + pill.dataset.lang = newLang; + try { + var r = await fetch('/api/settings/language', { + method: 'PATCH', + headers: {'Content-Type': 'application/json'}, + credentials: 'same-origin', + body: JSON.stringify({lang: newLang}), + }); + if (!r.ok) throw new Error('HTTP ' + r.status); + // Reload localized panels so the user immediately sees content + // in the new language (strategic log, dashboard header, etc.). + if (window.location.pathname === '/log' || + window.location.pathname.startsWith('/log/')) { + window.location.reload(); + } + } catch (e) { + pill.dataset.lang = prev; + console.warn('language switch failed:', e); + } + };