fix: Erntepost-Eingabefeld war auf 34 px zusammengedrueckt
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 2m13s

Regression aus dem vorigen Commit (Turnstile per Prop statt process.env):
sobald das CAPTCHA auf der Newsletter-Anmeldung tatsaechlich rendert, sprengt
es die Eingabezeile.

Das Formular war "flex flex-col sm:flex-row gap-3 max-w-lg" ohne flex-wrap,
und das Widget lag als dritter Eintrag in derselben Zeile. Ab 640 px teilten
sich damit Eingabefeld, Knopf und ein rund 300 px breites CAPTCHA eine Zeile
von 512 px. Auf wabenhain.com bei 1440 px nachgemessen: Eingabefeld 34x71,
Knopf 174x71, CAPTCHA 300x71.

Solange kein Sitekey ankam, fiel das nicht auf — das Widget erschien nie, die
Zeile hatte nur zwei Eintraege. Der Fehler lag also schon laenger im Markup
und wurde erst sichtbar, als das CAPTCHA wie vorgesehen erschien.

Jetzt bilden Eingabefeld und Knopf eine eigene Zeile, das CAPTCHA steht
darunter. Die Firmenanfrage ist nicht betroffen, sie stapelt ueber space-y-5.

Dazu zwei Einstellungen am Widget selbst, die von Anfang an gefehlt haben:

- language: Turnstile folgte der BROWSER-Sprache statt der Seitensprache. Auf
  der deutschen Seite stand englisch "Verify you are human".
- theme: "light": Turnstile folgte dem Farbschema des Betriebssystems. Wer es
  auf "dunkel" stehen hat, bekam einen schwarzen Kasten mitten in einen
  Abschnitt, den diese Seite ausschliesslich in Creme und Waldgruen zeichnet.
  Die Seite hat keinen Dunkelmodus, "auto" ist hier also immer falsch.

Beides betrifft alle Formulare, nicht nur den Newsletter.

tsc: 0 Fehler. vitest: 359/359 gruen. eslint: 0 Warnungen. next build: gruen.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5 committed 2026-09-20 04:44:09 +02:00
1 parent b9f92b5c0d
commit 256e823c4f
2 files changed
+22 -7

No files matched your search

+11 -5
View File
@@ -63,10 +63,15 @@ export function NewsletterSignup({ turnstileSiteKey }: { turnstileSiteKey?: stri
{status === "success" ? ( {status === "success" ? (
<p className="mt-8 text-forest">{t.home.newsletter.successMessage}</p> <p className="mt-8 text-forest">{t.home.newsletter.successMessage}</p>
) : ( ) : (
<form <form onSubmit={handleSubmit} className="mt-8 max-w-lg mx-auto">
onSubmit={handleSubmit} {/* Eingabefeld und Knopf bilden die Zeile, das CAPTCHA steht
className="mt-8 flex flex-col sm:flex-row gap-3 max-w-lg mx-auto" darunter. Frueher lagen alle drei in derselben Flex-Zeile
> ohne flex-wrap: sobald das Widget tatsaechlich rendert,
belegte es rund 300 px der 512 px breiten Zeile und drueckte
das Eingabefeld auf 34 px zusammen. Solange kein Sitekey
gesetzt war, fiel das nicht auf, weil das Widget gar nicht
erst erschien. */}
<div className="flex flex-col sm:flex-row gap-3">
<input <input
type="email" type="email"
required required
@@ -78,8 +83,9 @@ export function NewsletterSignup({ turnstileSiteKey }: { turnstileSiteKey?: stri
<Button type="submit" disabled={status === "loading"} className="flex-shrink-0 whitespace-nowrap"> <Button type="submit" disabled={status === "loading"} className="flex-shrink-0 whitespace-nowrap">
{status === "loading" ? t.home.newsletter.subscribing : t.home.newsletter.subscribe} {status === "loading" ? t.home.newsletter.subscribing : t.home.newsletter.subscribe}
</Button> </Button>
</div>
{turnstileSiteKey ? ( {turnstileSiteKey ? (
<div className="w-full flex justify-center"> <div className="mt-3 flex justify-center">
<TurnstileWidget siteKey={turnstileSiteKey} onVerify={setTurnstileToken} /> <TurnstileWidget siteKey={turnstileSiteKey} onVerify={setTurnstileToken} />
</div> </div>
) : null} ) : null}
+11 -2
View File
@@ -110,7 +110,7 @@ interface TurnstileWidgetProps {
* Wiederholung unten. * Wiederholung unten.
*/ */
export function TurnstileWidget({ siteKey, onVerify }: TurnstileWidgetProps) { export function TurnstileWidget({ siteKey, onVerify }: TurnstileWidgetProps) {
const { t } = useI18n(); const { t, locale } = useI18n();
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const widgetIdRef = useRef<string | null>(null); const widgetIdRef = useRef<string | null>(null);
const onVerifyRef = useRef(onVerify); const onVerifyRef = useRef(onVerify);
@@ -138,6 +138,15 @@ export function TurnstileWidget({ siteKey, onVerify }: TurnstileWidgetProps) {
setFailed(false); setFailed(false);
widgetIdRef.current = turnstile.render(containerRef.current, { widgetIdRef.current = turnstile.render(containerRef.current, {
sitekey: siteKey, sitekey: siteKey,
// Ohne diese beiden Angaben richtet sich Turnstile nach dem BROWSER
// des Besuchers statt nach der Seite: die Beschriftung folgte der
// Browsersprache (englisches "Verify you are human" auf einer
// deutschen Seite) und die Farbgebung dem Farbschema des
// Betriebssystems. Wer sein System auf "dunkel" stehen hat, bekam
// deshalb einen schwarzen Kasten mitten in einen Abschnitt, den
// diese Seite ausschliesslich in Creme und Waldgruen zeichnet.
language: locale,
theme: "light",
callback: (token: string) => onVerifyRef.current(token), callback: (token: string) => onVerifyRef.current(token),
// Ein abgelaufenes oder fehlgeschlagenes Token muss das Formular // Ein abgelaufenes oder fehlgeschlagenes Token muss das Formular
// erfahren, sonst schickt es ein laengst ungueltiges mit. // erfahren, sonst schickt es ein laengst ungueltiges mit.
@@ -164,7 +173,7 @@ export function TurnstileWidget({ siteKey, onVerify }: TurnstileWidgetProps) {
console.warn("[turnstile] Widget konnte nicht entfernt werden:", error); console.warn("[turnstile] Widget konnte nicht entfernt werden:", error);
} }
}; };
}, [siteKey, attempt]); }, [siteKey, attempt, locale]);
// "max-w-full overflow-x-auto" ist kein Schoenheitsmittel, sondern eine // "max-w-full overflow-x-auto" ist kein Schoenheitsmittel, sondern eine
// Zusicherung: Cloudflare liefert einen iframe mit FESTER Breite (rund // Zusicherung: Cloudflare liefert einen iframe mit FESTER Breite (rund