#02 FilamentPHP応用

モーダルの仕組み——Slide-over・確認・カスタムモーダル

FilamentのモーダルはActionに統合されている

Filamentでは、モーダルダイアログは独立したコンポーネントではなく、Actionと一体化した仕組みとして実装されています。Action::make()に続けてモーダル関連のメソッドをチェーンするだけで、確認ダイアログ・フォームモーダル・カスタムコンテンツを表示できます。

このアプローチの利点は、モーダルの表示ロジックとビジネスロジックが同じ場所にまとまることです。Bladeファイルを別途用意することなく、PHPのメソッドチェーンだけでモーダルUIを完成させられます。

->modalWidth() — モーダルのサイズを調整する

デフォルトのモーダルサイズはlgです。コンテンツに応じて適切なサイズを選びましょう。

use Filament\Support\Enums\MaxWidth;

Action::make('edit')
    ->modalWidth(MaxWidth::ExtraLarge)  // xl

利用できるサイズ一覧:

定数幅の目安用途
MaxWidth::ExtraSmallxs(320px相当)短い確認文のみ
MaxWidth::Smallsm(384px相当)シンプルな確認
MaxWidth::Mediummd(448px相当)標準的なフォーム
MaxWidth::Largelg(512px相当)デフォルト
MaxWidth::ExtraLargexl(576px相当)中程度のフォーム
MaxWidth::TwoExtraLarge2xl(672px相当)複雑なフォーム
MaxWidth::ThreeExtraLarge3xl(768px相当)多フィールドフォーム
MaxWidth::Screen画面幅いっぱい大きなコンテンツ

文字列でも指定できます。

->modalWidth('2xl')

->slideOver() でスライドオーバーに変更する

モーダルの代わりに、画面右側からスライドして現れるパネル(スライドオーバー)を使うことができます。

Action::make('viewDetails')
    ->label('詳細を見る')
    ->slideOver()
    ->modalContent(fn (Post $record): View => view(
        'filament.modals.post-details',
        ['post' => $record]
    ))

スライドオーバーは特にモバイル対応に優れており、リスト表示から詳細情報を確認するようなケースで自然なUIになります。->slideOver()を付けるだけで自動的にスライドオーバースタイルに切り替わります。

->modalContent(fn) でBladeビューをモーダルに表示する

フォームではなく独自のBladeビューをモーダル内に表示したい場合は->modalContent()を使います。

Action::make('preview')
    ->label('プレビュー')
    ->icon('heroicon-o-eye')
    ->modalContent(fn (Post $record): View => view(
        'filament.modals.post-preview',
        ['post' => $record]
    ))
    ->modalWidth('3xl')
    ->modalFooterActions([])  // フッターを非表示

Bladeビューの例(resources/views/filament/modals/post-preview.blade.php):

<div class="prose max-w-none p-4">
    <h1>{{ $post->title }}</h1>
    <p class="text-gray-500">{{ $post->published_at?->format('Y年m月d日') }}</p>
    <div>{!! $post->body !!}</div>
</div>

->extraModalFooterActions() で追加ボタンを付ける

モーダルフッターにキャンセル・実行ボタン以外のボタンを追加できます。

Action::make('edit')
    ->form([...])
    ->extraModalFooterActions([
        Action::make('saveAndPublish')
            ->label('保存して公開')
            ->color('success')
            ->action(function (Post $record, array $data): void {
                $record->update($data + ['status' => 'published']);
            }),
    ])

これにより「保存」「保存して公開」「キャンセル」という3ボタン構成が実現できます。

->modalIcon()->modalIconColor()

モーダルヘッダーにアイコンを表示してアクションの意味を視覚的に伝えます。

Action::make('delete')
    ->requiresConfirmation()
    ->modalIcon('heroicon-o-trash')
    ->modalIconColor('danger')
    ->modalHeading('削除の確認')
    ->modalDescription('このレコードを削除します。この操作は元に戻せません。')

アイコンカラーはprimarysuccesswarningdangergrayinfoを指定できます。削除系はdanger(赤)、承認系はsuccess(緑)で使い分けると直感的です。

->closeModalByClickingAway(false) で誤操作を防ぐ

デフォルトでは、モーダルの外側(オーバーレイ部分)をクリックするとモーダルが閉じます。フォーム入力中に誤って閉じてしまう問題を防ぐには:

Action::make('create')
    ->form([
        TextInput::make('title')->required(),
        RichEditor::make('body'),
    ])
    ->closeModalByClickingAway(false)

これで外クリックによる誤閉じが防止されます。Escapeキーによる閉じ操作も無効にしたい場合は->closeModalByEscaping(false)も使えます。

->modalFooterActionsAlignment() でフッターのボタン位置を制御する

use Filament\Support\Enums\Alignment;

Action::make('confirm')
    ->requiresConfirmation()
    ->modalFooterActionsAlignment(Alignment::Right)  // デフォルト
    // Alignment::Left / Alignment::Center / Alignment::Right

デザインガイドラインに合わせてボタンの配置を統一できます。

CreateAction/EditActionのモーダル化

テーブルの行アクションとして使える組み込みのCreateActionEditActionも、同じモーダルAPIを使えます。

use Filament\Tables\Actions\CreateAction;
use Filament\Tables\Actions\EditAction;

->actions([
    EditAction::make()
        ->slideOver()
        ->modalWidth('2xl'),
])

->headerActions([
    CreateAction::make()
        ->modalHeading('新しい記事を作成')
        ->modalWidth('3xl')
        ->closeModalByClickingAway(false),
])

Resourceのページを経由せず、テーブル上でインラインにCRUD操作できるため、管理画面のUXが大幅に向上します。

実例:詳細表示スライドオーバー付きテーブル

public function table(Table $table): Table
{
    return $table
        ->columns([
            TextColumn::make('title')->limit(40),
            TextColumn::make('status')->badge(),
            TextColumn::make('created_at')->since(),
        ])
        ->actions([
            Action::make('view')
                ->label('詳細')
                ->icon('heroicon-o-eye')
                ->slideOver()
                ->modalWidth('xl')
                ->modalHeading(fn (Post $record) => $record->title)
                ->modalContent(fn (Post $record) => view(
                    'filament.modals.post-details',
                    ['post' => $record]
                ))
                ->modalFooterActions([]),

            EditAction::make()
                ->slideOver()
                ->modalWidth('2xl')
                ->closeModalByClickingAway(false),

            Action::make('delete')
                ->icon('heroicon-o-trash')
                ->color('danger')
                ->requiresConfirmation()
                ->modalIcon('heroicon-o-exclamation-triangle')
                ->modalIconColor('danger')
                ->modalHeading('記事を削除')
                ->modalDescription('この操作は取り消せません。')
                ->modalSubmitActionLabel('削除する')
                ->action(fn (Post $record) => $record->delete()),
        ]);
}

まとめ

FilamentのモーダルシステムはActionと統合されているため、PHPのメソッドチェーンだけで完結したUIが構築できます。->slideOver()->modalWidth()->modalContent()を使い分けることで、確認ダイアログから本格的なフォームモーダルまで柔軟に対応できます。次のエピソードではフォームコンポーネントをカスタマイズする方法を解説します。