Bonsai

Mini app · laboratorio de interfaces

Interacciones

¿Qué librerías hay hoy para arrastrar y soltar y para animar interfaces, qué tan pulida queda la experiencia con cada una y para qué tipo de aplicación conviene? Cada escenario se parece a una app real y está hecho con varias librerías sobre los mismos datos, para compararlas lado a lado.

Recomendaciones

La conclusión del laboratorio, para cuando haya que elegir en un proyecto real. No hay una librería ganadora: depende de la aplicación.

Antes de elegir: decidir que no habrá accesibilidad

Si se busca una experiencia premium, sobre todo en apps para ingenieros civiles, hay que definir desde el principio que no se implementará nada de accesibilidad (lectores de pantalla, alternativas al arrastre sin ratón, anuncios). Los usuarios son conocidos: trabajan en escritorio, con ratón y teclado, sin problemas de visión. Esa decisión es la que permite elegir por la sensación.

  • Se puede elegir arrastre «dibujado» (Motion, dnd-kit), que anima, en vez del nativo (Pragmatic, React Aria), que no anima nada.
  • No hace falta React Aria (73 KB) ni menús «Mover arriba/abajo» como alternativa al arrastre.
  • El tiempo va a lo que el usuario nota: resortes, huecos que se abren, aterrizajes, tarjetas que se inclinan.
  • Los atajos de teclado sí entran, pero como productividad (como en AutoCAD), no como accesibilidad.
  • Si algún día un cliente lo exige por norma (sector público, WCAG), se revisa la elección: ahí React Aria sí tiene sentido.

Una lista que se reordena (tareas, capas de un plano, pasos de un proceso, partidas)

Motion (Reorder)

Cómo: Reorder.Group + Reorder.Item con asa (useDragControls). Guardar el orden en un borrador local y confirmarlo en el store al soltar.

Evitar: Pragmatic o React Aria: arrastre nativo, nada se anima hasta soltar.

Varias listas entre las que se mueven elementos (Kanban, asignar tareas a personas o frentes de obra)

dnd-kit

Cómo: @dnd-kit/react con useSortable (group por columna) y move() de @dnd-kit/helpers sobre un borrador; fijar la versión exacta (aún es 0.x).

Evitar: Motion solo: hay que escribir el arrastre a mano (3,6 veces más código).

Animar una interfaz que cambia: filtros, orden, cambio de vista, abrir un detalle

Motion

Cómo: layout en cada elemento, AnimatePresence para entradas y salidas, layoutId para el elemento compartido, y resortes en vez de duraciones.

Evitar: View Transitions dentro de una misma pantalla: bloquea los clics mientras anima y no se interrumpe.

Pulir en minutos una lista o tabla que crece y decrece

AutoAnimate

Cómo: Una línea: useAutoAnimate() en el contenedor.

Evitar: Esperar que anime cambios de diseño (cuadrícula ↔ lista): no lo hace.

Transiciones entre páginas de Next.js (una miniatura que se convierte en la página de detalle)

View Transitions

Cómo: <ViewTransition name> con el mismo nombre en las dos páginas; la navegación ya es una transición.

Evitar: Usarla con estado en Zustand o Jotai: sus actualizaciones no la disparan.

Soltar archivos desde el escritorio o arrastrar entre ventanas

Pragmatic

Cómo: El adaptador de archivos externos de Pragmatic (o react-dropzone, pendiente de comparar en el nivel 2).

Evitar: dnd-kit y Motion: no usan el arrastre nativo del navegador.

Veredictos, escenario por escenario

Lista ordenable · tipo Todoist

Motion

Resortes y deslizamiento en vivo: «ampliamente superior».

Kanban · tipo Trello

dnd-kit

Las tarjetas se apartan en vivo entre columnas y trae resuelto lo difícil con el menor código.

Galería animada · tipo Pinterest

Motion

Se puede interrumpir, transforma la imagen en el detalle y anima el cambio a lista.

Fichas de las librerías

Peso: lo que añade cada implementación al paquete, minificado y con gzip, sin contar React ni el código común. Medido el 2026-10-18 con pnpm measure:interacciones. La fluidez depende del equipo: se mide en el laboratorio con el medidor de fotogramas.

dnd-kit

arrastre@dnd-kit/react, @dnd-kit/helpers · 0.5.1 · MIT

El kit de arrastrar y soltar más usado en React. El elemento se arrastra «dibujado» por la librería y un plugin reordena el DOM en vivo mientras lo mueves.

Lista: 38,1 KB · 79 líneasKanban: 38,3 KB · 93 líneas

