Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autofocus in modals forcing screenreaders to the end of the modal #854

Open
3 tasks done
stuininga1 opened this issue Dec 12, 2024 · 2 comments
Open
3 tasks done

Comments

@stuininga1
Copy link

Flux version

1.0.23

Livewire version

3.5.12

What is the problem?

When you use a Flux modal, it autofocuses whatever is actionable (like an input or a button) within the modal. This makes sense for a sighted user who can read the modal's content then proceed to interact with whatever actionable element is focused. However for a screenreader, unless the actionable element is the absolute first one in the modal the autofocus skips them over the regular flow in the modal. This means that in order to fully read a modal screenreaders have to scan backwards from the actionable element to any text elements (like headings or paragraphs) then navigate forward again which isn't very accessible since people with vision impairments can't see that there's more content to navigate to.

Originally reported in this discussion thread: #796 (reply in thread)

Code snippets

On the site I'm trying to meet accessibility on, I have modals with a heading, text, then an action button at the bottom. However because of the autofocus functionality the user is automatically being forced to the bottom of my modal. You should be able to recreate this with any Flux modal with both text elements and actionable items, but since this ask for how to reproduce it, this is the exact code I've been using when testing this issue:

I've customized the modal component to allow me to have my close action as a button instead of a standard x (only change is to the close button section)

<ui-modal {{ $attributes }} data-flux-modal>
    <?php if ($trigger): ?>
        {{ $trigger }}
    <?php endif; ?>

    <dialog
        wire:ignore.self {{-- This needs to be here because the dialog element adds a "close" attribute that isn't durable... --}}
        {{ $styleAttributes->class($classes) }}
        @if ($name) data-modal="{{ $name }}" @endif
        @if ($variant === 'flyout') data-flux-flyout @endif
        x-data
        @isset($__livewire)
            x-on:modal-show.document="
                if ($event.detail.name === @js($name) && ($event.detail.scope === @js($__livewire->getId()))) $el.showModal();
                if ($event.detail.name === @js($name) && (! $event.detail.scope)) $el.showModal();
            "
            x-on:modal-close.document="
                if ($event.detail.name === @js($name) && ($event.detail.scope === @js($__livewire->getId()))) $el.close();
                if (! $event.detail.name || ($event.detail.name === @js($name) && (! $event.detail.scope))) $el.close();
            "
        @else
            x-on:modal-show.document="if ($event.detail.name === @js($name) && (! $event.detail.scope)) $el.showModal()"
            x-on:modal-close.document="if (! $event.detail.name || ($event.detail.name === @js($name) && (! $event.detail.scope))) $el.close()"
        @endif
    >
        {{ $slot }}

       {{-- start of my customization --}}
        @if($close_type == 'button')
            <flux:modal.close>
                <flux:button 
                    variant="filled"
                    icon-trailing="circle-chevron-down"
                    class="mt-pl3"
                    data-flux-modal-close
                >
                    {{ $close_button }}
                </flux:button>
            </flux:modal.close>
        @elseif($closable)
            {{-- This "[&[hidden]]:block" hack is here to prevent this element from effecting classes like "space-y-6" --}}
            <div class="absolute top-0 right-0 mt-4 mr-4 [&[hidden]]:block" hidden>
                <flux:modal.close>
                    <flux:button variant="ghost" icon="x-mark" size="sm" alt="Close modal" class="!text-zinc-400 hover:!text-zinc-800 dark:!text-zinc-500 dark:hover:!text-white"></flux:button>
                </flux:modal.close>
            </div>
        @endif
        {{-- end of my customization --}}
    </dialog>
</ui-modal>

Then the modal I'm actually testing with looks like so:

    <flux:modal.trigger name="fuel_economy_help_text">
        <flux:button variant="ghost" class="tooltip-trigger hover:opacity-70">
            <flux:icon.circle-info class="size-5 min-w-5" />
            <span class="sr-only">View Help Text</span>
        </flux:button>
    </flux:modal.trigger>

    <flux:modal name="fuel_economy_help_text" close_button="Back to Results" class="min-w-[300px] overflow-x-hidden">
        <flux:heading class="text-wrap">
            <flux:icon.circle-info class="size-5 min-w-5 text-blue-700" />
            Average Fuel Economy
        </flux:heading>

        <p class="text-wrap">The Fuel Economy rating displayed is an average for operation while in gasoline mode only. Actual total energy usage will vary depending on daily distances driven in relation to the vehicle’s EV-mode range, as PHEV vehicles switch over to gasoline mode once battery charge is exhausted.</p>
    </flux:modal>

My actual modal looks like this:
Image

How do you expect it to work?

I would expect that the modal would allow the screenreader to focus on the first element first, then move through the modal in normal document flow instead of being autofocused and forced to skip around in the document flow in order to get all of the content out of a modal. Whether this is the ability to turn off autofocus in modals or choose which element gets focus first, either would work to allow developers to create accessible modals!

Please confirm (incomplete submissions will not be addressed)

  • I have provided easy and step-by-step instructions to reproduce the bug.
  • I have provided code samples as text and NOT images.
  • I understand my bug report will be closed if I haven't met the criteria above.
@aurawindsurfing
Copy link

I second that! There should be option to disable autofocus for inputs within modal. Espacially when modal is a flyout

Image

In this example I have some text and images preceding the form and do not want to be focused on the form straight away.

@jeffchown
Copy link

jeffchown commented Dec 28, 2024

While I agree it would be nice to be able to disable the autofocus in a modal when desired, one workaround may be to add:

<input type="text" autofocus="autofocus" style="display:none" />

at the top of your form (or in whatever position will best serve your modal).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants