MAD Lab
/
Tutor > Navegação e overlays > Modal

Modal

Navegação e overlays

mad-modal
Básico

mad-modal size=sm com abrir/fechar via mad-btn (open-modal / close-modal).

Confirmar exclusão

Tem certeza que deseja excluir este registro? Esta ação não pode ser desfeita.

resources/views/tutor/examples/navegacao-modal/basico.blade.php
<mad-modal name="tutor-modal-basico" title="Confirmar exclusão" size="sm">
    <p>Tem certeza que deseja excluir este registro? Esta ação não pode ser desfeita.</p>
    <div style="display:flex;justify-content:flex-end;gap:.5rem;margin-top:1rem;">
        <mad-btn close-modal="tutor-modal-basico" variant="ghost">Cancelar</mad-btn>
        <mad-btn close-modal="tutor-modal-basico" variant="danger" icon="trash-2">Confirmar exclusão</mad-btn>
    </div>
</mad-modal>

<mad-btn open-modal="tutor-modal-basico" variant="danger" icon="trash-2">Excluir registro</mad-btn>
Footer (prop string)

footer NÃO é slot nomeado — monte o HTML em @php e passe via :footer.

Aviso de manutenção
O sistema ficará indisponível das 02h às 04h para manutenção programada.
resources/views/tutor/examples/navegacao-modal/footer.blade.php
@php
    // footer NAO e slot nomeado do <mad-modal> — e prop STRING: monta-se o
    // HTML em PHP e passa via :footer. Mad.closeModal(nome) e a mesma chamada
    // que o compilador gera pro atalho close-modal="nome" (ver
    // MadBladeCompiler::parseParams "Overlay shortcuts").
    $footer = '<button type="button" class="mad-btn mad-btn-ghost" '
            . 'onclick="Mad.closeModal(\'tutor-modal-footer\')">Cancelar</button>'
            . '<button type="button" class="mad-btn mad-btn-primary" '
            . 'onclick="Mad.closeModal(\'tutor-modal-footer\')">OK, entendi</button>';
@endphp
<mad-modal name="tutor-modal-footer" title="Aviso de manutenção" size="md" :footer="$footer">
    O sistema ficará indisponível das 02h às 04h para manutenção programada.
</mad-modal>

<mad-btn open-modal="tutor-modal-footer" variant="outline" icon="info">Ver aviso</mad-btn>
Não-dismissível (ação obrigatória)

dismissible=false + mad:click real fechando o modal.

Aceite obrigatório

Você precisa aceitar os termos de uso antes de continuar usando o sistema.

resources/views/tutor/examples/navegacao-modal/nao-dismissivel.blade.php
<mad-modal name="tutor-modal-termos" title="Aceite obrigatório" size="md" :dismissible="false">
    <p>Você precisa aceitar os termos de uso antes de continuar usando o sistema.</p>
    <div style="display:flex;justify-content:flex-end;margin-top:1rem;">
        <mad-btn mad:click="onAceitarTermosModal" variant="primary" icon="check">Aceitar termos</mad-btn>
    </div>
</mad-modal>

<mad-btn open-modal="tutor-modal-termos" variant="outline" icon="shield-alert">Abrir aceite obrigatório</mad-btn>
app/control/Tutor/TutorNavegacaoModal.php
/** Exemplo "Não-dismissível" — só fecha depois da ação obrigatória. */
public function onAceitarTermosModal(): MadResponse
{
    return (new MadResponse())
        ->toast('Termos aceitos — obrigado!', 'success')
        ->closeModal('tutor-modal-termos');
}
Tamanhos

sm (380px), md (520px, padrão), lg (680px) e xl (900px).

Tamanho sm (380px)
Modal pequeno — confirmações rápidas.
Tamanho md (520px)
Modal médio — formulários curtos (tamanho padrão).
Tamanho lg (680px)
Modal grande — visualização rápida de um detalhe.
Tamanho xl (900px)
Modal extra grande — conteúdo mais denso (tabelas, resumos).
resources/views/tutor/examples/navegacao-modal/tamanhos.blade.php
<mad-modal name="tutor-modal-sm" title="Tamanho sm (380px)" size="sm">
    Modal pequeno — confirmações rápidas.
</mad-modal>
<mad-modal name="tutor-modal-md" title="Tamanho md (520px)" size="md">
    Modal médio — formulários curtos (tamanho padrão).
</mad-modal>
<mad-modal name="tutor-modal-lg" title="Tamanho lg (680px)" size="lg">
    Modal grande — visualização rápida de um detalhe.
</mad-modal>
<mad-modal name="tutor-modal-xl" title="Tamanho xl (900px)" size="xl">
    Modal extra grande — conteúdo mais denso (tabelas, resumos).
</mad-modal>

<div style="display:flex;gap:.5rem;flex-wrap:wrap;">
    <mad-btn open-modal="tutor-modal-sm" variant="outline">sm</mad-btn>
    <mad-btn open-modal="tutor-modal-md" variant="outline">md</mad-btn>
    <mad-btn open-modal="tutor-modal-lg" variant="outline">lg</mad-btn>
    <mad-btn open-modal="tutor-modal-xl" variant="outline">xl</mad-btn>
</div>
Modal dinâmico (ação wire)

conteúdo injetado por MadResponse->html() ANTES de openModal() — a ordem importa.

