Consigna y contexto aplicable
Construye una lista de tareas cuyos elementos se puedan reordenar. Los usuarios de ratón y táctiles pueden arrastrar un elemento, pero cada reordenamiento también debe ser posible con el teclado y con clics o toques que no requieran un movimiento de arrastre. Un usuario de lector de pantalla debe enterarse de qué elemento se movió y de su nueva posición. El diseño debe preservar el foco, admitir la cancelación, evitar la pérdida o duplicación de elementos y gestionar un guardado fallido sin dejar ambiguo el orden visible.
Asume que la lista base se renderiza por completo, cada elemento tiene un ID único estable y solo se mueve un elemento a la vez. Reordenar dentro de una lista virtualizada, mover varios elementos seleccionados y resolver ediciones concurrentes son preguntas de seguimiento. El framework no es la decisión principal: React puede renderizar la vista, pero la entrevista evalúa el modelado de entradas, la semántica accesible, la propiedad del estado y la verificación.
Arrastrar es una mejora, no la operación de negocio. La operación de negocio es "mover el elemento X a la posición final Y". El arrastre con puntero, los comandos de teclado y los controles de movimiento visibles deben invocar todos esa misma operación. Esta separación evita que tres vías de entrada produzcan tres órdenes sutilmente diferentes.
Qué evalúa el entrevistador
La primera señal es si el candidato separa la identidad de la posición. Los índices de los arreglos son posiciones temporales, por lo que no deben ser claves de React ni identidades persistentes de los elementos. Un ID de elemento estable selecciona qué se mueve; un índice final o un ID estable vecino selecciona hacia dónde se mueve.
La segunda señal es la precisión en accesibilidad. La operación por teclado de WCAG y el requisito de movimiento de arrastre de WCAG 2.2 están relacionados pero son independientes. Un atajo solo para teclado no proporciona por sí mismo una alternativa de un solo puntero a un usuario que puede hacer clic o tocar pero no puede mantener presionado y arrastrar. Los controles visibles Mover arriba, Mover abajo o Mover a pueden satisfacer ambas vías de entrada.
La tercera señal es la disciplina en el estado de interacción. Una respuesta sólida distingue entre inactivo, reordenamiento activo, confirmación y cancelación; retiene el orden original para la reversión; gestiona pointercancel, Escape y una colocación inválida; y no persiste cada posición de desplazamiento sobre un elemento (hover) como una actualización de negocio.
La cuarta señal es el comportamiento con tecnologías asistivas. La semántica nativa de listas y botones, un controlador de arrastre explícito, instrucciones concisas, un foco estable, un anuncio de estado cortés (polite) e indicadores visibles de colocación importan más que agregar muchos atributos ARIA. aria-grabbed y aria-dropeffect están obsoletos y no deben presentarse como la solución.
Finalmente, el entrevistador busca una verificación basada en evidencia: pruebas de reordenamiento puro, pruebas de ratón y táctiles, operación solo con teclado, comprobaciones con lectores de pantalla, aserciones de foco, comportamiento con movimiento reducido y colores forzados, y recuperación ante fallos de guardado. Un escaneo automatizado de accesibilidad no puede demostrar que un flujo de reordenamiento hablado sea comprensible.
Preguntas para aclarar antes de responder
- ¿El reordenamiento es dentro de una lista o entre listas? Una sola lista necesita una posición final; el movimiento entre listas también necesita propiedad de origen y destino, tipos de colocación permitidos y una actualización atómica.
- ¿El orden debe guardarse remotamente? El orden solo local puede confirmarse de inmediato. La persistencia remota necesita comportamiento para pendiente, éxito, fallo, reintento y conflicto de versiones.
- ¿Qué entradas están dentro del alcance? Los eventos de arrastre HTML solo para ratón son insuficientes si se requieren usuarios de pantalla táctil, teclado, conmutadores, voz o lectores de pantalla.
- ¿Hay visible una alternativa de clic o toque? Los atajos de teclado satisfacen una necesidad diferente. Para una lista ordenable no esencial, proporciona controles que puedan activarse con un solo puntero sin mantener presionado y moverlo.
- ¿El movimiento tiene vista previa inmediata o solo al soltar? La vista previa en tiempo real ofrece una retroalimentación visual más fuerte, pero la cancelación debe restaurar el orden original y los anuncios no deben saturar con cada píxel del puntero.
- ¿Se pueden seleccionar varios elementos? El movimiento de múltiples elementos cambia el modelo de un ID de elemento a un conjunto ordenado y requiere reglas para elementos mezclados entre móviles y bloqueados.
- ¿La lista está virtualizada? Las posiciones fuera de pantalla no existen como destinos de colocación en el DOM, por lo que las pruebas de impacto (hit testing), los anuncios, los recuentos totales y el movimiento por teclado deben operar sobre el modelo de datos.
- ¿Puede otro cliente reordenar de forma concurrente? En caso afirmativo, el contrato de guardado necesita una versión de la lista o una precondición equivalente y una política de conflictos explícita.
Estructura de respuesta en 30 segundos
"Modelaría el reordenamiento como un único comando puro: mover un ID de elemento estable a un índice final. El arrastre con puntero, las acciones de teclado y los botones visibles de Mover lo llaman. Usaría semántica nativa de listas y botones, preservaría el foco en el controlador movido y anunciaría su nueva posición. La sesión almacena el orden original, de modo que Escape, pointercancel, una colocación inválida o un fallo de guardado puedan restaurarlo. Luego verificaría el invariante de permutación y probaría los flujos de ratón, táctil, solo clic, teclado, lector de pantalla, foco y fallos".
Análisis detallado paso a paso
Comienza con una operación de datos canónica. La entrada utiliza un ID estable y un índice final basado en cero; la salida es un nuevo orden. La operación debe preservar cada ID exactamente una vez y dejar el arreglo de entrada intacto.
interface SortableItem {
id: string
label: string
}
function moveItem(
items: ReadonlyArray<SortableItem>,
itemId: string,
targetIndex: number,
): ReadonlyArray<SortableItem> {
const fromIndex = items.findIndex((item) => item.id === itemId)
if (fromIndex === -1 || items.length < 2) return items
const finalIndex = Math.max(0, Math.min(targetIndex, items.length - 1))
if (fromIndex === finalIndex) return items
const next = [...items]
const [movedItem] = next.splice(fromIndex, 1)
if (!movedItem) return items
next.splice(finalIndex, 0, movedItem)
return next
}Este comando tiene un costo de tiempo O(n) y de espacio O(n) porque la eliminación, inserción y copia de arreglos desplazan elementos. Eso es apropiado para una lista de tareas normal completamente renderizada. Una lista virtualizada muy grande puede almacenar claves de rango ordenables o aplicar movimientos del lado del servidor mediante IDs vecinos, pero esa complejidad adicional necesita evidencia del requisito de escala.
Utiliza IDs estables como claves de React. Con key={item.id}, React puede mover el nodo del elemento existente en lugar de tratar un nuevo índice como una nueva identidad. Esto ayuda a preservar el controlador enfocado y el estado local del elemento. Si una actualización asíncrona aún pierde el foco, mantén referencias indexadas por ID de elemento y restaura el foco a ese mismo controlador después del renderizado confirmado. No envíes el foco al inicio de la lista y no fuerces cambios de foco para los usuarios de puntero.
Haz que el marcado base sea comprensible sin arrastrar. Una lista ordenada y elementos de lista exponen la estructura de la colección. Cada elemento tiene un botón nativo llamado, por ejemplo, "Reordenar Revisión". Proporciona botones visibles Mover arriba y Mover abajo, o una acción Mover a la posición, con el nombre del elemento en cada nombre accesible. Deshabilita una acción de límite imposible. Estos controles funcionan mediante activación por clic, toque y teclado, por lo que son tanto una alternativa detectable como una vía de recuperación sencilla cuando falla el arrastre.
La distinción entre dos requisitos de accesibilidad cambia el diseño. La operación por teclado significa que el reordenamiento completo se puede realizar sin un dispositivo apuntador. Por separado, el movimiento de arrastre debe tener un método de un solo puntero que no requiera mantener presionado y mover el puntero cuando arrastrar no es esencial. El modo de arrastre con teclas de flecha puede satisfacer a los usuarios de teclado, pero no el segundo requisito, a menos que sus controles también se puedan operar mediante clic o toque. Los botones de movimiento visibles satisfacen ambos.
Un modo de arrastre por teclado compacto opcional puede reducir las pulsaciones repetidas de Tab. Enfoca el controlador de arrastre y presiona Enter o Espacio para comenzar; Flecha arriba y Flecha abajo cambian la posición candidata; Enter o Espacio confirman; Escape cancela y restaura la instantánea. Coloca estas instrucciones en texto referenciado por el controlador para que los usuarios puedan descubrirlas. Si el elemento también admite selección, mantén separados los comandos de selección y reordenamiento para que Espacio no tenga dos significados en el mismo objetivo de foco.
Representa la interacción como una sesión de corta duración. Al inicio, almacena itemId, el tipo de entrada, el orden original y el índice candidato actual. El movimiento de puntero o teclado solo actualiza el candidato mediante moveItem. La confirmación genera una solicitud de persistencia y un anuncio. La cancelación restaura el orden original y anuncia la cancelación. No se debe permitir que una nueva respuesta del servidor sobrescriba una sesión más reciente simplemente porque su solicitud terminó más tarde.
Para la entrada de puntero, usa un controlador explícito en lugar de hacer que toda la fila sea arrastrable. Esto evita que un arrastre robe clics a enlaces, casillas de verificación, selección de texto o desplazamiento. Si implementas la ordenación en la página con Pointer Events, espera un pequeño umbral de movimiento, captura el puntero, calcula la posición candidata a partir de los puntos medios de los elementos, expone un indicador de inserción que no dependa solo del color y gestiona pointerup, pointercancel, la pérdida de captura, el desplazamiento y una colocación fuera de la lista. Es preferible una biblioteca de arrastre probada cuando los sensores táctiles, el desplazamiento automático, la detección de colisiones, los contenedores con desplazamiento anidados y el comportamiento con tecnologías asistivas son todos requisitos.
El arrastrar y soltar nativo de HTML puede ser razonable para la transferencia de datos en escritorio o entre aplicaciones, pero no proporciona un flujo de trabajo de reordenamiento por teclado o lector de pantalla. Su modelo de eventos también requiere destinos de colocación válidos explícitos y suprime otros eventos de entrada del dispositivo durante un arrastre. Elegirlo no elimina la necesidad de controles de movimiento, comportamiento del foco, anuncios o verificación táctil.
Comunica los resultados a través de elementos visuales y semántica. Muestra el punto de inserción candidato con forma o borde así como con color, mantén un indicador de foco visible y respeta las preferencias de movimiento reducido. Usa una región de estado cortés (polite) persistente para mensajes cortos después de movimientos deliberados por teclado, confirmaciones, cancelaciones y fallos. Un mensaje como "Se movió Revisión a la posición 2 de 5" incluye el elemento, el resultado, la posición y el total. No anuncies cada desplazamiento de puntero y no recrees la región activa en el mismo momento que su mensaje.
Evita la semántica de arrastre obsoleta. WAI-ARIA 1.2 marca aria-grabbed y aria-dropeffect como obsoletos. Los elementos nativos, nombres accesibles, instrucciones descriptivas, el estado actual transmitido en texto y anuncios probados proporcionan un contrato más confiable. ARIA no agrega el comportamiento de teclado faltante ni una alternativa de clic ausente.
Para la persistencia remota, envía los IDs ordenados estables o un comando de movimiento más la versión que el cliente editó. Previsualiza de forma optimista el resultado, expón el estado de guardado sin bloquear el foco del teclado y confirma el anuncio solo bajo la regla de producto elegida. Ante un fallo de red, conserva el orden pendiente local con Reintentar o revierte a la instantánea y anuncia la reversión. Ante un conflicto de versiones, obtén el orden actual y pídele al usuario que reintente o aplica una fusión definida; sobrescribir silenciosamente el orden de otro cliente no es una estrategia de recuperación.
La verificación comienza con el comando puro. Prueba movimientos al primero, último, adyacente, misma posición, ID desconocido y fuera de rango. Para entradas generadas, asegura mediante aserciones que la salida contenga los mismos IDs con los mismos recuentos y solo el movimiento relativo solicitado. Luego ejecuta una matriz de interacción:
- arrastre con ratón, arrastre táctil, controles de solo clic y una colocación fuera de la lista;
- movimiento solo por teclado, confirmación, acción en el límite y cancelación con Escape;
- el foco permanece en el controlador del elemento movido después de cada renderizado y reversión;
- VoiceOver con Safari y NVDA con Firefox o Chrome anunciando elemento, instrucciones, nueva posición, cancelación y fallo de guardado una sola vez;
- zoom al 200%, colores forzados, alto contraste, movimiento reducido, etiquetas largas, desplazamiento y diseño RTL;
- éxito demorado, reordenamiento de solicitudes, fallo sin conexión, reintento y conflicto de versiones.
Las herramientas automáticas de accesibilidad pueden detectar nombres faltantes, atributos inválidos y algunos problemas de capacidad de foco. No pueden juzgar si el modelo de teclado es detectable, si la secuencia hablada es coherente o si un lector de pantalla táctil puede completar la tarea. Eso requiere uso manual.
Respuesta de muestra de alta calidad
"Mantendría la identidad del elemento independiente de la posición en el arreglo. El reducer acepta un ID de elemento y un índice final, devuelve una nueva permutación y es el único código autorizado a cambiar el orden. El arrastre con puntero, los botones Mover arriba o Mover abajo y cualquier modo de arrastre por teclado despachan todos ese mismo comando.
La base semántica sería una lista ordenada con botones nativos. Cada fila tiene un controlador de reordenamiento explícito y controles de movimiento visibles cuyos nombres accesibles incluyen la etiqueta del elemento. Los controles de movimiento son importantes porque el soporte de teclado y una alternativa de clic o toque al arrastre son requisitos separados. No dependería de aria-grabbed ni de aria-dropeffect; ambos están obsoletos.
Cuando comienza un reordenamiento, conservo el orden original y el ID del elemento activo. Las pruebas de impacto del puntero o las teclas de flecha actualizan solo una posición candidata. La confirmación envía un guardado y anuncia, por ejemplo, 'Se movió Revisión a la posición 2 de 5'. Escape, pointercancel, una colocación inválida o la regla elegida para fallos de guardado restauran la instantánea. Las claves estables de React mantienen enfocado el mismo controlador después de que cambia el orden en el DOM.
Para la ordenación con puntero usaría un controlador dedicado, un umbral de movimiento, captura de puntero, un indicador de inserción claro, comportamiento de desplazamiento automático y limpieza tras la cancelación. Si se requieren soporte táctil, desplazamiento anidado y manejo de colisiones entre navegadores, elegiría una biblioteca probada solo después de verificar su comportamiento con teclado y lectores de pantalla; una demostración con ratón no es suficiente.
Haría pruebas unitarias del invariante de permutación y luego completaría manualmente la tarea con ratón, táctil, teclado, controles de solo clic, VoiceOver y NVDA. También probaría el foco, Escape, colocación afuera, movimiento reducido, colores forzados, guardados demorados, respuestas obsoletas y conflictos de versiones. Eso verifica el contrato de interacción real; un escaneo automatizado por sí solo es insuficiente".
Errores comunes
- Usar índices de arreglos como claves → el reordenamiento cambia la identidad, el foco y el estado local del elemento → Usa IDs de elementos estables para claves y comandos.
- Hacer del arrastre la única interacción → los usuarios que no pueden mantener presionado y mover un puntero no pueden reordenar → Proporciona controles visibles de clic o toque con resultados equivalentes.
- Agregar teclas de flecha y afirmar que se cumplen todos los requisitos → la equivalencia de teclado por sí sola aún puede carecer de un método de un solo puntero sin arrastre → Evalúa los requisitos de teclado y movimiento de arrastre de forma independiente.
- Adjuntar escuchadores de arrastre a toda la fila → los enlaces, la selección, las casillas de verificación y el desplazamiento entran en conflicto con el reordenamiento → Usa un controlador explícito enfocable.
- Implementar algoritmos de reordenamiento separados para cada entrada → el ratón, el tacto y el teclado producen diferentes casos límite → Dirige cada entrada a un único comando con ID estable.
- Mutar el arreglo o el DOM directamente → el estado renderizado y el estado guardado divergen → Devuelve una nueva permutación desde el propietario del estado.
- Usar
aria-grabbedyaria-dropeffectcomo plan de accesibilidad → los atributos están obsoletos y no agregan interacción → Usa controles nativos, instrucciones, estado, foco y anuncios probados. - Anunciar cada movimiento del puntero → la región activa se vuelve ruidosa y retrasada → Anuncia pasos deliberados de teclado y resultados finales, no píxeles de puntero.
- Mover el foco al inicio de la lista después de reordenar → los usuarios pierden su lugar → Preserva o restaura el foco mediante el ID estable del elemento.
- Guardar cada posición de hover → las carreras de red pueden aplicar órdenes intermedios obsoletos → Persiste un único movimiento confirmado con una precondición de versión.
- Confiar solo en una auditoría automatizada → no puede validar instrucciones habladas ni flujos de entrada completos → Prueba con teclado real, táctil y lectores de pantalla.
Preguntas de seguimiento y respuestas
Seguimiento 1: ¿Qué cambia cuando la lista está virtualizada?
No trates las filas DOM montadas como la colección completa. Mantén el movimiento, el recuento total y la posición candidata en el modelo de datos. Los comandos de teclado pueden moverse por índice lógico incluso cuando el destino está fuera de pantalla, desplazando luego el elemento movido a la vista sin perder su objetivo de foco. El movimiento de puntero necesita pruebas de impacto conscientes del modelo y desplazamiento automático. Si la biblioteca no puede exponer una semántica precisa de la colección o un foco estable a través de la virtualización, un modo accesible no virtualizado puede ser la solución de compromiso más segura a la escala medida.
Seguimiento 2: ¿Cómo moverías varios elementos seleccionados?
Almacena un conjunto ordenado de IDs estables, preserva su orden relativo, elimínalos como un solo grupo e inserta el grupo en un único límite final. El anuncio incluye el recuento de elementos y el destino. La selección y el controlador de arrastre necesitan comandos separados, especialmente cuando Espacio ya conmuta la selección. Rechaza una selección mixta que contenga elementos bloqueados o define exactamente qué elementos permanecen; mover silenciosamente solo parte de la selección es ambiguo.
Seguimiento 3: ¿Qué sucede si dos clientes reordenan la misma lista de forma concurrente?
Adjunta una versión de lista o ETag a la solicitud de movimiento. El servidor acepta el movimiento solo si la versión coincide. En caso de conflicto, obtén el orden actual, conserva el elemento y destino previstos por el usuario como contexto, y ofrece un reintento o aplica una regla de fusión documentada. Last-write-wins solo es aceptable cuando el producto acepta explícitamente perder la decisión de ordenamiento de otro usuario.
Seguimiento 4: ¿Usarías arrastrar y soltar nativo de HTML, Pointer Events o una biblioteca?
El arrastrar y soltar nativo es útil para transferencias de datos en escritorio y externas, pero no proporciona el flujo de trabajo completo para teclado y tecnologías asistivas. Pointer Events ofrece control para la ordenación táctil y de ratón en la página, pero requiere detección de colisiones, captura, desplazamiento automático y limpieza. Una biblioteca es la mejor opción cuando esos comportamientos ya están probados, siempre que su teclado real, lector de pantalla táctil, foco y semántica DOM pasen la matriz de verificación del producto. Los controles de movimiento y el comando de reordenamiento canónico permanecen independientemente de la elección del sensor.
Seguimiento 5: ¿Qué pasa si el guardado falla después de que el usuario haya continuado trabajando?
Etiqueta cada reordenamiento confirmado con una secuencia del cliente y la versión del servidor en la que se basó. Un fallo tardío solo debe revertir el estado derivado de esa solicitud; no debe reemplazar un orden confirmado más reciente con una instantánea antigua. La política segura más simple es serializar los guardados, mantener un orden pendiente explícito y bloquear una segunda confirmación mientras se permiten el foco y la lectura. Una cola más responsiva necesita reajuste de base (rebasing) y pruebas de conflictos antes de que esté justificada.