Files
collective-lists/plan/fase-5-mobile-ux.md
Oier Bravo Urtasun 30a7c55252 docs: point DESIGN.md references to design/slate_collective/DESIGN.md
The duplicate design/DESIGN.md was removed; the authoritative "Monolith
Editorial" spec lives at design/slate_collective/DESIGN.md. Update
CLAUDE.md, README.md, and plan/fase-5-mobile-ux.md accordingly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:40:58 +02:00

9.8 KiB
Raw Blame History

Fase 5 — Rediseño UX Mobile ("Monolith Editorial")

Estado: Plan propuesto Duración estimada: 12 semanas Objetivo: reescribir la capa de presentación para que el app sea mobile-first, siguiendo las mockups de Stitch en design/*/screen.png y la dirección "Monolith Editorial" de design/slate_collective/DESIGN.md.

Esta fase sigue TDD: primero los tests, al final la verificación. Toda la cobertura funcional actual (211 tests) debe seguir verde. Los nuevos tests cubren responsive breakpoints y el shell mobile.


0. Brecha entre el estado actual y la dirección de diseño

Lo que ya funciona a favor del plan:

  • Modo Compra ya es full-screen overlay con z-50 (/lists/[id]/session) — compatible mobile.
  • Sticky bottom input con glassmorphism básico en /lists/[id] y /tasks/[id].
  • Tokens de diseño en app.css (RGB triplets + rgb(var(--token) / <alpha>)) compatibles con la paleta slate.
  • Swipe-to-delete touch en /lists/[id] para items (parcial — sin zona roja animada ni toast de "undo").

Lo que hay que introducir/ajustar:

  • El shell tiene una sidebar fija de 14rem que se muestra siempre. En mobile hay que ocultarla y mostrar top-bar con hamburger + bottom tab bar con glassmorphism.
  • Ningún header tiene el tratamiento de masthead editorial (uppercase label + big title) que piden las mockups (WORKSPACE / Shared Lists, CURRENT INVENTORY / Grocery List, etc.).
  • Las cards de listas en /lists son genéricas; la mockup mobile las quiere con icono, meta ("12 items · Shared with Family") y avatares de presencia overlapping.
  • Swipe-to-delete no tiene zona roja con fade + toast con undo (ver §UX Patterns en design/colectivo_design_reference.html).
  • Chips de frecuencia no son horizontalmente scrollables en mobile.
  • Headers de sección (todas las pantallas) usan text-xs uppercase tracking-wide pero sin el pairing masthead.
  • Padding actual px-6 no escala: mobile pide px-4, desktop px-6.

Scope deliberadamente no incluido:

  • Priority badges y secciones decorativas ("URGENT ACTION", "High Priority", "Bento Grid", "Backlog") de tasks_mobile — no hay datos funcionales que los respalden; la mockup es de referencia visual, no contractual.
  • "SAVE" manual en notas (seguimos con autosave).
  • Mic/voice search en search_mobile (fuera de alcance).
  • Meta ficticia tipo "Dairy • Weekly" en ítems de la compra — el modelo no tiene categorías.

5.0 Tests primero — escribir antes de implementar

Playwright (apps/web/tests/e2e/):

  • mobile-shell.test.ts:
    • M-01: en viewport 375×812 (iPhone 13), la sidebar NO es visible.
    • M-02: en viewport 375×812, el bottom tab bar es visible con 4 iconos (lists/tasks/notes/search) y el icono de la ruta activa tiene aria-current="page".
    • M-03: tap en el hamburger abre un drawer con el collective switcher + settings + logout.
    • M-04: en viewport 1280×800, la sidebar SÍ es visible y el bottom tab bar NO aparece.
  • mobile-masthead.test.ts:
    • M-05: cada ruta (/lists, /tasks, /notes, /search) muestra un elemento con data-testid="masthead-label" (uppercase) + data-testid="masthead-title" (big).
  • mobile-swipe-delete.test.ts:
    • M-06: en /lists/[id] con viewport mobile, simulate touch swipe-left en un item → se revela la zona roja con aria-label "Delete item".
    • M-07: full-swipe dispara el delete; toast con botón "Undo" restaura el ítem si se pulsa en < 4s.

Vitest (apps/web/src/lib/...):

  • swipe.test.ts — helper de estado del swipe (offset → revealed → committed) aislado para testeo sin DOM.
  • undoQueue.test.ts — cola de deletes con TTL de 4s que puede cancelarse.

Nota: los 211 tests existentes deben seguir pasando tras el rediseño. Ese es el verdadero smoke de regresión — no añadimos tests funcionales nuevos que dupliquen lo que ya hay.


5.1 Shell responsive

  • apps/web/src/lib/components/layout/MobileTopBar.svelte:
    • Hamburger (izq) + wordmark "Colectivo" (centro) + avatar (der)
    • Visible solo en md:hidden
    • Sticky top con glassmorphism (backdrop-blur-xl bg-surface/80)
  • apps/web/src/lib/components/layout/BottomTabBar.svelte:
    • 4 items: Lists, Tasks, Notes, Search. Solo iconos (sin texto).
    • Glassmorphism igual que la top bar.
    • Respeta env(safe-area-inset-bottom) con pb-[env(safe-area-inset-bottom)].
    • Active: text-slate-900 / inactive: text-slate-400.
    • Visible solo en md:hidden.
  • apps/web/src/lib/components/layout/MobileDrawer.svelte:
    • Se abre al tocar el hamburger.
    • Contiene: collective switcher (con lista de colectivos + emoji), botón "Manage collective", enlace a Settings, Sign out.
    • Backdrop con click-outside close + trap focus.
    • Usa CSS transform (no re-mount) para evitar pérdida de estado.
  • apps/web/src/routes/(app)/+layout.svelte:
    • Extraer la sidebar actual a DesktopSidebar.svelte, renderizar solo md:flex.
    • Renderizar <MobileTopBar /> + <main> + <BottomTabBar /> en mobile.
    • Main scroll area con pb-20 en mobile para dejar espacio al bottom bar.

5.2 Masthead editorial + responsive padding

  • Extraer un componente ScreenMasthead.svelte:
    <!-- props: label, title -->
    <p data-testid="masthead-label" class="text-[13px] font-semibold uppercase tracking-[0.05em] text-text-secondary">{label}</p>
    <h1 data-testid="masthead-title" class="text-[28px] md:text-[32px] font-semibold tracking-[-0.02em] text-text-primary">{title}</h1>
    
  • Aplicar en /lists (WORKSPACE / Shopping Lists), /tasks (TASK MANAGER / Productivity o Tareas), /notes (REPOSITORY / Notes), /search (OMNI-SEARCH / Find Anything.).
  • Reemplazar px-6 genérico por px-4 md:px-6 en contenedores principales.
  • Reemplazar max-w ausente por max-w-2xl mx-auto en pantallas de lectura (notes, search results) para mantener longitudes editoriales en pantallas grandes.

5.3 Rediseño de /lists mobile

  • Cards con el tratamiento de la mockup lists_mobile:
    • Icono grande (emoji / lucide) arriba-izq
    • Título + línea meta ({n} items · {member_count} members o Active si vacío)
    • Avatares de presencia overlapping (usa collectiveMembers ya cargado; máximo 3, "+N" si más)
    • Sin shadow — separa por bg-surface-raised sobre bg-background
  • Card "featured" (primera lista activa) a ancho completo; resto en grid 2×2 en mobile.
  • Sticky input conserva Plus + Create button como en la mockup.

5.4 Rediseño de /lists/[id] mobile

  • Top-bar contextual: back arrow + nombre de la lista (truncado) + menú 3-dots.
  • Fila de ítem:
    • Checkbox 24px a la izq
    • Nombre (body-lg) + meta opcional {unit} debajo si existe
    • Qty stepper a la derecha ( N +) siempre visible en mobile (quitar hover-only actual)
    • Handle de drag (GripVertical) oculto en mobile — se activa con long-press
  • Swipe-to-delete "zona roja":
    • Touch-move left → translate X y revela bg-red-500 text-white con icono Trash2 a la derecha
    • Threshold 48px = snap abierto; >72% del ancho = commit delete
    • Post-delete: toast con "Undo" durante 4s (ver undoQueue)
    • Reutilizar lógica existente y añadir animación de color + el componente de toast

5.5 Toast con "Undo" para deletes suaves

  • apps/web/src/lib/stores/undoQueue.ts:
    • scheduleUndoable({ label, restore, commit }) devuelve id
    • TTL 4s; si nadie llama undo(id), ejecuta commit; si llama undo, ejecuta restore
  • apps/web/src/lib/components/UndoToast.svelte:
    • Monta al fondo de la pantalla (encima del bottom bar en mobile)
    • Muestra label + botón "Undo"
    • Escucha el store y desaparece cuando la cola se vacía
  • Integrar en: delete de item (lists), delete de task, send-to-trash de nota.

5.6 Chips de frecuencia scrollables

  • ItemSuggestions.svelte: wrapper con overflow-x-auto flex-nowrap en mobile, grid en desktop.
  • Hacer los chips rounded-full bg-slate-200 dark:bg-slate-800 según DESIGN.md §5.

5.7 Adaptar /tasks, /notes, /search al shell + masthead

  • /tasks: masthead TASK MANAGER / Tareas. Quitar priority badges de las mockups (no están en el modelo). Mantener secciones "Pendientes / Completadas" con animación flip.
  • /notes: masthead REPOSITORY / Notes + contador {n} ENTRIES. Listado en una columna mobile; grid masonry solo en md+.
  • /search: masthead OMNI-SEARCH / Find Anything.. Las secciones ya tienen data-testid="search-group-*" — solo añadir badge "{n} MATCHES" junto al header.

5.Z Verificación final — todos los tests verdes

  • just test-all → 0 failures (los 211 actuales siguen verdes + los nuevos mobile tests)
  • Validación visual en DevTools iPhone 13 (375×812) + Pixel 7 (412×915) + Desktop (1280×800)
  • loginAs(USERS.borja) en Playwright con viewport mobile emulado — el shell mobile debe estar activo automáticamente.

Plan de ejecución (orden sugerido)

  1. 5.0 Tests primero — escribir los mobile tests aunque inicialmente fallen.
  2. 5.1 Shell responsive — sin esto, nada más es testable en mobile.
  3. 5.5 UndoQueue + UndoToast — dependencia de 5.4.
  4. 5.2 Masthead + padding — trivial, desbloquea los tests M-05.
  5. 5.3 / 5.4 / 5.6 — ajustes por pantalla.
  6. 5.7 — pulido de tasks/notes/search con el shell.
  7. 5.Z Verificación — correr toda la suite, snapshot visual, commit.

Criterio de aceptación

  • En viewport ≤ 768px: sidebar oculta, bottom tab bar + top bar visibles, drawer abre con el switcher.
  • Todas las pantallas tienen el par masthead (label uppercase + title big).
  • Swipe-left en un item revela la zona roja; full-swipe borra con toast de undo.
  • Los 211 tests funcionales siguen verdes. Los nuevos mobile tests (M-01..M-07) pasan.
  • Validado manualmente en DevTools en 3 viewports.