Detalhes do pedido
Selecione um pedido acima para ver os detalhes.
resources/views/tutor/examples/navegacao-modal/dinamico.blade.php
<div style="display:flex;gap:.5rem;flex-wrap:wrap;">
    <mad-btn variant="outline" icon="eye" mad:click="onVerPedidoModal(1)">Ver pedido #1</mad-btn>
    <mad-btn variant="outline" icon="eye" mad:click="onVerPedidoModal(2)">Ver pedido #2</mad-btn>
    <mad-btn variant="outline" icon="eye" mad:click="onVerPedidoModal(3)">Ver pedido #3</mad-btn>
</div>

<mad-modal name="tutor-modal-pedido" title="Detalhes do pedido" size="md">
    <div id="tutor-modal-pedido-content">Selecione um pedido acima para ver os detalhes.</div>
</mad-modal>
app/control/Tutor/TutorNavegacaoModal.php
/**
 * Exemplo "Modal dinâmico" — o conteúdo depende de QUAL pedido foi
 * clicado, então injeta o HTML no placeholder antes de abrir o modal.
 */
public function onVerPedidoModal(int $id): MadResponse
{
    $pedido = self::PEDIDOS_DEMO[$id] ?? null;

    if (!$pedido) {
        return (new MadResponse())->toast('Pedido não encontrado.', 'danger');
    }

    $html = '<p><strong>Pedido:</strong> #' . $id . '</p>'
        . '<p><strong>Cliente:</strong> ' . e($pedido['cliente']) . '</p>'
        . '<p><strong>Valor:</strong> R$ ' . number_format($pedido['valor'], 2, ',', '.') . '</p>'
        . '<p><strong>Status:</strong> ' . e($pedido['status']) . '</p>';

    return (new MadResponse())
        ->html('#tutor-modal-pedido-content', $html)
        ->openModal('tutor-modal-pedido');
}
Código-fonte completo da página
app/control/Tutor/TutorNavegacaoModal.php
<?php

namespace App\Control\Tutor;

use App\Support\Tutor\TutorPage;
use Mad\Http\MadResponse;

/**
 * TutorNavegacaoModal — página "Modal" do MAD Lab.
 *
 * Cobre mad-modal: abrir/fechar por botão, footer como PROP STRING (não é
 * slot nomeado), modal não-dismissível (ação obrigatória), os 4 tamanhos e
 * um modal dinâmico — conteúdo injetado por MadResponse->html() ANTES de
 * openModal() (ordem importa: o conteúdo precisa existir no DOM quando o
 * modal abre).
 */
class TutorNavegacaoModal extends TutorPage
{
    protected string $catalogKey = 'navegacao_modal';

    /** Fixture local (sem banco) do exemplo "Modal dinâmico". */
    private const PEDIDOS_DEMO = [
        1 => ['cliente' => 'Ana Souza',  'valor' => 1240.50, 'status' => 'Enviado'],
        2 => ['cliente' => 'Bruno Lima', 'valor' => 389.90,  'status' => 'Entregue'],
        3 => ['cliente' => 'Carla Dias', 'valor' => 2110.00, 'status' => 'Novo'],
    ];

    /** Exemplo "Não-dismissível" — só fecha depois da ação obrigatória. */
    public function onAceitarTermosModal(): MadResponse
    {
        return (new MadResponse())
            ->toast('Termos aceitos — obrigado!', 'success')
            ->closeModal('tutor-modal-termos');
    }

    /**
     * Exemplo "Modal dinâmico" — o conteúdo depende de QUAL pedido foi
     * clicado, então injeta o HTML no placeholder antes de abrir o modal.
     */
    public function onVerPedidoModal(int $id): MadResponse
    {
        $pedido = self::PEDIDOS_DEMO[$id] ?? null;

        if (!$pedido) {
            return (new MadResponse())->toast('Pedido não encontrado.', 'danger');
        }

        $html = '<p><strong>Pedido:</strong> #' . $id . '</p>'
            . '<p><strong>Cliente:</strong> ' . e($pedido['cliente']) . '</p>'
            . '<p><strong>Valor:</strong> R$ ' . number_format($pedido['valor'], 2, ',', '.') . '</p>'
            . '<p><strong>Status:</strong> ' . e($pedido['status']) . '</p>';

        return (new MadResponse())
            ->html('#tutor-modal-pedido-content', $html)
            ->openModal('tutor-modal-pedido');
    }
}
resources/views/tutor/navegacao/modal.blade.php
<x-tutor-page page="navegacao_modal">
    <x-tutor-demo demo="tutor.examples.navegacao-modal.basico"
        title="Básico" desc="mad-modal size=sm com abrir/fechar via mad-btn (open-modal / close-modal)." />

    <x-tutor-demo demo="tutor.examples.navegacao-modal.footer"
        title="Footer (prop string)" desc="footer NÃO é slot nomeado — monte o HTML em @php e passe via :footer." />

    <x-tutor-demo demo="tutor.examples.navegacao-modal.nao-dismissivel"
        title="Não-dismissível (ação obrigatória)" desc="dismissible=false + mad:click real fechando o modal."
        php="TutorNavegacaoModal::onAceitarTermosModal" />

    <x-tutor-demo demo="tutor.examples.navegacao-modal.tamanhos"
        title="Tamanhos" desc="sm (380px), md (520px, padrão), lg (680px) e xl (900px)." />

    <x-tutor-demo demo="tutor.examples.navegacao-modal.dinamico"
        title="Modal dinâmico (ação wire)" desc="conteúdo injetado por MadResponse->html() ANTES de openModal() — a ordem importa."
        php="TutorNavegacaoModal::onVerPedidoModal" />
</x-tutor-page>