Skip to content

feat(móvil): rediseño completo — tablero, modal de ticket y navegación propia - #80

Merged
JoseSerpaCode merged 6 commits into
mainfrom
feat/movil-kb
Aug 20, 2026
Merged

JoseSerpaCode merged 6 commits into
mainfrom
feat/movil-kb

Conversation

@JoseSerpaCode

Copy link
Copy Markdown
Owner

Resumen

Cierra la Fase 4 del plan de rediseño móvil (composed-gathering-knuth.md): el espacio de trabajo deja de ser el escritorio encogido.

  • Tablero: una columna a ancho completo con conmutador de estado, en vez de cuatro columnas de 320px en 360 de pantalla. Mover un ticket es un desplegable en la tarjeta, porque el arrastre HTML5 no dispara con eventos táctiles.
  • Modal de ticket: los campos se apilan en vez de partirse en columnas de 150px; la cabecera se envuelve en vez de abrir scroll horizontal.
  • Navegación: barra inferior de cuatro pestañas que sustituye a la hamburguesa, con hoja «Más» para lo que no cabe.
  • Tabla dinámica: cada fila pasa a ficha, con los campos que sobran plegados.

Más una tanda de arreglos de capas y copy encontrados en capturas reales — ver CHANGELOG.md [1.26.0] para el detalle completo (área táctil resucitando .hidden, z-index compitiendo con paneles, un intermitente real en la paleta de comandos).

Plan de pruebas

  • npm run typecheck — 0 errores
  • npx vitest run — 322 pasan
  • npx playwright test — 234 pasan, 3 corridas seguidas sin fallos
  • Cada regresión nueva verificada reintroduciendo el fallo a mano
  • Capturas reales a 360px en Chrome DevTools (Galaxy S10)

🤖 Generated with Claude Code

JoseSerpaCode and others added 6 commits August 18, 2026 09:27
Era la pantalla más rota del producto. El árbol de páginas es un `w-64` con
`m-4` —288 px fijos— así que en una pantalla de 360 dejaban 72 para el editor
y, menos su propio padding, **ocho píxeles de área de escritura**. Ni el árbol,
ni el editor, ni las dos páginas que los alojan tenían una sola utilidad
responsive.

El árbol pasa a ser un **cajón**: fuera de pantalla por defecto, superpuesto al
abrirse en vez de empujar el contenido. En un móvil no se lee el índice y el
texto a la vez, y el editor necesita el ancho entero. Se cierra pulsando fuera,
con Escape y al elegir una página —lo siguiente es leerla, no seguir mirando la
lista.

El colapso que ya existía para escritorio no servía aquí: dejaba el árbol en 64
px, que siguen siendo un quinto de la pantalla ocupados por algo que solo se
mira al cambiar de página.

**Borrar una página estaba fuera del viewport y solo con el ratón encima**:
`-right-12` la sacaba de la pantalla y `opacity-0 group-hover` la hacía
inalcanzable en táctil, donde no hay hover. En un teléfono, esa función no
existía. Ahora está dentro del flujo y visible; en escritorio se mantiene el
comportamiento discreto.

El panel de atajos se esconde en móvil: se abría solo con el ratón encima y lo
que lista son **atajos de teclado**. Hacerlo pulsable sería ofrecer una ayuda
que no ayuda.

## La causa real costó tres intentos

Los dos primeros arreglos no movieron el número ni un píxel: seguía midiendo
exactamente 25. Culpé al carril de la barra de Editor.js y al `shrink-0` del
flex, y ninguna era la causa.

Lo resolvió una **captura de pantalla**: el contenido estaba empujado fuera por
la derecha, o sea que el cajón seguía ocupando su hueco pese al `fixed`. El
motivo es que la cadena de clases terminaba en `relative`, y en Tailwind, dentro
del mismo grupo de utilidades, gana la que aparece más abajo en la hoja. El
`fixed` del principio no llegaba a aplicarse nunca.

Dos horas de diagnóstico por leer números en vez de mirar la pantalla.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diecinueve controles del producto se pintaban con `opacity-0
group-hover:opacity-100` —o `invisible`, o `hidden`— y en una pantalla táctil no
hay hover. Entre ellos: **borrar una página**, **borrar una fila** de una base
dinámica, cambiar el avatar, cambiar el banner, cambiar el icono del espacio y
las acciones del árbol de páginas.

En un teléfono esas funciones no eran incómodas de usar: no se podían usar.

