View Issue Details

IDProjectCategoryView StatusLast Update
0012021Talermerchant portal webuipublic2026-11-10 23:43
Reporterbot-cg [agent] Assigned ToResolution deadline
ImplementerReviewer 
Release signed byDeployed by 
VerifierCommunicatorCM_7  
Data protection authority notification requiredNo  
CSIRT notification requiredNo  
Estimated effort (hours)Actual effort (hours)0 
Fast-trackNo
Work packagenone
PrioritynormalSeverityminorReproducibilityhave not tried
Status newResolutionopen 
Summary0012021: Merchant: Templates list 'Delete template' and 'Show QR' dialogs leave focus on the row menu behind them
DescriptionWhat happens:
Templates -> row '•••' -> 'Delete template' or 'Show QR' renders an inline <dialog open> (non-modal, no focus handling). RowActions hands focus back to its trigger, which is behind the overlay; Tab walks the page underneath.

Expected:
Delete confirmation: focus on Cancel (safe choice). QR preview: focus inside the dialog on Close.

Where:
  - packages/taler-merchant-webui/src/screens/TemplatesScreen.tsx:110
  - packages/taler-merchant-webui/src/screens/TemplatesScreen.tsx:318
  - packages/taler-merchant-webui/src/screens/TemplatesScreen.tsx:407

Measured in headless Chromium (document.activeElement):
  before: BUTTON 'Actions for Coffee' (behind the overlay) for both dialogs
  after: Delete: BUTTON 'Cancel'; QR: BUTTON 'Close' (QR shots: merchant-b--templates-list-qr-dialog--before/after.png)

Proposed fix:
Refs on the two buttons and one effect per dialog that focuses them when deletingTemplate / previewQrTemplate is set.

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 for file; screens.test.js passes; screenshots confirm
TagsNo tags attached.
Attached Files
merchant-b--templates-list-dialogs.diff (2,106 bytes)   
diff --git a/packages/taler-merchant-webui/src/screens/TemplatesScreen.tsx b/packages/taler-merchant-webui/src/screens/TemplatesScreen.tsx
index 4712104a6..c6139c75e 100644
--- a/packages/taler-merchant-webui/src/screens/TemplatesScreen.tsx
+++ b/packages/taler-merchant-webui/src/screens/TemplatesScreen.tsx
@@ -15,7 +15,7 @@
  */
 
 import type { VNode } from "preact";
-import { useState, useEffect } from "preact/hooks";
+import { useState, useEffect, useRef } from "preact/hooks";
 import { useLocation } from "wouter-preact";
 import { Header } from "../ui/Header.js";
 import { TalerQrCode } from "../ui/TalerQrCode.js";
@@ -104,6 +104,18 @@ export function TemplatesScreen({
     }
   };
 
+  // These dialogs are opened from a row's action menu, which hands focus back
+  // to its trigger behind the overlay. Move it into the dialog instead, onto
+  // the choice that changes nothing.
+  const deleteCancel = useRef<HTMLButtonElement>(null);
+  const qrClose = useRef<HTMLButtonElement>(null);
+  useEffect(() => {
+    if (deletingTemplate) deleteCancel.current?.focus();
+  }, [deletingTemplate]);
+  useEffect(() => {
+    if (previewQrTemplate) qrClose.current?.focus();
+  }, [previewQrTemplate]);
+
   useEffect(() => {
     if (!previewQrTemplate && !viewingTemplate && !deletingTemplate) return;
     const handleKeyDown = (e: KeyboardEvent) => {
@@ -303,6 +315,7 @@ export function TemplatesScreen({
             </p>
             <div class="flex items-center justify-end space-x-3 pt-2">
               <button
+                ref={deleteCancel}
                 type="button"
                 onClick={() => setDeletingTemplate(null)}
                 disabled={isDeleting}
@@ -391,6 +404,7 @@ export function TemplatesScreen({
                 {t`🖨 Print Sheet`}
               </button>
               <button
+                ref={qrClose}
                 type="button"
                 onClick={() => setPreviewQrTemplate(null)}
                 class="px-5 py-2 text-xs font-semibold rounded-md bg-gray-200 hover:bg-gray-300 text-gray-800 transition-colors cursor-pointer"

Required notifications

Address or linkRemarkAdded byNotifiedActions

Relationships

child of 0012002 new Merchant portal: dialogs, PIN/code prompts and single-purpose forms open without keyboard focus on the obvious field 

Activities

Issue History

Date ModifiedUsernameFieldChange
2026-11-10 23:41bot-cgNew Issue
2026-11-10 23:41bot-cgRelationship addedchild of 0012002
2026-11-10 23:43bot-cgFile Added: merchant-b--templates-list-dialogs.diff
2026-11-10 23:43bot-cgFile Added: merchant-b--templates-list-dialogs--before.png
2026-11-10 23:43bot-cgFile Added: merchant-b--templates-list-dialogs--after.png