From 302d8b48c797b77743e6fadaae42b4f2cbe29735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Wed, 19 Aug 2026 10:42:35 +0000 Subject: [PATCH] wrap chain source, rescan and wallet-rename fields in real forms three input sites lived in a div instead of a form, so pressing enter did nothing and the button was the only way in. chain source url, rescan search depth, and the inline wallet-rename field all get a
, with every non-submit button in each marked type="button" (the rescan card's reset button was previously untyped, which would have submitted the form once wrapped). CoinsView.tsx has no text inputs (checkbox + buttons only) and SeedPhraseInput.tsx deliberately hijacks enter to advance between word boxes rather than submit, so both are left alone. Co-Authored-By: Claude Opus 5 --- web/ChainSourceCard.tsx | 16 ++++++++-------- web/RescanCard.tsx | 12 +++++++++--- web/WalletSettingsView.tsx | 12 ++++++------ 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/web/ChainSourceCard.tsx b/web/ChainSourceCard.tsx index 71d0c2f..9875be8 100644 --- a/web/ChainSourceCard.tsx +++ b/web/ChainSourceCard.tsx @@ -80,7 +80,9 @@ export const ChainSourceCard = () => { const busy = save.isPending || forget.isPending; const meta = KINDS[kind]; - const submit = async () => { + const submit = async (ev?: React.FormEvent) => { + ev?.preventDefault(); + if (!trimmed || !dirty || busy) return; setError(null); setHeight(null); try { @@ -111,7 +113,8 @@ export const ChainSourceCard = () => { }; return ( -
+ // Typing a URL and pressing return is what anyone does; a div full of inputs swallows it silently. +

Chain source

Where on-chain wallets read balances and history. It sees every address this wallet asks about, so your own node @@ -144,9 +147,6 @@ export const ChainSourceCard = () => { setUrl(ev.target.value)} - onKeyDown={(ev) => { - if (ev.key === 'Enter' && trimmed && dirty && !busy) void submit(); - }} placeholder={meta.placeholder} disabled={isLoading || busy} className="h-8 font-mono text-xs" @@ -155,12 +155,12 @@ export const ChainSourceCard = () => { spellCheck={false} />

- {data?.custom && ( - @@ -188,6 +188,6 @@ export const ChainSourceCard = () => { : `Using the built-in default (${data?.defaultUrl ?? '—'}), which rate-limits and can see every address you look up.`}{' '} {meta.hint}

-
+ ); }; diff --git a/web/RescanCard.tsx b/web/RescanCard.tsx index 128ebe6..4266777 100644 --- a/web/RescanCard.tsx +++ b/web/RescanCard.tsx @@ -37,8 +37,14 @@ export const RescanCard = ({ walletId }: RescanCardProps) => { const parsed = Number(gapLimit); const depth = gapLimit.trim() && Number.isInteger(parsed) && parsed > 0 ? parsed : null; + const submit = (ev?: React.FormEvent) => { + ev?.preventDefault(); + if (running || rescan.isPending) return; + rescan.mutate(depth ? { gapLimit: depth } : {}); + }; + return ( -
+

Find missing coins

@@ -50,9 +56,9 @@ export const RescanCard = ({ walletId }: RescanCardProps) => {
{state && } -
+ ); }; diff --git a/web/WalletSettingsView.tsx b/web/WalletSettingsView.tsx index add0802..4633032 100644 --- a/web/WalletSettingsView.tsx +++ b/web/WalletSettingsView.tsx @@ -206,7 +206,8 @@ const WalletNameField = ({ wallet, onSave, isPending }: WalletNameFieldProps) => const trimmed = draft.trim(); const dirty = trimmed !== wallet.name; - const commit = async () => { + const commit = async (ev?: React.FormEvent) => { + ev?.preventDefault(); if (!trimmed || !dirty) { setDraft(wallet.name); setEditing(false); @@ -242,7 +243,7 @@ const WalletNameField = ({ wallet, onSave, isPending }: WalletNameFieldProps) => } return ( -
+
disabled={isPending} onChange={(ev) => setDraft(ev.target.value)} onKeyDown={(ev) => { - if (ev.key === 'Enter') void commit(); if (ev.key === 'Escape') cancel(); }} className="h-7 max-w-56 text-sm font-semibold" @@ -259,13 +259,13 @@ const WalletNameField = ({ wallet, onSave, isPending }: WalletNameFieldProps) => autoComplete="off" spellCheck={false} /> - - -
+ ); };