- Added `useCompanyNavigationEntries` for defining navigation entries. - Created `CompanyContextBar` for displaying company information and navigation. - Developed `CompanyHeader` for showing company identity and status. - Introduced `CompanyNavigationSheet` for mobile navigation options. - Implemented `CompanySectionNavigation` for section-specific navigation. - Added `workspaceContentFocusTarget` to manage focus behavior. - Created `WorkspaceMobileNavigationProvider` for managing mobile navigation state. - Developed `WorkspaceMobileSheet` for consistent mobile sheet UI. - Added `WorkspaceSkipLink` for accessibility improvements. - Established `WorkspaceMobileNavigationContext` for navigation state management. - Created `WorkspaceNavigationContent` for displaying workspace navigation. - Implemented `WorkspaceSearchContent` and `WorkspaceSearch` for search functionality.
11 KiB
V01.1 — Navegación móvil y franja contextual
Primera entrega de la arquitectura responsive V01, 21 de octubre de 2026. V01 sigue parcialmente pendiente: esta entrega solo modifica la composición por debajo de 768 px.
Comportamiento implementado
- Cabecera móvil compacta: menú global, marca, búsqueda y cuenta. La búsqueda reutiliza estado, filtrado y destinos actuales, sin consultar activos/personas.
- Franja sticky con compañía, sección actual y botón Secciones; nombre completo accesible y tooltip para texto truncado. No hay 21 enlaces apilados antes del contenido.
- Sheet global con destinos, compañías y configuración; Sheet contextual con los 21 destinos, contadores, cambio de compañía y edición existentes. Una raíz modal y una presentación activa; el cambio contextual → global conserva modalidad sin apilar Sheet.
- Destinos con BrowserLink nativo,
aria-currenty estilos de Button; botones para acciones. Enter navega, Espacio conserva la interacción nativa de enlaces. Se verificaron Ctrl+clic y clic central abriendo otra pestaña, sin cerrar el menú original ni cambiar su URL. - Escape/cierre devuelve foco al disparador; navegación ordinaria lo traslada al contenido. Cancelar edición de compañía desde el menú devuelve foco a Secciones. Base UI conserva el trap y el bloqueo de fondo; no se implementan manualmente.
- Enlace Saltar al contenido al inicio del teclado, con destino
mainreal y separación del bloque sticky. Scroll vertical principal único; scroll propio en menús extensos y tabla horizontal cuando lo requiere. - Cruzar a 768 px cierra el menú y devuelve foco visible; volver a móvil no reabre menús. Apertura efímera, sin nuevas preferencias.
Las barras de escritorio, el colapso manual 228/72, la secundaria de 240, los filtros, paginación, rutas y permisos permanecen con sus contratos anteriores. La edición usa la acción ya disponible en la ficha: no se inventa un permiso ni se amplía acceso. No cambian inventory=1100, dashboard=1200 ni useCompactDetail; V01.2–V01.4 quedan pendientes.
Componentes y decisiones
CompaniesWorkspace compone WorkspaceMobileNavigationProvider, salto al contenido, sidebar y cabecera sobre el scroll existente. WorkspaceMobileSheet encapsula popup, título, cierre traducido y foco; el consumidor aporta contenido. Los controles de modalidad pertenecen a Base UI.
WorkspaceNavigationContent comparte destinos globales entre escritorio y móvil. useCompanyNavigationEntries concentra los 21 destinos contextuales; CompanySectionNavigation comparte presentación y contadores. CompanyContextBar y CompanyNavigationSheet contienen las responsabilidades móviles; CompanyHeader conserva el encabezado desktop extraído del componente anterior.
WorkspaceSearch conserva una sola consulta local; WorkspaceSearchContent comparte input/resultados entre las presentaciones. No duplica consultas remotas ni crea otro motor. El catálogo semántico propio incorpora MenuIcon de Tabler. No se modifica vendor ni se añaden dependencias.
Los estilos nuevos se limitan al shell móvil, sticky y separación de foco. El breakpoint de 768 es el existente; no se introducen 920/1160/1660 ni observadores de capacidad. Los enlaces de navegación usan las variantes públicas de Button sin el comportamiento de teclado de un botón no nativo.
Geometría medida
Mismo entorno sintético, cuatro pantallas y siete resoluciones antes/después: 28 geometrías por fase. Se esperó a carga, fuentes y transiciones. No son wireframes.
| Resolución | Activos: Y de main antes → después | Ancho main antes/después | Tabla útil antes/después |
|---|---|---|---|
| 320×640 | 1496,31 → 106 | 320 | 286 |
| 390×844 | 1429,66 → 106 | 390 | 356 |
| 768×1024 | 88 → 88 | 300 | 249 |
| 1024×768 | 88 → 88 | 556 | 505 |
| 1366×768 | 88 → 88 | 898 | 847 |
| 1440×900 | 88 → 88 | 972 | 921 |
| 1920×1080 | 88 → 88 | 1452 | 1401 |
A tamaño normal, cabecera/franja miden 57/49 px efectivos incluidos bordes. Ambos móviles cumplen main.y <= 128 y muestran título sin scroll. No hay overflow horizontal del documento en la matriz; la tabla conserva su scroll propio. Dashboard/directorio comienzan tras la cabecera compacta, sin franja de compañía. La escasa capacidad de tablet a 768 continúa como deuda de V01.2, no se presenta como corregida.
Validación ejecutada
Se preparó una única instancia desechable con scripts/visual-audit.py: no había archivo de sesión reutilizable. Login real de usuario ordinario, compañía y activo sintéticos, servicios/puertos propios. Las pruebas visuales bloquean escrituras HTTP; altas y ediciones se cancelan. No se accede a datos reales ni se retiran contenedores anteriores ajenos. Al terminar, el preparador retiró su entorno y eliminó la sesión privada; las evidencias permanecen sin credenciales.
Pruebas de componentes: nuevos casos es/en en apps/web/src/app.test.tsx y companies-page.test.tsx, con 21 href únicos, estado activo, nombres accesibles y menús cerrados sin compañía. Ambos casos pasan. No dependen de clases para simular interacciones; teclado/modalidad se comprueban en Chromium.
Se amplía scripts/visual-audit-ui.test.py, usando el mismo cliente MCP y preparador, sin otro framework. El directorio de salida es configurable y restringido a .artifacts/playwright/:
METIS_PLAYWRIGHT_STORAGE_STATE=.artifacts/playwright/authenticated-ID/session.json \
METIS_UI_AUDIT_DIRECTORY=.artifacts/playwright/v01-1/after \
python3 scripts/visual-audit-ui.test.py
Sustituir ID por la sesión activa, manteniendo el preparador abierto. La suite comprueba geometría, 21 destinos y último enlace por teclado, Tab/Shift+Tab/Espacio/Enter/Escape, retorno de foco, rutas y Atrás/Adelante, clics modificados, transferencia entre menús, búsqueda, sticky, resize, cuenta/idioma y edición cancelada. Incluye regresiones V02, V03, V06 y V09. Se espera al foco final de la primitiva tras atravesar sus guardas, no a una espera fija.
Resultado final: nueve pruebas MCP pasan en 288,506 s. Después se amplió el caso de teclado con un ciclo inverso de 26 pulsaciones Shift+Tab y se repitió ese caso completo: pasa en 25,263 s. En ambos sentidos se mantiene el foco en el Sheet y se alcanza el último destino. Logs: technical/visual-ui.log y technical/visual-keyboard.log.
Se simula un nombre largo mediante respuestas GET interceptadas, sin guardarlo. A 320 px conserva el presupuesto de 106 y no desborda. En 320×360 se alcanza el último enlace y el cierre permanece visible. La ampliación de fuente raíz al 200 % mantiene el ancho sin overflow y aumenta main.y a 210 px: excepción justificada al presupuesto nominal por ampliación de texto. Se conserva contenido y scroll; no se fuerza un alto fijo recortando textos.
El intento de zoom real con atajos de Chromium headless no cambió devicePixelRatio. No se declara comprobado zoom real 200/400 %: ampliar fuente y probar viewport de 320 son comprobaciones distintas. También quedan pendientes Cmd+clic en macOS, lector de pantalla, modo oscuro completo y combinaciones de muchos roles/compañías. El usuario ordinario no recibe enlace de administración de usuarios; el comportamiento administrativo conserva su condición existente.
Comprobaciones técnicas
| Comprobación | Resultado |
|---|---|
| Typecheck dirigido compañías y web | Pasa |
| Biome de los archivos TS/TSX/JSON modificados | Pasa |
| Espaciado ESLint dirigido | Pasa tras corregir cuatro separaciones |
| Nuevos tests de componentes es/en | 2 pasan |
pnpm build |
Pasa; conserva aviso de chunk grande |
pnpm typecheck |
Falla en vendor calendar.tsx:165, contrato locale de react-day-picker; sin modificar vendor |
pnpm lint |
Falla con 15 errores en código ajeno de fotos/procesos/migraciones; además avisos de assets de skills |
pnpm check |
Falla global; archivos modificados comprobados separadamente |
pnpm test con BD aislada |
Falla en dos expectativas antiguas de companies-page.test.tsx: «Personas (1)» y texto antiguo sobre acceso de persona. No se corrigen fuera de alcance; la suite global no se declara aprobada |
La BD de tests se crea en otro contenedor y se elimina al terminar. Se conserva el log de Turbo para distinguir paquetes ejecutados/cacheados y no atribuir validación a suites que su fallo haya interrumpido. Los fallos citados estaban documentados antes de V01.1; se contrastan con los archivos implicados, no se supone que todo error nuevo sea previo.
La consola de la suite final no registra errores ni warnings. En la matriz previa apareció un 404 accesorio de favicon; no bloquea navegación.
Durante desarrollo se corrigieron una expansión indebida del separador móvil y expectativas/esperas de las propias pruebas. Los intentos parciales no sustituyen el resultado final. No se ignora un fallo de la aplicación para hacer pasar una prueba.
Evidencias y documentación
Evidencias locales, excluidas de Git:
- Baseline y matriz posterior.
- Últimos resultados por escenario, historial de mediciones interactivas, ciclo de teclado ampliado, consola e índice de capturas con dimensiones y SHA-256.
- Activos 320 antes, después, Sheet contextual, global y búsqueda.
- Logs de comandos en
.artifacts/playwright/v01-1/technical/. Las capturas se abrieron y examinaron; geometría, snapshot y comportamiento son pruebas distintas.
Para compartir evidencias, entregar solo v01-1/; no incluir authenticated-*, sesiones ni credenciales. Se actualizan DESIGN.md y componentes de interfaz para esta entrega, conservando los estados de los otros hallazgos.
Skills consultadas: ux-navigation dirige orientación y separación de ámbitos; shadcn aporta contratos Sheet/Base UI y primitivas existentes; frontend-design conserva identidad y jerarquía; composición y reglas React justifican modelos compartidos, estado efímero y suscripción responsive acotada. La CLI informativa shadcn falló por DNS; se consultaron sus docs oficiales de Sheet y Dialog de Base UI, contrastadas con el código instalado. No se aplicaron auditores no instalados ni se instalaron herramientas.