a11y(dialog): ARIA-Rolle, Fokus-Falle und Fokus-Rueckgabe ergaenzt ohne Escape/Initial-Fokus zu doppeln

This commit is contained in:
2026-06-13 20:59:39 +02:00
parent 0a93340792
commit 085cca2812
+20
View File
@@ -40,23 +40,30 @@ const HellionDialog = {
*/ */
_show(config) { _show(config) {
return new Promise(resolve => { return new Promise(resolve => {
const prevFocus = document.activeElement;
const overlay = document.createElement('div'); const overlay = document.createElement('div');
overlay.className = 'dialog-overlay'; overlay.className = 'dialog-overlay';
const box = document.createElement('div'); const box = document.createElement('div');
box.className = 'dialog-box'; box.className = 'dialog-box';
box.setAttribute('role', config.isConfirm ? 'alertdialog' : 'dialog');
box.setAttribute('aria-modal', 'true');
box.setAttribute('aria-labelledby', 'dialogTitle');
box.setAttribute('aria-describedby', 'dialogBody');
// Header // Header
const header = document.createElement('div'); const header = document.createElement('div');
header.className = 'dialog-header'; header.className = 'dialog-header';
header.appendChild(this._createIcon(config.type)); header.appendChild(this._createIcon(config.type));
const titleSpan = document.createElement('span'); const titleSpan = document.createElement('span');
titleSpan.id = 'dialogTitle';
titleSpan.textContent = config.title; titleSpan.textContent = config.title;
header.appendChild(titleSpan); header.appendChild(titleSpan);
// Body // Body
const body = document.createElement('div'); const body = document.createElement('div');
body.className = 'dialog-body'; body.className = 'dialog-body';
body.id = 'dialogBody';
body.textContent = config.message; body.textContent = config.message;
// Actions // Actions
@@ -69,6 +76,7 @@ const HellionDialog = {
overlay.classList.remove('active'); overlay.classList.remove('active');
overlay.remove(); overlay.remove();
}); });
if (prevFocus && typeof prevFocus.focus === 'function') prevFocus.focus();
resolve(result); resolve(result);
} }
@@ -106,6 +114,18 @@ const HellionDialog = {
e.preventDefault(); e.preventDefault();
cleanup(config.isConfirm ? false : undefined); cleanup(config.isConfirm ? false : undefined);
} }
if (e.key === 'Tab') {
// Fokus-Falle: nur die Buttons im actions-Container sind fokussierbar
const items = Array.from(actions.querySelectorAll('button'));
if (items.length === 0) return;
const first = items[0];
const last = items[items.length - 1];
if (e.shiftKey && document.activeElement === first) {
e.preventDefault(); last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault(); first.focus();
}
}
} }
document.addEventListener('keydown', keyHandler); document.addEventListener('keydown', keyHandler);