Skip to content

Commit

Permalink
Merge pull request #12991 from gehrisandro/feature/make-modal-autofoc…
Browse files Browse the repository at this point in the history
…us-deactivatable

Add ability to disable autofocus on modals
  • Loading branch information
danharrin authored May 30, 2024
2 parents 9824951 + c26283a commit 61b52bd
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 1 deletion.
23 changes: 23 additions & 0 deletions packages/actions/docs/04-modals.md
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,29 @@ use Filament\Support\View\Components\Modal;
Modal::closeButton(false);
```

## Preventing the modal from autofocusing

By default, modals will autofocus on the first focusable element when opened. If you wish to disable this behavior, you can use the `modalAutofocus(false)` method:

```php
Action::make('updateAuthor')
->form([
// ...
])
->action(function (array $data): void {
// ...
})
->modalAutofocus(false)
```

If you'd like to disable autofocus for all modals in the application, you can do so by calling `Modal::autofocus(false)` inside a service provider or middleware:

```php
use Filament\Support\View\Components\Modal;

Modal::autofocus(false);
```

## Optimizing modal configuration methods

When you use database queries or other heavy operations inside modal configuration methods like `modalHeading()`, they can be executed more than once. This is because Filament uses these methods to decide whether to render the modal or not, and also to render the modal's content.
Expand Down
5 changes: 5 additions & 0 deletions packages/actions/resources/views/components/modals.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

<x-filament::modal
:alignment="$action?->getModalAlignment()"
:autofocus="$action?->isModalAutofocused()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
:close-by-escaping="$action?->isModalClosedByEscaping()"
Expand Down Expand Up @@ -67,6 +68,7 @@

<x-filament::modal
:alignment="$action?->getModalAlignment()"
:autofocus="$action?->isModalAutofocused()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
:close-by-escaping="$action?->isModalClosedByEscaping()"
Expand Down Expand Up @@ -122,6 +124,7 @@

<x-filament::modal
:alignment="$action?->getModalAlignment()"
:autofocus="$action?->isModalAutofocused()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
:close-by-escaping="$action?->isModalClosedByEscaping()"
Expand Down Expand Up @@ -183,6 +186,7 @@

<x-filament::modal
:alignment="$action?->getModalAlignment()"
:autofocus="$action?->isModalAutofocused()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
:close-by-escaping="$action?->isModalClosedByEscaping()"
Expand Down Expand Up @@ -244,6 +248,7 @@
<form wire:submit.prevent="callMountedFormComponentAction">
<x-filament::modal
:alignment="$action?->getModalAlignment()"
:autofocus="$action?->isModalAutofocused()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
:close-by-escaping="$action?->isModalClosedByEscaping()"
Expand Down
14 changes: 14 additions & 0 deletions packages/actions/src/Concerns/CanOpenModal.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ trait CanOpenModal

protected bool | Closure | null $isModalClosedByEscaping = null;

protected bool | Closure | null $isModalAutofocused = null;

protected string | Closure | null $modalIcon = null;

/**
Expand Down Expand Up @@ -129,6 +131,13 @@ public function modalCloseButton(bool | Closure | null $condition = true): stati
return $this;
}

public function modalAutofocus(bool | Closure | null $condition = true): static
{
$this->isModalAutofocused = $condition;

return $this;
}

public function modalIcon(string | Closure | null $icon = null): static
{
$this->modalIcon = $icon;
Expand Down Expand Up @@ -614,6 +623,11 @@ public function isModalClosedByEscaping(): bool
return (bool) ($this->evaluate($this->isModalClosedByEscaping) ?? Modal::$isClosedByEscaping);
}

public function isModalAutofocused(): bool
{
return $this->evaluate($this->isModalAutofocused) ?? Modal::$isAutofocused;
}

/**
* @deprecated Use `makeModalSubmitAction()` instead.
*
Expand Down
20 changes: 20 additions & 0 deletions packages/support/docs/09-blade-components/02-modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,16 @@ By default, when you click away from a modal, it will close itself. If you wish
</x-filament::modal>
```

## Closing the modal by escaping

By default, when you press escape on a modal, it will close itself. If you wish to disable this behavior for a specific action, you can use the `close-by-escaping` attribute:

```blade
<x-filament::modal :close-by-escaping="false">
{{-- Modal content --}}
</x-filament::modal>
```

## Hiding the modal close button

By default, modals have a close button in the top right corner. You can remove the close button from the modal by using the `close-button` attribute:
Expand All @@ -204,3 +214,13 @@ By default, modals have a close button in the top right corner. You can remove t
{{-- Modal content --}}
</x-filament::modal>
```

## Preventing the modal from autofocusing

By default, modals will autofocus on the first focusable element when opened. If you wish to disable this behavior, you can use the `autofocus` attribute:

```blade
<x-filament::modal :autofocus="false">
{{-- Modal content --}}
</x-filament::modal>
```
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@props([
'alignment' => Alignment::Start,
'ariaLabelledby' => null,
'autofocus' => \Filament\Support\View\Components\Modal::$isAutofocused,
'closeButton' => \Filament\Support\View\Components\Modal::$hasCloseButton,
'closeByClickingAway' => \Filament\Support\View\Components\Modal::$isClosedByClickingAway,
'closeByEscaping' => \Filament\Support\View\Components\Modal::$isClosedByEscaping,
Expand Down Expand Up @@ -95,7 +96,7 @@
x-on:{{ $closeEventName }}.window="if ($event.detail.id === '{{ $id }}') close()"
x-on:{{ $openEventName }}.window="if ($event.detail.id === '{{ $id }}') open()"
@endif
x-trap.noscroll="isOpen"
x-trap.noscroll{{ $autofocus ? '' : '.noautofocus' }}="isOpen"
x-bind:class="{
'fi-modal-open': isOpen,
}"
Expand Down
7 changes: 7 additions & 0 deletions packages/support/src/View/Components/Modal.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ class Modal

public static bool $isClosedByEscaping = true;

public static bool $isAutofocused = true;

public static function autofocus(bool $condition = true): void
{
static::$isAutofocused = $condition;
}

public static function closeButton(bool $condition = true): void
{
static::$hasCloseButton = $condition;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
@if (($layout === FiltersLayout::Modal) || $triggerAction->isModalSlideOver())
<x-filament::modal
:alignment="$triggerAction->getModalAlignment()"
:autofocus="$triggerAction->isAutofocused()"
:close-button="$triggerAction->hasModalCloseButton()"
:close-by-clicking-away="$triggerAction->isModalClosedByClickingAway()"
:close-by-escaping="$triggerAction?->isModalClosedByEscaping()"
:description="$triggerAction->getModalDescription()"
:footer-actions="$triggerAction->getVisibleModalFooterActions()"
:footer-actions-alignment="$triggerAction->getModalFooterActionsAlignment()"
Expand Down

0 comments on commit 61b52bd

Please sign in to comment.