feat(accessibility): add native keyboard dialogs and semantic account links (U08)

This commit is contained in:
2026-11-02 19:24:21 +01:00
parent 86a73b862a
commit 62e2b7dee8
23 changed files with 218 additions and 65 deletions
@@ -630,3 +630,14 @@ fieldset { min-width: 0; }
@keyframes toast-enter { from { transform: translateY(-2rem); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .app-toast { animation: none; } }
.input-rejection:empty { display: none; }
.app-modal { color: var(--color-text); max-height: calc(100dvh - 2rem); overflow-y: auto; }
.app-modal::backdrop { background: #0009; backdrop-filter: blur(3px); }
.dialog-actions { display: flex; gap: .5rem; flex-wrap: wrap; justify-content: flex-end; }
.account-card { display: block; width: 100%; color: inherit; text-decoration: none; }
:focus-visible { outline: 3px solid var(--color-accent); outline-offset: 3px; }
fieldset { border: 0; margin: 0; padding: 0; }
body:has(dialog[open]) .toast-stack:not(.modal-toasts) { display: none; }
.visually-hidden { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0,0,0,0) !important; white-space: nowrap !important; border: 0 !important; }
+13
View File
@@ -17,3 +17,16 @@
if (e.target.matches('[data-amount-guard]') && !accept(e.target, e.clipboardData.getData('text').trim())) e.preventDefault();
});
})();
window.duempelkasDialog = {
open(dialog, receiver) {
const opener = document.activeElement;
dialog.addEventListener('cancel', event => { event.preventDefault(); receiver.invokeMethodAsync('RequestCloseAsync'); });
dialog.addEventListener('close', () => { if (opener?.isConnected) opener.focus(); });
dialog.showModal();
const initial = dialog.querySelector('[data-safe-focus]') || dialog.querySelector('[data-initial-focus]') || dialog.querySelector('input,select,textarea,button');
initial?.focus();
},
close(dialog) { if (dialog?.open) dialog.close(); },
focus(dialog, selector) { dialog.querySelector(selector)?.focus(); }
};