Se arregla en el CSS base y no en cada componente, por dos motivos. Uno: son
diecinueve sitios, y arreglarlos de uno en uno deja fuera el siguiente que
alguien escriba. Dos: el patrón es **correcto** en escritorio —una interfaz que
no enseña todos los botones a la vez se lee mejor— y lo que falla es solo el
medio.

La regla vive dentro de la consulta de ancho máximo que ya existía, así que el
escritorio no se toca. Y eso se comprueba en vez de suponerse: hay una prueba
que verifica que en escritorio el botón de borrar fila **sigue oculto** hasta
acercar el ratón, y que aparece al hacerlo. Una regla con `!important` mal
acotada llenaría cada fila de botones que solo estorban.

Las pruebas de móvil miran los que borran o cambian algo, no los decorativos: un
tooltip que no aparece es una molestia; un botón de borrar que no aparece es una
función que no existe. Verificadas contra el fallo: quitando la regla, fallan
diciendo «está a opacidad 0».

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… crítico

**En un teléfono no había ninguna forma de buscar.** La búsqueda global se
esconde por debajo de 768 y la paleta Cmd+K necesita un teclado. La paleta ya
sabe buscar y ya está en todas las páginas: solo le faltaba una puerta que se
pueda tocar, y ahora la tiene en la barra.

Eso convierte en real la prueba que llevaba un `test.fail()` desde que se creó
el proyecto de móvil, afirmando que hoy no se podía.

**Socket.IO se cargaba en todas las páginas con sesión** y abría su conexión de
inmediato, solo para recibir notificaciones. Cuesta en los dos extremos: en la
`e2-micro` cada conexión abierta es memoria del proceso hasta que la pestaña se
cierra, y en un móvil una conexión persistente mantiene la radio despierta, que
es de las cosas que más batería gastan.

Ahora se carga en el primer momento de inactividad, y **no se conecta si la
pestaña está en segundo plano**: abrir diez pestañas para leer algo no debería
costar diez conexiones. No se pierde ninguna notificación —el servidor las
guarda y la campana las lee al abrirse.

La prueba mira el **HTML servido**, no un cronómetro. La primera versión
comprobaba si el socket se había pedido al llegar `domcontentloaded` y fallaba:
en una página local el navegador queda inactivo tan pronto que el
`requestIdleCallback` ya ha disparado. Medía la velocidad de la máquina, no el
comportamiento. Lo que importa es que la etiqueta no venga en el HTML, porque
ahí sí bloquea el análisis del documento.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…de navegación propia

Cierra la Fase 4 del plan de rediseño móvil.

- El tablero pasa de cuatro columnas apretadas a una a ancho completo, con
  un conmutador de estado que sustituye al desplazamiento a ciegas y a
  "Mover a…" en la tarjeta, porque el arrastre HTML5 del tablero no dispara
  con eventos táctiles.
- El modal de ticket deja de partirse en cuatro rejillas de dos columnas;
  los campos se apilan por debajo de `sm` y la cabecera se envuelve en vez
  de abrir un scroll horizontal.
- Nueva barra inferior de cuatro pestañas que sustituye a la hamburguesa en
  móvil, con hoja "Más" para lo que no cabe.
- Las filas de una tabla dinámica pasan a ficha en móvil, con los campos
  que sobran plegados.

Y una tanda de arreglos de capas y copy encontrados en captura real:
- La regla de área táctil resucitaba `.hidden` y forzaba `display` sobre
  enlaces que ya traían el suyo, así que en móvil aparecían controles que
  el código manda esconder (info, tema, idioma) y las tarjetas-enlace se
  volvían filas.
- Varios `z-50` puestos para que un tooltip ganara a las tarjetas también
  ganaban al panel de notificaciones y al cajón lateral.
- El modal "Acerca de" a 650px fijos, con atajos de teclado ofrecidos en
  un teléfono y tres cadenas sueltas en inglés.
- Un intermitente real en la paleta de comandos: una búsqueda que llegaba
  después de cerrar el diálogo lo repintaba. Cinco corridas limpias tras
  el arreglo, frente a una de cada ocho antes.

0 errores de typecheck, 322 unitarias, 234 e2e ×3 corridas limpias.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
`getTestDb` se quedó importado en escritorio-hover.spec.ts al reescribir la
prueba para acotarla a la tabla; el fichero siembra por la API, no por la base.

Biome lo cazó en CI y yo no, porque verificaba con typecheck, vitest y
playwright pero nunca corría el linter — que es justamente lo que bloquea el
merge.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@JoseSerpaCode
JoseSerpaCode merged commit de63d85 into main Aug 20, 2026
1 check passed
@JoseSerpaCode
JoseSerpaCode deleted the feat/movil-kb branch August 20, 2026 14:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant