diff --git a/src/renderer.ts b/src/renderer.ts index 3693e7c..58a584c 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -689,14 +689,28 @@ function showAppToast(message: string, type: 'info' | 'warn' = 'info'): void { toast = document.createElement('div'); toast.id = 'appToast'; toast.className = 'app-toast'; + // Live region — screen readers announce the toast text whenever + // it changes. Warn toasts go through aria-live="assertive" so the + // reader interrupts whatever it was speaking; info toasts use + // "polite" so they wait for a natural break in current speech. + toast.setAttribute('role', 'status'); + toast.setAttribute('aria-live', 'polite'); + toast.setAttribute('aria-atomic', 'true'); document.body.appendChild(toast); } - toast.textContent = message; toast.classList.remove('warn', 'show'); if (type === 'warn') { toast.classList.add('warn'); + toast.setAttribute('role', 'alert'); + toast.setAttribute('aria-live', 'assertive'); + } else { + toast.setAttribute('role', 'status'); + toast.setAttribute('aria-live', 'polite'); } + // Setting textContent AFTER the aria-live attribute is in place + // ensures the change is captured as a live-region update by AT. + toast.textContent = message; requestAnimationFrame(() => { toast?.classList.add('show');