Sortable

1.0.0

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:

  1. Contenedor: list o grid reordenable.
  2. Ítem: componente individual (card, tag, row).
  3. Handler de movimiento: ícono o área visible para iniciar el drag.
  4. 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

NameTypeDefaultDescription

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'
'vertical'

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

NameTypeDefaultDescription

id*

'string'
'number'

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

NameTypeDefaultDescription

children

React.ReactNode

The content of the SortableItemHandle component