Modo Tutor IT Split-View Persistente — Panel de Ayuda
Resumen
El modo Tutor IT split-view permite que el panel de ayuda de CreaRack Pro coexista visualmente con la aplicación en lugar de solaparse. Cuando el usuario activa “Tutor ON”, el contenido de la app se comprime hacia la izquierda y el panel ocupa 600 px fijos en el lado derecho, permitiendo trabajar con ambos simultáneamente. Además, el estado abierto/cerrado del panel sobrevive navegaciones HTMX y re-renders parciales de Alpine, eliminando el bug s55 en el que el panel se “cerraba solo” al hacer click en la app.
Motivación (bug s55, fix #4)
El commit fd5172d resolvió el cuarto ciclo de iteración del bug s55 (serie de sprints de Edu + @Esquembri):
| Fix | Problema resuelto |
|---|---|
| #1–#2 | Panel no aparecía / HTML roto |
| #3 | HTML root mal formado → overlay transparente + pointer-events:none correcto |
| #4 | Panel se cerraba al navegar (re-init Alpine) + petición UX split-view de Edu |
Causa raíz del cierre: las navegaciones HTMX (y re-renders parciales de Alpine) reinicializan el componente helpWidget desde cero con open: false. El usuario percibía que el panel “se cerraba” cuando en realidad “se reiniciaba”.
Comportamiento esperado (post-fix #4)
- Activar Tutor + abrir panel → la app se comprime hacia la izquierda con transición suave (0.25s); el panel ocupa 600 px a la derecha. Sin solapamiento.
- Click en la app en modo Tutor → la app reacciona normalmente; el panel permanece abierto incluso si HTMX recarga parcialmente la página.
- Cerrar panel en modo Tutor →
helpOpense elimina de localStorage; en el próximo re-render el panel no se reabre. - Desactivar Tutor →
body.help-tutor-activese quita; el layout vuelve al ancho completo;helpOpense limpia. - Recarga de página completa en modo Help (Tutor OFF) → panel siempre arranca cerrado (no persiste fuera de modo Tutor).
Implementación técnica
Persistencia de estado (JS)
// Inicialización de `open` — IIFE que lee localStorage
open: (function () {
try {
const tutor = localStorage.getItem('helpTutorMode') === 'true';
return tutor && localStorage.getItem('helpOpen') === 'true';
} catch (_) { return false; }
})(),
// _persistOpen(): guarda o borra helpOpen según el estado actual
_persistOpen() {
try {
if (this.tutorMode && this.open) {
localStorage.setItem('helpOpen', 'true');
} else {
localStorage.removeItem('helpOpen');
}
} catch (_) {}
},
Split-view via clase body (JS + CSS)
// _applyTutorBodyClass(): añade/quita help-tutor-active al <body>
_applyTutorBodyClass() {
try {
document.body.classList.toggle(
'help-tutor-active',
this.tutorMode && this.open,
);
} catch (_) {}
},
/* static/css/pages/help.css — s55 split-view */
body.help-tutor-active {
padding-right: 600px;
transition: padding-right 0.25s ease;
}
El panel (.help-panel) tiene position: fixed; right: 0; width: 600px —está fuera del flujo normal— por lo que no se ve afectado por el padding-right. Solo el contenido del <body> se comprime.
Hook init() Alpine
init() {
this._applyTutorBodyClass();
// Cargar wiki si el panel arrancó restaurado (modo Tutor)
if (this.open && this.total === 0) this.loadWiki();
},
Garantiza que, tras un re-render, el layout split-view se aplica antes de que Alpine pinte el panel.
Flujo de llamadas por acción
toggle() → open=!open → loadWiki(si procede) → _persistOpen() → _applyTutorBodyClass()
close() → open=false → _persistOpen() → _applyTutorBodyClass()
toggleTutor() → tutorMode=!tutorMode → answer=null → _persistOpen() → _applyTutorBodyClass()
init() → _applyTutorBodyClass() → loadWiki(si procede)
Archivos modificados
| Archivo | Tipo de cambio |
|---|---|
static/js/alpine-components.js | Lógica JS: IIFE open, _persistOpen(), _applyTutorBodyClass(), init(), refactor close() |
static/css/pages/help.css | Nueva regla body.help-tutor-active |
Consideraciones de compatibilidad
- CSP: todos los accesos a
localStorageestán envueltos entry/catchpara entornos con Storage bloqueado (modo incógnito estricto, algunos navegadores). El panel simplemente arranca cerrado. - Alpine re-init: la solución es resiliente a cualquier futura migración de HTMX boost / turbo porque lee el estado desde
localStorageen cadainit(), no desde memoria. - Sin efecto en modo Help: la persistencia solo se activa cuando
helpTutorMode === 'true'. Un usuario en modo Help normal no verá cambios de comportamiento.
Estado
- Implementado y confirmado visualmente por Edu (@Esquembri) — commit
fd5172d, 2026-05-11. - Pendiente: test E2E que simule navegación HTMX con panel abierto en modo Tutor.
Véase también
- [[entity—core—component—help-widget]]