first publish

This commit is contained in:
2026-09-06 17:21:52 +02:00
commit b8e41b4d55
147 changed files with 19367 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
"use client";
import { usePathname } from "next/navigation";
import { cn } from "@/lib/utils";
import { counterpart, langSwitch, otherLang, type Lang } from "@/lib/i18n";
import { TransitionLink } from "@/components/motion/TransitionLink";
/**
* Sprachumschalter im Kopf. Steht an der Stelle, an der vorher „Kontakt“ stand.
*
* Zeigt beide Sprachen: die aktive als stiller Zustand, die andere als Link auf das
* Gegenstück derselben Seite (`counterpart()`), nicht pauschal auf die Startseite.
*
* Zur Flagge: Eine Flagge steht für ein Land, nicht für eine Sprache deshalb steht
* neben ihr immer das Sprachkürzel, und der zugängliche Name nennt die Sprache
* ausgeschrieben. Wer die Flaggen weglassen will, entfernt hier zwei Zeilen.
*/
export function LangSwitch({ lang, className }: { lang: Lang; className?: string }) {
const pathname = usePathname() ?? "/";
const other = otherLang(lang);
const href = counterpart(pathname, other);
const base =
"inline-flex items-center gap-1.5 font-mono text-[11px] uppercase tracking-[0.14em] transition-colors duration-300";
return (
<div className={cn("flex items-center gap-2", className)}>
<span className={cn(base, "text-accent")} aria-current="true" title={langSwitch[lang].title}>
<Flag lang={lang} />
{langSwitch[lang].short}
</span>
<span aria-hidden="true" className="h-3 w-px bg-line" />
<TransitionLink
href={href}
label={langSwitch[other].label}
hrefLang={other}
aria-label={langSwitch[other].title}
className={cn(base, "-my-3 py-3 text-fg-muted hover:text-accent focus-visible:text-accent")}
>
<Flag lang={other} />
{langSwitch[other].short}
</TransitionLink>
</div>
);
}
/** 16 × 11 px, randlos, damit die Fahne neben 11-px-Versalien nicht dominiert. */
function Flag({ lang }: { lang: Lang }) {
const common = { width: 16, height: 11, viewBox: "0 0 16 11", "aria-hidden": true as const, className: "shrink-0" };
if (lang === "de") {
return (
<svg {...common}>
<rect width="16" height="11" fill="#0C0C0C" />
<rect y="3.667" width="16" height="3.667" fill="#DD0000" />
<rect y="7.334" width="16" height="3.666" fill="#FFCE00" />
</svg>
);
}
return (
<svg {...common}>
<rect width="16" height="11" fill="#012169" />
<path d="M0 0 16 11M16 0 0 11" stroke="#FFF" strokeWidth="2.2" />
<path d="M0 0 16 11M16 0 0 11" stroke="#C8102E" strokeWidth="1.1" />
<path d="M8 0v11M0 5.5h16" stroke="#FFF" strokeWidth="3.7" />
<path d="M8 0v11M0 5.5h16" stroke="#C8102E" strokeWidth="2.2" />
</svg>
);
}
export default LangSwitch;