fix(tags): tagging works on Android Chrome PWA
TagInput's onkeydown only commits on `e.key === 'Enter' || e.key === ','`. On Android Chrome with predictive text (GBoard et al), the soft keyboard keydown fires with `e.key === 'Unidentified'` and `e.keyCode === 229` during IME composition — the check misses entirely, the Enter never adds the tag, and the press instead bubbles up to the parent <form> and submits the whole activity. Result: impossible to tag from mobile. Fixes: - Track composition state via oncompositionstart / oncompositionend so we ignore commits while the IME is mid-composition. - Accept Enter via either `e.key === 'Enter'` OR `e.keyCode === 13` (and same for comma). preventDefault on every commit attempt so the parent form never submits accidentally. - Add an explicit "Legg til"-button next to the input. Foolproof mobile path — a tap is a tap, no IME involved. Desktop users still have Enter. - `enterkeyhint="done"` so the soft keyboard shows a sensible label on the action key. autocapitalize/autocorrect/spellcheck off so tags don't get mangled by autocomplete suggestions. Placeholder copy updated to mention the button.
This commit is contained in:
parent
5e5bf92afb
commit
a94a38071b
1 changed files with 48 additions and 9 deletions
|
|
@ -30,6 +30,13 @@
|
|||
let serverHits: { name: string; usage_count: number }[] = $state([]);
|
||||
let privateHits: { name: string; count: number }[] = $state([]);
|
||||
let timer: ReturnType<typeof setTimeout> | undefined;
|
||||
// True while the soft keyboard is composing (IME predictive text on
|
||||
// Android, hangul/kana/pinyin elsewhere). During composition keydown
|
||||
// fires with e.key === 'Unidentified' and e.keyCode === 229, so a naive
|
||||
// `e.key === 'Enter'` check misses the user's commit-and-press-enter
|
||||
// gesture. We commit on compositionend Enter via the addCurrent button
|
||||
// instead — see the keydown handler.
|
||||
let composing = $state(false);
|
||||
|
||||
function add(name: string) {
|
||||
const n = name.trim().toLowerCase();
|
||||
|
|
@ -48,7 +55,19 @@
|
|||
}
|
||||
|
||||
function onKey(e: KeyboardEvent) {
|
||||
if (e.key === 'Enter' || e.key === ',') {
|
||||
// Detect "commit" intent across desktop and mobile soft keyboards.
|
||||
// Android Chrome with predictive text fires keydown with key
|
||||
// 'Unidentified' + keyCode 229 during composition; Enter committed
|
||||
// afterwards still has keyCode 13 (or 'Enter'), so we accept either.
|
||||
// Comma is the same.
|
||||
if (composing) return;
|
||||
const isEnter = e.key === 'Enter' || e.keyCode === 13;
|
||||
const isComma = e.key === ',' || e.keyCode === 188;
|
||||
if (isEnter || isComma) {
|
||||
// Always preventDefault on Enter — without it the parent <form>
|
||||
// submits the whole activity when the user is just trying to add a
|
||||
// tag (especially noticeable on mobile where the soft keyboard's
|
||||
// "Done" key triggers form submit).
|
||||
e.preventDefault();
|
||||
add(input);
|
||||
} else if (e.key === 'Backspace' && !input && tags.length) {
|
||||
|
|
@ -56,6 +75,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
/** Called by the "Legg til"-button. The button is the foolproof mobile
|
||||
* path — IME composition can swallow Enter, but a tap is a tap. */
|
||||
function addCurrent() {
|
||||
add(input);
|
||||
}
|
||||
|
||||
function onType(e: Event) {
|
||||
input = (e.target as HTMLInputElement).value;
|
||||
clearTimeout(timer);
|
||||
|
|
@ -87,14 +112,28 @@
|
|||
{/each}
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
value={input}
|
||||
oninput={onType}
|
||||
onkeydown={onKey}
|
||||
placeholder="Legg til etikett, trykk Enter"
|
||||
aria-label="Ny etikett"
|
||||
/>
|
||||
<div class="row" style="gap: 0.4rem; align-items: stretch;">
|
||||
<input
|
||||
type="text"
|
||||
value={input}
|
||||
oninput={onType}
|
||||
onkeydown={onKey}
|
||||
oncompositionstart={() => (composing = true)}
|
||||
oncompositionend={() => (composing = false)}
|
||||
placeholder="Skriv etikett, trykk Enter eller «Legg til»"
|
||||
aria-label="Ny etikett"
|
||||
enterkeyhint="done"
|
||||
autocapitalize="none"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
style="flex: 1 1 auto; min-width: 0;"
|
||||
/>
|
||||
<button type="button" onclick={addCurrent} disabled={!input.trim()}
|
||||
aria-label="Legg til etikett"
|
||||
style="flex: 0 0 auto;">
|
||||
Legg til
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if serverHits.length || privateHits.length}
|
||||
<div class="card" style="margin-top: 0.25rem;" role="listbox" aria-label="Forslag">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue