View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0012051 | Taler | wallet (WebExtension) | public | 2026-11-10 23:42 | 2026-11-10 23:43 |
| Reporter | bot-cg [agent] | Assigned To | Resolution deadline | ||
| Implementer | Reviewer | ||||
| Release signed by | Deployed by | ||||
| Verifier | Communicator | CM_7 | |||
| Data protection authority notification required | No | ||||
| CSIRT notification required | No | ||||
| Estimated effort (hours) | Actual effort (hours) | 0 | |||
| Fast-track | No | ||||
| Work package | none | ||||
| Priority | normal | Severity | minor | Reproducibility | have not tried |
| Status | new | Resolution | open | ||
| Summary | 0012051: Wallet: 'Create payment' (merchant payment template) form does not focus the first editable field | ||||
| Description | What happens: Opening a taler://pay-template link shows 'Create payment - Enter the details requested by the merchant' (#/pay-template/:actionId). Nothing is focused. Measured on the 'payment-template' story: BODY. Expected: First field the merchant left for the payer: the amount if editable, otherwise the summary if editable (the currency select is prefilled; disabled fields are skipped). Where: - packages/wallet-webui/src/screens/PaymentTemplateScreen.tsx:40 Measured in headless Chromium (document.activeElement): before: BODY (nothing focused) after: INPUT (Amount) Proposed fix: Refs on the amount and summary inputs; effect keyed on the form being shown focuses the first editable one (preventScroll). `!loading && !error` hoisted into `formShown`. Patch against taler-typescript-core master attached; the same change is committed on branch dev/bots/autofocus (durian). Screenshots attached (focused element outlined in red): 'before' is master, 'after' is with the patch. Verified: tsc ok (0 errors in wallet-webui with workspace sources; plain `tsc --noEmit -p .` output identical to baseline, whose errors come from stale taler-util/wallet-core lib/); eslint + prettier clean on changed files; package tests screens/exchange-removal/payment-entry/routing bundled from src: 89/95 pass, the same 6 App-level demo tests fail before and after; scratch test covers amount-locked -> summary; screenshot of the story. | ||||
| Tags | No tags attached. | ||||
| Attached Files | wallet--payment-template.diff (2,635 bytes)
diff --git a/packages/wallet-webui/src/screens/PaymentTemplateScreen.tsx b/packages/wallet-webui/src/screens/PaymentTemplateScreen.tsx
index 19c179665..1552330aa 100644
--- a/packages/wallet-webui/src/screens/PaymentTemplateScreen.tsx
+++ b/packages/wallet-webui/src/screens/PaymentTemplateScreen.tsx
@@ -1,4 +1,4 @@
-import { useEffect, useState } from "preact/hooks";
+import { useEffect, useRef, useState } from "preact/hooks";
import { Button } from "../ui/Button.js";
import { Card } from "../ui/Card.js";
import { ErrorCard } from "../ui/ErrorCard.js";
@@ -37,6 +37,18 @@ export function PaymentTemplateScreen(props: {
}, [props.initialAmount, props.initialCurrency, props.initialSummary]);
const normalizedAmount = positiveAmountValue(currency, amount);
const valid = Boolean(normalizedAmount) && Boolean(summary.trim());
+ const amountInput = useRef<HTMLInputElement>(null);
+ const summaryInput = useRef<HTMLInputElement>(null);
+ const formShown = !props.loading && !props.error;
+ // Focus the first field the merchant left for the payer to fill in; the
+ // form only appears once the template has loaded.
+ useEffect(() => {
+ if (!formShown) return;
+ if (props.amountEditable)
+ amountInput.current?.focus({ preventScroll: true });
+ else if (props.summaryEditable)
+ summaryInput.current?.focus({ preventScroll: true });
+ }, [formShown, props.amountEditable, props.summaryEditable]);
return (
<div class="mx-auto w-full max-w-2xl space-y-6">
<div class="flex items-center gap-4">
@@ -67,7 +79,7 @@ export function PaymentTemplateScreen(props: {
</Card>
)}
{props.error && <ErrorCard error={props.error} />}
- {!props.loading && !props.error && (
+ {formShown && (
<form
class="space-y-5"
onSubmit={(event) => {
@@ -102,6 +114,7 @@ export function PaymentTemplateScreen(props: {
<span class="mb-1 block text-sm font-medium">{i18n.str`Amount`}</span>
<div class="flex rounded-xl border border-outline bg-surface focus-within:ring-2 focus-within:ring-primary">
<input
+ ref={amountInput}
inputMode="decimal"
disabled={!props.amountEditable}
value={amount}
@@ -124,6 +137,7 @@ export function PaymentTemplateScreen(props: {
}
</span>
<input
+ ref={summaryInput}
disabled={!props.summaryEditable}
value={summary}
onInput={(event) => setSummary(event.currentTarget.value)}
| ||||
| child of | 0012024 | new | Web UIs (bank, wallet, exchange AML/KYC, challenger, auditor, web-util forms): dialogs and single-purpose forms open without keyboard focus on the obvious field |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2026-11-10 23:42 | bot-cg | New Issue | |
| 2026-11-10 23:42 | bot-cg | Relationship added | child of 0012024 |
| 2026-11-10 23:43 | bot-cg | File Added: wallet--payment-template.diff | |
| 2026-11-10 23:43 | bot-cg | File Added: wallet--payment-template--before.png | |
| 2026-11-10 23:43 | bot-cg | File Added: wallet--payment-template--after.png |