fix(studio): uMind era inusable en móvil

El SPA no tenía ningún tratamiento responsive: un sidebar fijo de 256px
siempre visible. En un teléfono de 375px eso deja 119px para el contenido.

Ahora en móvil el sidebar sale de flujo y entra deslizándose desde la
izquierda, con botón en el header y fondo oscuro para cerrarlo. Se cierra
solo al elegir un tenant: dejarlo abierto tapa justo la pantalla a la que
se acaba de entrar. En escritorio (md+) no cambia nada — sigue fijo y sin
botón.

El estado vive en lib/ui.js porque lo tocan dos componentes que no son
padre/hijo: el botón del header y el propio sidebar.

También se achica el padding del contenido en pantallas chicas y las tabs
del agente pasan a scrollear en su propia caja en vez de desbordar.

Medido a 492px de ancho: scrollWidth igual a innerWidth y ningún elemento
sobresaliendo. Escritorio verificado sin regresión.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-17 18:16:34 -05:00
co-authored by Claude Sonnet 5
parent e2440b04f1
commit ce5956878d
8 changed files with 69 additions and 33 deletions
+20 -2
View File
@@ -1,8 +1,9 @@
<script setup>
import { computed, onMounted, ref } from 'vue'
import { computed, onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { api } from '../lib/api.js'
import { apiUmind, contexto } from '../lib/contexto.js'
import { menuAbierto } from '../lib/ui.js'
const route = useRoute()
const router = useRouter()
@@ -20,6 +21,10 @@ const form = ref(vacio())
// anidada de sus agentes (/tenants/:tenantId/agentes/:agenteId).
const tenantActivoId = computed(() => route.params.tenantId || route.params.id)
// Al elegir un tenant en móvil el menú se cierra solo: dejarlo abierto tapa
// justo la pantalla a la que se acaba de entrar.
watch(() => route.fullPath, () => { menuAbierto.value = false })
function vacio() {
return { nombre: '', dominios_permitidos: '', activo: true, cliente_id: null, plan_id: null }
}
@@ -121,7 +126,20 @@ onMounted(() => {
</script>
<template>
<aside class="w-64 shrink-0 h-screen sticky top-0 flex flex-col border-r border-borde bg-superficie">
<!-- Fondo oscuro en móvil: sin esto el menú abierto se superpone al
contenido sin dejar claro que hay que cerrarlo. -->
<div
v-if="menuAbierto"
class="fixed inset-0 bg-black/50 z-30 md:hidden"
@click="menuAbierto = false"
></div>
<aside
class="w-64 shrink-0 flex flex-col border-r border-borde bg-superficie
fixed inset-y-0 left-0 z-40 transition-transform duration-200
md:static md:h-screen md:sticky md:top-0 md:translate-x-0"
:class="menuAbierto ? 'translate-x-0' : '-translate-x-full'"
>
<div class="h-14 px-4 flex items-center border-b border-borde">
<router-link to="/" class="text-base font-semibold text-texto">
uMind <span class="text-brand">Studio</span>