Reputation: 691
In my TALL (+Fillament) stack app, I have a multi-step modal dialog using Alpine.js and Filament UI components. While the visual focus correctly moves between steps, screen readers aren't properly announcing the content of the new step.
When a user clicks "Next" to advance to a new step, the browser focus (orange border) correctly moves to the heading of the next step, but the screen reader announces "Chrome unresponsive" before getting cut off and saying "group". The screen reader focus starts on the Back button instead of the heading content.
Here's the relevant part of my implementation:
<div x-data="{ page: 1 }">
<x-filament::modal
role="dialog"
aria-labelledby="modal-title"
aria-describedby="modal-content"
id="protect-the-trust"
width="lg"
footerActionsAlignment="right"
aria-label="Request Policy Agreement">
<!-- Modal heading -->
<x-slot name="heading" aria-hidden="true">
<h2 id="modal-title" class="text-lg font-bold" tabindex="-1">Protect the Trust</h2>
</x-slot>
<div id="modal-content" class="flex flex-col">
<!-- One of the steps (simplified for clarity) -->
<div x-show="page == 3" role="region" aria-labelledby="step3-heading" id="step3-content" x-cloak>
<h3 id="step3-heading" class="font-medium" tabindex="-1">CarePortal Appropriate (Step 3/3)</h3>
<!-- Step content here -->
</div>
</div>
<!-- Navigation buttons -->
<x-slot name="footerActions">
<div x-show="page == 2" x-cloak>
<x-filament::button color="gray" x-on:click="page = 1; $nextTick(() => document.getElementById('step1-heading').focus())">Back</x-filament::button>
<x-filament::button x-on:click="page = 3; $nextTick(() => document.getElementById('step3-heading').focus())" dusk="protectTheTrustIAgreePage2">Next</x-filament::button>
</div>
</x-slot>
</x-filament::modal>
</div>
I'm using $nextTick()
to focus the heading of the next step after changing pages:
x-on:click="page = 3; $nextTick(() => document.getElementById('step3-heading').focus())"
I've added tabindex="-1"
to the headings to make them focusable, and set up proper ARIA attributes:
role="region"
on each step containeraria-labelledby
pointing to the headingx-cloak
to hide inactive stepsThe visual focus works correctly (I can see the orange focus outline on the heading), but screen readers aren't announcing the heading content and are focusing on the Back button instead.
How can I ensure that when navigating between steps in an Alpine.js modal, screen readers correctly focus on and announce the heading of each new step? Is there something I'm missing in my ARIA implementation or focus management approach?
Upvotes: 0
Views: 29