Skip to content

MeModal

Modal com overlay, suporte a posicionamento, slots de header/body/footer, fechamento por ESC, clique fora e botão de fechar.

Playground

Importação

vue
<script>
import { MeModal } from '@/components/global/utils/export/index'
</script>

Uso Básico

vue
<script setup>
import { ref } from 'vue'
const isOpen = ref(false)
</script>

<template>
  <MeButton label="Abrir Modal" @click="isOpen = true" />

  <MeModal :visible="isOpen" title-header="Título do Modal" @close="isOpen = false">
    <template #body>
      Conteúdo do modal.
    </template>
    <template #footer>
      <MeButton label="Fechar" variant="gray" flat @click="isOpen = false" />
    </template>
  </MeModal>
</template>

Posicionamento

A prop position controla onde o modal aparece na tela.

vue
<MeModal
  :visible="isOpen"
  position="top-right"
  width="360px"
  title-header="Top Right"
  @close="isOpen = false"
>
  <template #body>Conteúdo</template>
</MeModal>

Body com Scroll

Use body-max-height para limitar a altura do body e ativar scroll automático.

vue
<MeModal
  :visible="isOpen"
  title-header="Body com Scroll"
  body-max-height="200px"
  @close="isOpen = false"
>
  <template #body>
    <!-- conteúdo longo -->
  </template>
</MeModal>

Conteúdo Customizado

Com custom-content, o slot default substitui toda a estrutura de header/body/footer.

vue
<MeModal :visible="isOpen" :custom-content="true" width="400px" @close="isOpen = false">
  <div style="padding: 40px; text-align: center">
    <h2>Conteúdo Livre</h2>
    <MeButton label="Fechar" @click="isOpen = false" />
  </div>
</MeModal>

Controle de Fechamento

Por padrão o modal fecha por ESC, clique fora e botão de fechar. Cada comportamento pode ser desabilitado individualmente.

vue
<MeModal
  :visible="isOpen"
  title-header="Modal Restrito"
  :close-on-esc="false"
  :close-on-click-outside="false"
  @close="isOpen = false"
>
  <template #body>Conteúdo</template>
</MeModal>

Evento close

O payload do evento indica o motivo do fechamento.

vue
<MeModal :visible="isOpen" @close="handleClose">
  <template #body>Conteúdo</template>
</MeModal>

<script setup>
function handleClose(reason) {
  // reason: 'close-button' | 'click-outside' | 'esc-key' | 'normal'
  console.log('Fechado por:', reason)
  isOpen.value = false
}
</script>

API

Props

PropTipoPadrãoDescrição
visiblebooleanfalseControla a visibilidade do modal
titleHeaderstringTítulo exibido no header padrão
widthstring'800px'Largura máxima do container
minHeightstring'80px'Altura mínima do container
positionMeModalPosition'center'Posição do modal na tela
showCloseButtonbooleantrueExibe o botão de fechar no canto superior direito
closeOnClickOutsidebooleantrueFecha ao clicar fora do container
closeOnEscbooleantrueFecha ao pressionar ESC
customContentbooleanfalseUsa o slot default como conteúdo livre
bodyMaxHeightstringAltura máxima do body (ativa overflow: auto)
containerStyleobject{}Estilo inline adicional para o container
headerStyleobject{}Estilo inline adicional para o header
bodyStyleobject{}Estilo inline adicional para o body
footerStyleobject{}Estilo inline adicional para o footer

MeModalPosition

typescript
type MeModalPosition =
  | 'center' | 'top-center' | 'top-right' | 'top-left'
  | 'bottom-center' | 'bottom-right' | 'bottom-left'
  | 'center-left' | 'center-right'

Eventos

EventoPayloadDescrição
closestringEmitido ao fechar. Motivo: 'close-button', 'click-outside', 'esc-key' ou 'normal'

Slots

NomeDescrição
#headerConteúdo adicional no header. O header só é renderizado se titleHeader ou este slot forem fornecidos
#bodyConteúdo principal do modal
#footerRodapé do modal. Só é renderizado quando preenchido
defaultConteúdo livre quando customContent=true

Acessibilidade

  • O container do modal tem role="dialog" e aria-modal="true"
  • Navegação por teclado: ESC fecha o modal (controlado por closeOnEsc)
  • O scroll do document.body é bloqueado enquanto o modal está aberto e restaurado ao fechar