Úsala para

  • Tableros con varias listas (Kanban, planificadores, asignar tareas a personas)
  • Cuando los demás elementos deben apartarse en vivo mientras arrastras
  • Cuando quieres el desplazamiento automático y la cancelación ya resueltos

No la uses para

  • Arrastrar archivos desde el escritorio o entre ventanas (no usa el arrastre nativo)
  • Una sola lista simple donde importa más la animación que la lógica (Motion se siente mejor)
Hallazgos y mantenimiento
  • El Kanban salió con 93 líneas: el borrador del tablero se reordena con `move()` de @dnd-kit/helpers.
  • Sus anuncios para lector de pantalla vienen en inglés y con los ids internos («Draggable item t3 was dropped»).
  • Emite un evento de «sobre destino» justo al levantar, sobre la misma posición.
  • @dnd-kit/core (la versión clásica) no publica desde diciembre de 2024; la nueva @dnd-kit/react aún no llega a la 1.0.
  • Mantenimiento: Activa (0.5.1, octubre de 2026), pero antes de la 1.0: la API puede cambiar. Fijar la versión.

Pragmatic drag and drop

arrastre@atlaskit/pragmatic-drag-and-drop (+ hitbox, auto-scroll) · 4.0.0 · Apache-2.0

La de Atlassian (Trello, Jira). Usa el arrastre nativo del navegador: la librería solo informa dónde está el puntero y la app dibuja todo lo demás.

Lista: 9,1 KB · 241 líneasKanban: 11,4 KB · 221 líneas

Úsala para

  • Arrastrar archivos, texto o enlaces desde fuera de la página, o entre ventanas
  • Cuando el peso importa: la más liviana de las librerías de arrastre
  • Apps muy grandes donde nada debe re-renderizarse mientras se arrastra

No la uses para

  • Cuando se espera que los elementos se aparten en vivo: nada se mueve hasta soltar
  • Prototipos rápidos: el indicador, la vista previa y la animación al soltar son trabajo tuyo
Hallazgos y mantenimiento
  • La vista previa es una imagen fija que genera el navegador; para inclinarla como Trello hay que dibujarla aparte (setCustomNativeDragPreview).
  • El desplazamiento automático es un paquete separado.
  • No trae arrastre con teclado: Atlassian recomienda un menú «Mover».
  • Unas 2,4 veces más código que dnd-kit para el mismo Kanban.
  • Mantenimiento: Activa (4.0.0, septiembre de 2026). Respaldada por Atlassian.

Motion

animaciónmotion (antes Framer Motion) · 14.3.0 · MIT

Librería de animación: resortes, animaciones de diseño (`layout`), entradas y salidas, elementos compartidos (`layoutId`). Reorder ordena una sola lista arrastrando.

Lista: 47,6 KB · 81 líneasKanban (arrastre propio): 53,3 KB · 337 líneasGalería: 47 KB · 105 líneas

Úsala para

  • Que la interfaz se sienta viva: listas que se reordenan, filtros, cambios de vista
  • Animaciones que se interrumpen sin saltos (pulsar varias veces seguidas)
  • Elemento compartido dentro de una página: una miniatura que se convierte en el detalle
  • Una lista ordenable sencilla (Reorder)

No la uses para

  • Arrastrar entre varias listas: no lo trae y hay que escribir la lógica (337 líneas en el Kanban)
  • Cuando cada KB cuenta y basta con animaciones básicas (AutoAnimate o CSS)
Hallazgos y mantenimiento
  • Ganó en la lista y en la galería: los resortes y el deslizamiento en vivo se notan.
  • En el Kanban se puede igualar la sensación, pero con 3,6 veces el código de dnd-kit.
  • Reorder no tiene teclado ni anuncios para lector de pantalla.
  • Mantenimiento: Muy activa (14.3.0, octubre de 2026).

React Aria

arrastre accesiblereact-aria-components · 1.22.1 · Apache-2.0

Componentes accesibles de Adobe. Su arrastre usa el nativo con ratón y uno propio con teclado y lector de pantalla, con los anuncios ya traducidos.

Lista: 73,3 KB · 66 líneas

Úsala para

  • Apps donde la accesibilidad es requisito (sector público, normas WCAG)
  • Si ya usas sus componentes (listas, tablas, menús) y quieres arrastre coherente con ellos

No la uses para

  • Apps de Bonsai y de ingeniería: la accesibilidad no es requisito y es la más pesada (73 KB)
  • Cuando importa la sensación: el arrastre nativo no anima nada
Hallazgos y mantenimiento
  • Lo más completo con teclado: foco, flechas, Enter, Escape y anuncios en español sin configurar nada.
  • Los anuncios en español son formales («Pulse el tabulador…») y al soltar no dicen la posición.
  • Por defecto incluye las traducciones de todos sus idiomas, parte de su peso.
  • Mantenimiento: Muy activa (1.22.1, octubre de 2026). Respaldada por Adobe.

