diff --git a/.Jules/palette.md b/.Jules/palette.md new file mode 100644 index 0000000..f2ea895 --- /dev/null +++ b/.Jules/palette.md @@ -0,0 +1,3 @@ +## 2026-02-18 - [Accessibility & Interaction Feedback] +**Learning:** Custom interactive elements (like cards used as buttons) must have proper ARIA roles, tabindex, and keyboard event handlers (Enter/Space) to be accessible. Additionally, async buttons should always provide visual loading states and use a `finally` block in JS to ensure the button is restored if the modal stays open or on error. +**Action:** Always check for `role="button"` and `tabindex="0"` on non-button interactive elements, and implement robust button state management for async calls. diff --git a/app/static/js/quickscan.js b/app/static/js/quickscan.js index 0b0b3f9..6ca91d5 100755 --- a/app/static/js/quickscan.js +++ b/app/static/js/quickscan.js @@ -1074,6 +1074,13 @@ const QuickScan = { return; } + const btn = document.getElementById('quickScanConfirmBtn'); + const originalHTML = btn ? btn.innerHTML : ''; + if (btn) { + btn.disabled = true; + btn.innerHTML = ' Verarbeitung...'; + } + try { // Daten für die API zusammenstellen const requestData = { @@ -1108,11 +1115,19 @@ const QuickScan = { } else { showQuickScanToast('success', data.message); this.reset(); - document.getElementById('quickScanModal').close(); + const modal = document.getElementById('quickScanModal'); + if (modal) modal.close(); } } catch (error) { console.error('Error:', error); showQuickScanToast('error', 'Ein Fehler ist aufgetreten'); + } finally { + if (btn) { + btn.disabled = false; + btn.innerHTML = originalHTML; + // Re-validate button state based on remaining inputs if modal wasn't closed + updateQuickScanButton(); + } } } }; diff --git a/app/templates/base.html b/app/templates/base.html index c376ba7..6b91edc 100755 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -203,6 +203,11 @@ box-shadow: 0 8px 20px rgba(0,0,0,0.2); } + #quickScanTrigger:focus-visible { + outline: 2px solid #4f46e5; + outline-offset: 2px; + } + /* Trennlinie */ .sidebar-divider { width: 85%; @@ -399,7 +404,7 @@

{% if current_user.is_authenticated %}