Sortable
El componente Sortable proporciona funcionalidad de arrastrar y soltar para crear listas ordenables, con soporte para orientación vertical y horizontal, navegación por teclado y manejadores de arrastre personalizables.
import React, { useState } from "react";
import { Sortable } from "@nimbus-ds/patterns";
import { Box, Card, Text } from "@nimbus-ds/components";
import { mockSortableItems as defaultItems } from "lib/mocks/mock-items";
const Example: React.FC = () => {
const [items, setItems] = useState(defaultItems);
return (
<Sortable items={items} onReorder={setItems} orientation="vertical">
<Box
display="flex"
flexDirection="column"
width="100%"
padding="2"
overflow="hidden"
>
{items.map((item) => (
<Sortable.Item key={item.id} id={item.id}>
<Box as="div" width="100%" marginY="2" cursor="grab">
<Card>
<Card.Body>
<Text>{item.content}</Text>
</Card.Body>
</Card>
</Box>
</Sortable.Item>
))}
</Box>
</Sortable>
);
};
export default Example;
Instalá el componente via terminal.
npm install @nimbus-ds/sortable
🔄 Sortable
El patrón Sortable permite reorganizar elementos dentro de una lista o grid mediante interacciones de drag and drop. Su propósito es ofrecer control directo al usuario sobre el orden de los elementos, facilitando la personalización y jerarquización visual de la información en flujos donde el orden es relevante.
Es ideal para experiencias donde el orden de los ítems tiene impacto funcional o visual, como listas de productos destacados, categorías, módulos de contenido, entre otros.
- Cuando el usuario necesita definir el orden de ítems según prioridad o jerarquía.
- En flujos donde los ítems tienen un orden preestablecido pero editable (ej. pasos, listas de prioridad).
- Cuando el orden de los elementos no tiene consecuencias visibles o funcionales.
Ejemplo: Una lista con más de 20 ítems donde el orden no modifica la funcionalidad del sistema. - En listas donde el contenido es extenso o el reordenamiento puede afectar datos relacionados sin validación.
- Si los elementos necesitan confirmación adicional para ser movidos (drag and drop no es óptimo en estos casos).
- Acción directa: Reordenar mediante drag and drop sin necesidad de confirmación adicional.
- Feedback visual inmediato: Al arrastrar, se destacan zonas válidas de inserción.
- Persistencia automática: Cambios de orden se guardan automáticamente o al salir del flujo.
- Reordenamiento parcial: El usuario puede modificar solo algunos ítems sin tener que reorganizar toda la lista.
- Navegación con teclado: asegurar foco y uso de teclas (Enter, Space, Arrow keys) para mover ítems.
- Soporte ARIA: usar aria-roledescription="sortable" en el contenedor de la lista, aria-describedby combinado con una live region para anuncios, y aria-live="polite" para anunciar cambios.
- Orientación de la lista: usar aria-orientation="vertical" o aria-orientation="horizontal" en el contenedor según corresponda.
- Controles de arrastre: si se usan botones como handles, aplicar aria-pressed para indicar estado activo durante la operación de arrastre.
- Roles adecuados: usar role="list" y role="listitem" donde aplique.
- Feedback textual visible para screen readers al mover ítems.
- Zonas de tap de mínimo 44×44 px.
El patrón Sortable puede incluir:
- Contenedor: list o grid reordenable.
- Ítem: componente individual (card, tag, row).
- Handler de movimiento: ícono o área visible para iniciar el drag.
- Indicador de posición: línea o sombra donde el ítem será soltado.
- #Card
- #Icon
- #IconButton
- #List o #Grid
- Event handlers de drag and drop (onDragStart, onDragOver, onDrop, etc.)
- Vertical: Ideal para listas simples.
- Horizontal: Útil para displays visuales como carruseles.
- Con Handler: Ícono o zona específica para iniciar el movimiento.
- Scroll vertical: Múltiples ítems dentro de contenedor scrollable.
- Renderizado personalizado: El ítem puede tener un layout específico.
✅ Do
- Usar drag and drop para facilitar al usuario a controlar el orden de una lista de items.
- Permitir guardar automáticamente o validar al finalizar el reordenamiento.
**❌ Don't **
- No ocultar el estado del ítem durante el drag (usar opacidad o sombra).
- No bloquear accesibilidad al teclado o screen readers.
- No permitir reordenar si los ítems están deshabilitados o son dependientes entre sí sin validación previa.
Las props adicionales se pasan al elemento <Sortable>. Consulta la documentación de div para ver la lista de props aceptadas por el elemento <Sortable>.
Sortable
Name | Type | Default | Description |
---|---|---|---|
children | React.ReactNode | The children components | |
disabled | boolean | Whether to disable sorting functionality | |
items* | array | The items to be sorted | |
onReorder* | object | Callback fired when items are reordered | |
onDragStart | object | Callback fired when drag starts | |
onDragOver | object | Callback fired during drag | |
onDragEnd | object | Callback fired when drag ends | |
orientation | 'horizontal' | The orientation of the sortable list | |
sensorOptions | object | Custom sensor options for drag detection | |
overlaySettings | object | Configuration for the drag overlay appearance and behavior | |
dndContextSettings | object | Settings for the DndContext | |
renderOverlay | object | Render function for the dragged item overlay |
Sortable.Item
Name | Type | Default | Description |
---|---|---|---|
id* | 'string' | The unique identifier for the item | |
disabled | boolean | Whether the item is disabled from being dragged | |
handle | boolean | Custom drag handle selector | |
children | React.ReactNode | The children components | |
renderItem | object | Optional render function that receives drag state and handlers, useful for fully customizing the item |
Sortable.ItemHandle
Name | Type | Default | Description |
---|---|---|---|
children | React.ReactNode | The content of the SortableItemHandle component |