AutoAnimate

animación@formkit/auto-animate · 0.10.0 · MIT

Una línea (`useAutoAnimate`) sobre un contenedor: anima a los hijos que entran, salen o cambian de orden en el DOM.

Galería: 3,9 KB · 63 líneas

Úsala para

  • Pulir en minutos listas, tablas o tarjetas que cambian (añadir, quitar, filtrar)
  • Cuando no quieres tocar el marcado ni aprender una API

No la uses para

  • Cambios de diseño sin cambios en la lista (cuadrícula ↔ lista): no los anima
  • Elementos compartidos o animaciones a medida
Hallazgos y mantenimiento
  • La implementación más corta de la galería (63 líneas) y de las más livianas (4 KB).
  • Al cambiar a vista de lista no hubo ni una animación: solo reacciona a cambios en los hijos.
  • Mantenimiento: Activa (0.10.0, julio de 2026), aún antes de la 1.0.

View Transitions (React 19.3)

nativo del navegadorreact (<ViewTransition>) + API del navegador · React 19.3.0 · MIT

Sin librería: el navegador toma una «foto» antes y otra después del cambio y anima entre ellas. React decide qué elementos tienen nombre; las animaciones se escriben en CSS.

Galería: 0,9 KB · 73 líneas

Úsala para

  • Transiciones entre páginas en Next.js: la navegación ya es una transición
  • Un elemento compartido entre rutas (miniatura → página de detalle)
  • Cuando no quieres añadir ni un KB

No la uses para

  • Interfaces donde el usuario pulsa seguido: durante la animación la página no responde a los clics
  • Estado en un store externo (Zustand, Jotai): sus actualizaciones no disparan la transición
Hallazgos y mantenimiento
  • Solo anima actualizaciones dentro de startTransition; por eso la galería guarda su estado en React y no en Zustand.
  • No se puede interrumpir: una nueva transición espera o salta al final de la anterior.
  • Con muchos elementos con nombre, el navegador toma una foto de cada uno.
  • Mantenimiento: Estable en React 19.3; en Chromium completo, en Safari y Firefox recientes con diferencias.

Características por nivel

Nivel 1 · tres escenarios, comparación directacompleto

  • Lista ordenable tipo Todoist con dnd-kit, Pragmatic, Motion y React Aria
  • Kanban tipo Trello con dnd-kit, Pragmatic y Motion (con arrastre propio): columnas reordenables, tarjetas entre columnas, desplazamiento automático
  • Galería tipo Pinterest con Motion, AutoAnimate y View Transitions: filtrar, ordenar, barajar, añadir, quitar, cuadrícula ↔ lista y detalle con elemento compartido
  • Medidor de fotogramas, 20/500 elementos, estado guardado y pestaña y librería en la URL
  • Peso y líneas de cada implementación medidos con un script

Nivel 2 · amplitudpendiente

  • Árbol tipo explorador de VS Code: headless-tree frente a react-arborist
  • Tablero de widgets tipo Grafana: react-grid-layout frente a gridstack
  • Editor de nodos tipo n8n: React Flow
  • Paneles redimensionables tipo VS Code: react-resizable-panels
  • Soltar archivos tipo Drive: react-dropzone frente al arrastre nativo de Pragmatic

Nivel 3 · opcional

  • Gestos táctiles (carrusel, deslizar tipo Tinder, panel inferior) con Embla y Motion
  • Lienzo infinito tipo Miro con tldraw (licencia propia)

La accesibilidad (lectores de pantalla, alternativas al arrastre sin ratón) no es requisito en Bonsai y no es criterio de comparación; aparece solo como dato en las fichas.

Hecho a mano

Arrastre del Kanban con Motion
Umbral, tarjeta flotante, destino por centros, desplazamiento automático, aterrizaje y cancelación: lo que Motion no trae.
Masonry
La posición de cada tarjeta se calcula antes de pintar, como Pinterest.
Ilustraciones
SVG generados desde una semilla, una silueta por tipo de obra.
Medidor de fotogramas
Tiempo entre requestAnimationFrame mientras dura la interacción.
Medición de peso
Script con esbuild que empaqueta cada implementación por separado.

Descartadas de entrada

react-beautiful-dnd
Deprecada oficialmente por Atlassian.
@hello-pangea/dnd, swapy
Sin publicar desde inicios de 2025.
@use-gesture/react, vaul
Sin publicar desde 2024.
@dnd-kit/core, @dnd-kit/sortable
Congeladas desde diciembre de 2024; se usó la nueva @dnd-kit/react.