Container

React Container component props, configuration, callbacks, and imperative ref API.

Container wraps a core SnapSort container and provides it to descendant Item and nested Container components through React context.

React owns the rendered collection. Supply synchronous state and ghost callbacks for every structural operation the container accepts; the adapter does not fall back to SnapSort’s Vanilla DOM callbacks.

import { Container, Ghost, Item } from "@snap-engine/snapsort-react";

<Container
  config={{ direction: "column", groupID: "tasks", callbacks }}
>
  {renderedEntries.map((entry) =>
    entry.kind === "ghost" ? (
      <Ghost key={entry.id} event={entry.event} />
    ) : (
      <Item key={entry.task.id} itemId={entry.task.id}>{entry.task.label}</Item>
    ),
  )}
</Container>

Here callbacks.onItemMove synchronously updates the task array, onGhostInsert/onGhostRemove update the temporary ghost entry, and renderedEntries merges that ghost into the React-rendered list. See Setup for the complete single-list implementation.

Props

type ContainerProps = {
  children?: ReactNode;
  className?: string;
  config: ContainerConfig;
  containerObject?: SnapSortContainer | null;
  itemId?: string;
  locked?: boolean;
  selected?: boolean;
  metadata?: Record<string, unknown>;
  style?: CSSProperties;
};
PropDefaultDescription
childrenundefinedItem and nested container content.
className""Extra class string applied to the rendered element.
configRequiredSnapSort container configuration.
containerObjectnullOptional existing core container object. The component does not own its creation.
itemIdundefinedRequired when this container is a sortable entry inside another container.
lockedtrueKeeps a nested container from being dragged. Set to false to make it draggable.
selectedfalseConsumer-owned selection flag for multi-item drags. Only meaningful when locked is false.
metadata{}Metadata assigned to the container object and exposed in callback events.
styleundefinedInline styles merged onto the container element.

Container forwards a ref to its core object and renders a div with snapsort-container plus a mode-specific class.

Config

OptionDefaultDescription
mode"euclidean"Drag/drop mode for this tree: "euclidean", "progressive", "insertion", or "swap".
strategyResolved from modeAdvanced custom { dropTarget, lifecycle } strategy pair that overrides mode.
direction"column"Main layout direction: "column" or "row".
groupID"default-group"Containers with the same group can exchange items.
mainAxisAlign"start"Main-axis alignment for virtual placement. Supports "start" and "center".
nameGeneratedHuman-readable container name.
animationDefault 100ms animationsReorder, drop, and click-move animation settings. Set to null to disable configured animations.
disableFlipfalseDisables FLIP movement animation.
noDropfalsePrevents the container from being a drop target. Useful for root layout containers.
dropAreafalseTreats the container as an explicit drop area for collision filtering.
callbacksNo persistent mutation defaultRequired framework-state/ghost callbacks plus lifecycle and validation hooks.

Mode is resolved from the root container when a drag starts, so nested containers in one drag tree should use the same mode.

Callbacks

CallbackWhen it runs
onItemMove(event)An item moves to a new container or index. Preferred for state-backed lists because it includes both from and to.
onItemSwap(event)Swap mode commits a pairwise slot exchange. Required for swap mode in the React adapter.
onItemInsert(event)An item is inserted into a container; this is the lower-level fallback for onItemMove.
onItemRemove(event)An item is removed through removeItem(id).
onDragStart(event)A drag is starting. Return false to veto it.
onDragEnd(event)A drag has ended and its mutation has committed.
onDropTargetChange(event)The prospective drop container or index changed. Fires on the root container.
canDrop(event)Resolves whether this container accepts the current drag. Keep it cheap.
onGhostInsert(event)A ghost item or insertion marker is inserted or moved. Required for interactive React containers; store the event and render Ghost.
onGhostRemove(event)A ghost item or insertion marker is removed. Required for interactive React containers; remove the matching rendered ghost.
createGhost(event)Notification hook only in React. Returned DOM nodes are ignored because React owns ghost DOM.
flushMutation(mutation)Runs a structural callback inside React’s synchronous commit. Supplied automatically.
awaitMutation()Deprecated compatibility callback.

Update React state synchronously in onItemMove or onItemSwap. The adapter wraps structural callbacks in flushSync, allowing SnapSort to read committed DOM before paint. Do not defer these updates with transitions, timers, animation frames, or promises. Missing callbacks fail clearly instead of mutating framework-rendered DOM.

Imperative Ref

Container components forward refs to their core container object.

import { useRef } from "react";
import { Container, Item } from "@snap-engine/snapsort-react";
import type { Container as SnapSortContainer } from "@snap-engine/snapsort";

export function ClickMove() {
  const source = useRef<SnapSortContainer>(null);
  const target = useRef<SnapSortContainer>(null);

  function moveToTarget(id: string) {
    if (!source.current || !target.current) return;
    source.current.moveItem(id, target.current, target.current.numberOfItems);
  }

  return (
    <>
      <Container ref={source} config={{ direction: "column", groupID: "cards", callbacks }}>
        {renderedSourceEntries}
      </Container>
      <Container ref={target} config={{ direction: "column", groupID: "cards", callbacks }}>
        {renderedTargetEntries}
      </Container>
    </>
  );
}

The omitted callbacks and rendered-entry construction are the same state/ghost pattern shown in Setup. Imperative and pointer moves both commit through onItemMove; moveItem never authorizes direct DOM mutation.

The ref exposes moveItem, removeItem, numberOfItems, groupID, direction, mainAxisAlign, dropArea, mode, config, callbacks, and dragSession from the core container.