fix(infra): gradle_run detecta android-sdk — issue 0076 #2
@@ -0,0 +1,80 @@
|
||||
---
|
||||
id: "0091"
|
||||
title: "kanban: drag-aware dropzones para abrir/cerrar sidebar"
|
||||
status: open
|
||||
created_at: 2026-05-14
|
||||
priority: medium
|
||||
app: kanban
|
||||
---
|
||||
|
||||
## Problema
|
||||
|
||||
Mover una card desde el board a una columna que vive en el sidebar (location="sidebar") obliga a:
|
||||
|
||||
1. Soltar la card en el board.
|
||||
2. Hacer click en el toggle del navbar (icono "menu") para abrir el sidebar.
|
||||
3. Volver a coger la card y arrastrarla a la columna sidebar.
|
||||
|
||||
Tres pasos manuales para una operacion que conceptualmente es una sola. Es friccion innecesaria — el sidebar deberia abrirse solo si el usuario claramente intenta llegar a el durante un drag.
|
||||
|
||||
## Solucion
|
||||
|
||||
Anadir una banda invisible de **32px** en el borde izquierdo del viewport (entre el header y el bottom). Mientras hay un drag activo, si el puntero entra en esa banda y se queda mas de **400ms** sin moverse fuera, el sidebar se abre solo (`setNavOpen(true)`).
|
||||
|
||||
### Comportamiento
|
||||
|
||||
- **Auto-open**: si `navOpen=false` y hay drag activo y el puntero entra en la banda → timer 400ms → abrir sidebar.
|
||||
- **Auto-close**: **fuera de scope** en este issue. La friccion principal es abrir. Cerrar el sidebar a mano tras el drop es un click; mantenerlo abierto despues del drop es ademas lo que el usuario suele querer (suelta en sidebar, mira lo que tiene parqueado, decide). Se documenta como followup si surge.
|
||||
- **Feedback visual**: mientras el drag esta activo y el puntero esta dentro de la banda, render de un borde/glow `inset 4px 0 0 var(--mantine-color-blue-4)` con pulso suave.
|
||||
|
||||
### Detalles tecnicos
|
||||
|
||||
- La banda es un `<div>` `position: fixed`, `left: 0`, `top: 50px` (alto del header), `bottom: 0`, `width: 32px`, `z-index: 200` (encima del main, debajo de modals que son `z-index: 1000+`).
|
||||
- `pointer-events: none` para no interferir con el drop target real (board). Detectamos `mouseover/out` mediante `document.addEventListener('mousemove')` solo cuando hay drag activo, y comprobamos `clientX < 32`. Esto evita problemas de event-routing con dnd-kit que ya tiene capturado el pointer.
|
||||
- Timer cancelado en cuanto el puntero sale, en cuanto el drag termina, o si el sidebar ya esta abierto.
|
||||
|
||||
### Frontend
|
||||
|
||||
1. `apps/kanban/frontend/src/App.tsx`
|
||||
- Reusar el state `activeCard`/`activeType` ya existente para saber si hay drag activo (`isDragging = activeCard !== null || activeColumnId !== null`).
|
||||
- Anadir `useEffect` que, mientras `isDragging`, escuche `mousemove` global y dispare timers de hover.
|
||||
- Render del overlay debajo del `AppShell` o dentro pero antes de `AppShell.Main`.
|
||||
|
||||
2. `apps/kanban/frontend/src/styles/dropzone.css` (nuevo)
|
||||
- Animacion `@keyframes` simple para el pulso del borde.
|
||||
- Class `.kanban-drag-edge` con la animacion + transition de opacity.
|
||||
|
||||
3. `apps/kanban/frontend/src/main.tsx`
|
||||
- Import del CSS nuevo.
|
||||
|
||||
4. `apps/kanban/frontend/src/components/KanbanColumn.tsx`
|
||||
- Anadir `data-column-id={column.id}` al Paper raiz para selectores estables en e2e.
|
||||
|
||||
### Tests
|
||||
|
||||
- **Playwright e2e**: `apps/kanban/frontend/e2e/sidebar-dropzone.spec.ts` usando funciones del registry (`pw_kanban_login`, `pw_drag_drop`, `pw_wait_predicate`).
|
||||
- Setup: garantizar via API (`page.request`) que existe al menos una columna sidebar y una card en una columna board.
|
||||
- Login → board cargado → assert sidebar collapsed (width 0 o el slot oculto).
|
||||
- Drag de la card hacia x=10 (banda izquierda) con `hoverMs: 600` para que el timer 400ms se cumpla.
|
||||
- Assert que el sidebar se abrio (`AppShell.Navbar` ahora visible con ancho > 0).
|
||||
- Drop directamente en la columna sidebar visible.
|
||||
- Assert via `/api/board` que la card cambio de `column_id` a la columna sidebar.
|
||||
|
||||
## Criterios de aceptacion
|
||||
|
||||
- [ ] Aparece una banda de 32px en el borde izquierdo cuando hay drag activo (con feedback visual sutil al hover).
|
||||
- [ ] Hover en la banda durante >=400ms con drag activo y sidebar cerrado → sidebar se abre.
|
||||
- [ ] Cancelar el hover (mover puntero fuera antes de 400ms) → sidebar sigue cerrado.
|
||||
- [ ] Terminar drag mientras el sidebar esta abierto por la banda → sidebar sigue abierto (no auto-close).
|
||||
- [ ] Drag card de board a columna sidebar funciona end-to-end en Playwright.
|
||||
- [ ] Vitest existentes siguen pasando.
|
||||
|
||||
## Ramas / commits
|
||||
|
||||
- Rama: `issue/0091-kanban-sidebar-drag-zones`
|
||||
- Merge `--no-ff` a master.
|
||||
|
||||
## Followups potenciales
|
||||
|
||||
- Auto-close: simetria total — cuando se drage **desde** una columna sidebar **hacia** el board, hover en la zona central-derecha cierra el sidebar tras 400ms. Cuesta diseñar bien la "zona de cierre" sin colisionar con la columna sidebar misma; postpuesto.
|
||||
- Persistir preferencia de "abrir-on-drag" en localStorage por si algun usuario no la quiere.
|
||||
Reference in New Issue
Block a user