fix(a11y): gate always-mounted sheet dialog semantics on open state

ContextSheet and UploadSheet stay mounted (slid off-screen via translate-y) when
closed, but declared role="dialog" + aria-modal="true" — and kept their buttons
in the a11y tree + tab order — unconditionally. So a screen reader always saw
2+ simultaneous modal dialogs, and their controls (e.g. each sheet's "Abbrechen")
collided with real open dialogs.

Surfaced by the e2e a11y suite: focus-trap asserted exactly one [role=dialog]
[aria-modal] and got 2; upload-cancel-confirm's getByRole('button',{name:
'Abbrechen'}) matched the composer's X *and* a closed sheet's button.

Fix: when closed, drop role/aria-modal and mark the subtree aria-hidden + inert
so it's out of the a11y tree and tab order entirely. Open sheets are unchanged.

Verified: chromium-mobile a11y/gesture suite now 21 passed / 5 skipped / 0 a11y
failures (focus-trap + upload-cancel-confirm green); svelte-check 0 errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
fabi
2026-06-30 21:23:05 +02:00
parent 1c7495e568
commit b32231d4f4
2 changed files with 8 additions and 4 deletions

View File

@@ -103,8 +103,10 @@
class:translate-y-full={!open} class:translate-y-full={!open}
class:translate-y-0={open} class:translate-y-0={open}
style="padding-bottom: env(safe-area-inset-bottom)" style="padding-bottom: env(safe-area-inset-bottom)"
role="dialog" role={open ? 'dialog' : undefined}
aria-modal="true" aria-modal={open ? 'true' : undefined}
aria-hidden={!open}
inert={!open}
tabindex="-1" tabindex="-1"
> >
<div class="flex justify-center pt-3 pb-1"> <div class="flex justify-center pt-3 pb-1">

View File

@@ -136,9 +136,11 @@
class:translate-y-full={!open} class:translate-y-full={!open}
class:translate-y-0={open} class:translate-y-0={open}
style="padding-bottom: env(safe-area-inset-bottom)" style="padding-bottom: env(safe-area-inset-bottom)"
role="dialog" role={open ? 'dialog' : undefined}
aria-modal="true" aria-modal={open ? 'true' : undefined}
aria-label="Hochladen" aria-label="Hochladen"
aria-hidden={!open}
inert={!open}
tabindex="-1" tabindex="-1"
> >
<!-- Drag handle --> <!-- Drag handle -->