Es muy probable que los usuarios de nuestras aplicaciones sea por despiste o por cualquier imprevisto dejen sus sesiones abiertas durante largos periodos. En esta entrada cubrimos la base para que sepas cómo puedes mostrar una ventana modal que bloquee la pantalla cuando la inactividad del usuario sea del x minutos, tú lo puedes configurar fácilmente.
Además de mostrar una ventana modal que bloquee la pantalla, también es importante lanzar una petición al servidor para eliminar la sesión del usuario, ya que un usuario con conocimientos de HTML y muy malas intenciones podría ocultar esa ventana modal con el inspector del navegador y nuestro trabajo no serviría para mucho.
Pero si lo que quieres es cerrar sesión y abandonar la pantalla en la que se encontraba el usuario actualmente, lo mejor en este caso es además de cerrar sesión desde el cliente con Vue, hacer un redirect a la página de login con una sesión flash, así nos olvidamos de cualquier tipo de problema.
Por cierto, si todavía no sabes cómo instalar Vue 3 en Laravel, revisa esta entrada, a día de hoy es necesario hacerlo así. Instalar y configurar useIdle Lo primero que debemos hacer es instalar useIdle. Si no conoces VueUse, no te pierdas la ruta de Vue 3.
yarn add @vueuse/core
Esta dependencia nos permite escuchar los eventos del usuario en cada interacción con nuestra página, click, movimiento de mouse etcétera.
Ahora vamos a crear un componente Modal con TailwindCSS 2 y añadir toda la lógica para que pasados 5 minutos aparezca este componente bloqueando la interfaz de nuestro usuario.
<template>
<div class="fixed z-10 inset-0 overflow-y-auto" v-if="app_idle">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" role="dialog" aria-modal="true" aria-labelledby="modal-headline">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
<!-- Heroicon name: outline/exclamation -->
<svg class="h-6 w-6 text-red-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-headline">
Sesión cerrada por inactividad
</h3>
<div class="mt-2">
<p class="text-sm text-gray-500">
Hemos cerrado tu sesión por seguridad, vuelve a acceder a tu cuenta de nuevo
</p>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<a href="/login" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
Acceder de nuevo
</a>
</div>
</div>
</div>
</div>
</template>
<script>
import {onMounted, ref, watch} from "vue";
import {useIdle} from "@vueuse/core";
export default {
name: "IdleModal",
setup() {
const app_idle = ref(false)
const { idle, lastActive } = useIdle(5 * 60 * 1000) // 5 minutos
onMounted(() => {
watch(idle, (v) => {
if (idle.value === true) {
// petición http para cerrar sesión con el servidor
// mostramos la modal para notificar al usuario
app_idle.value = true
}
})
})
return { app_idle }
}
}
</script>Simplemente copia el código del componente, haz alguna prueba y ajusta a tus necesidades. Ahora debemos registrar el componente IdleModal para que esté disponible en Blade.
import IdleModal from './components/IdleModal'
createApp({
components: {
IdleModal
}
})
.mount("#app")Para finalizar utiliza la etiqueta html idle-modal en tus archivos blade, principalmente en los layouts si es que tienes más de uno, algo así:
<idle-modal></idle-modal>Si toda ha ido bien, pasados los 5 minutos (te recomiendo que lo bajes a unos segundos para hacer pruebas) verás el siguiente resultado.

¡Eso es todo!
Curso Laravel 12
Completo 2026
El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.
star Incluido en cualquier suscripción