From 4945204b7b37b213a57e2309e7fe30b73997682a Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Mon, 25 May 2026 22:22:22 +0200 Subject: [PATCH] =?UTF-8?q?fix(tags):=20Firefox=20Android=20=E2=80=94=20En?= =?UTF-8?q?ter=20to=20commit=20now=20works?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The prior fix (a94a380) handled Chrome Android via the keydown path. Firefox Android does something different: the soft-keyboard Enter is intercepted at the input layer as "advance to next form field" — no keydown fires for us to intercept, so the user's tag was lost and focus jumped to the next ActivityForm input. Add an onbeforeinput handler. InputEvent.inputType === 'insertLineBreak' fires on every modern browser when the user submits via Enter, even when keydown is suppressed at the IME/keyboard layer. preventDefault'ing here cancels the focus-advance before it happens. Idempotent with the existing onKey: - Chrome: keydown fires with Enter, our preventDefault cancels the line-break, so beforeinput never fires. - Firefox Android: no keydown for Enter, beforeinput fires with insertLineBreak, we commit there. - Android Chrome with IME composition: composing flag short-circuits both paths so we don't commit mid-composition. Comma + button remain as platform-agnostic fallbacks. --- frontend/src/components/TagInput.svelte | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/frontend/src/components/TagInput.svelte b/frontend/src/components/TagInput.svelte index 671e669..5594b5b 100644 --- a/frontend/src/components/TagInput.svelte +++ b/frontend/src/components/TagInput.svelte @@ -81,6 +81,25 @@ add(input); } + /** + * beforeinput fires before the browser commits a value change. We use it + * to catch Enter on platforms where keydown doesn't deliver a usable + * Enter event — notably Firefox on Android, which treats the soft- + * keyboard Enter as "advance to next form field" at the input layer + * (no keydown for us to intercept). InputEvent.inputType === 'insertLineBreak' + * still fires here, so we get to preventDefault before focus moves. + * Idempotent with onKey: keydown's preventDefault on Chrome cancels + * the would-be insertion, so beforeinput never fires there. + */ + function onBeforeInput(e: Event) { + const ie = e as InputEvent; + if (composing) return; + if (ie.inputType === 'insertLineBreak') { + e.preventDefault(); + add(input); + } + } + function onType(e: Event) { input = (e.target as HTMLInputElement).value; clearTimeout(timer); @@ -118,6 +137,7 @@ value={input} oninput={onType} onkeydown={onKey} + onbeforeinput={onBeforeInput} oncompositionstart={() => (composing = true)} oncompositionend={() => (composing = false)} placeholder="Skriv etikett, trykk Enter eller «Legg til»"