Files
vans-diy-bastelbedarf/src/components/LanguageSwitcher.astro
T
qciganoandClaude Sonnet 5 28ded7faae Sprach- und Konto-Dropdown öffnen jetzt automatisch beim Drüberfahren
Bisher musste man auf "Deutsch ▾" bzw. das Konto-Menü in der Kopfzeile klicken,
damit sich das Untermenü öffnet. Jetzt reicht auf dem Desktop einfaches
Drüberfahren mit der Maus (mit kurzer Schließverzögerung beim Verlassen,
damit der Wechsel vom Button zum Menü nicht sofort wieder zuklappt) — Klick
funktioniert als Fallback für Touch-Geräte/Tastatur weiterhin ganz normal.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-03 17:37:51 +02:00

114 lines
4.3 KiB
Plaintext

---
import { locales, localeMeta, type Locale } from "../i18n/config";
interface Props {
lang: Locale;
/** Sprachneutraler Pfad der aktuellen Seite, z.B. "/shop/" oder "/produkt/foo/". */
path: string;
/** Seite existiert nur auf Deutsch (z.B. Rechtstexte) — alle Optionen führen zur DE-Version,
* damit der Umschalter niemals auf eine 404-Seite verlinkt. */
legalOnly?: boolean;
}
const { lang, path, legalOnly = false } = Astro.props;
function hrefFor(target: Locale) {
if (legalOnly) return path; // immer die deutsche Original-URL
const prefix = target === "de" ? "" : `/${target}`;
return `${prefix}${path}` || "/";
}
function globeStyle(l: Locale) {
const m = localeMeta[l];
return `--globe-color:${m.color}; --globe-glow:${m.glow}; --flag-1:${m.flag[0]}; --flag-2:${m.flag[1]}; --flag-3:${m.flag[2]}`;
}
---
<div class="lang-switch" id="lang-switch">
<button
type="button"
class="lang-switch-btn"
id="lang-switch-btn"
aria-haspopup="true"
aria-expanded="false"
style={globeStyle(lang)}
>
<span class="lang-globe" aria-hidden="true">
<span class="lang-globe-rotor">
<svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round">
<circle cx="12" cy="12" r="8.5" />
<ellipse cx="12" cy="12" rx="3.6" ry="8.5" />
<path d="M3.7 9.5h16.6M3.7 14.5h16.6" />
</svg>
</span>
</span>
<span class="lang-label">{localeMeta[lang].label}</span>
<span class="chevron">▼</span>
</button>
<div class="lang-switch-menu" role="menu">
{locales.map((l) => (
<a
href={hrefFor(l)}
role="menuitem"
aria-current={l === lang ? "true" : "false"}
title={legalOnly && l !== "de" ? "Nur auf Deutsch verfügbar / Only available in German" : undefined}
style={globeStyle(l)}
>
<span class="lang-globe" aria-hidden="true">
<span class="lang-globe-rotor">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round">
<circle cx="12" cy="12" r="8.5" />
<ellipse cx="12" cy="12" rx="3.6" ry="8.5" />
<path d="M3.7 9.5h16.6M3.7 14.5h16.6" />
</svg>
</span>
</span>
<span class="lang-label">{localeMeta[l].label}</span>
</a>
))}
</div>
</div>
<script>
// Jede Instanz für sich initialisieren (Desktop-Header + evtl. Mobile-Nav-Kopie).
document.querySelectorAll(".lang-switch").forEach((el) => {
const btn = el.querySelector(".lang-switch-btn");
btn?.addEventListener("click", (e) => {
e.stopPropagation();
document.querySelectorAll(".lang-switch.open").forEach((other) => {
if (other !== el) other.classList.remove("open");
});
el.classList.toggle("open");
btn.setAttribute("aria-expanded", el.classList.contains("open") ? "true" : "false");
});
// Öffnet zusätzlich automatisch beim Drüberfahren mit der Maus (Desktop) — kein Klick mehr
// nötig. Kurze Schließverzögerung beim Verlassen, damit der Wechsel von Button zu Menü nicht
// sofort wieder zuklappt. Klick bleibt als Fallback für Touch-Geräte/Tastatur erhalten.
let closeTimer: ReturnType<typeof setTimeout> | null = null;
el.addEventListener("mouseenter", () => {
if (closeTimer) { clearTimeout(closeTimer); closeTimer = null; }
document.querySelectorAll(".lang-switch.open").forEach((other) => {
if (other !== el) {
other.classList.remove("open");
other.querySelector(".lang-switch-btn")?.setAttribute("aria-expanded", "false");
}
});
el.classList.add("open");
btn?.setAttribute("aria-expanded", "true");
});
el.addEventListener("mouseleave", () => {
closeTimer = setTimeout(() => {
el.classList.remove("open");
btn?.setAttribute("aria-expanded", "false");
}, 200);
});
});
document.addEventListener("click", () => {
document.querySelectorAll(".lang-switch.open").forEach((el) => el.classList.remove("open"));
});
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") {
document.querySelectorAll(".lang-switch.open").forEach((el) => el.classList.remove("open"));
}
});
</script>