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.

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

<Container config={{ direction: "column", groupID: "tasks" }}>
  <Item itemId="task-1">Task 1</Item>
</Container>

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.
callbacksDefault DOM callbacksHooks for DOM, framework state, and custom ghost behavior.

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. Falls back to two onItemMove events when undefined.
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.
onGhostRemove(event)A ghost item or insertion marker is removed.
createGhost(event)Creates a flow ghost or insertion/swap marker.
flushMutation(mutation)Runs a structural callback inside React’s synchronous commit. Supplied automatically.
awaitMutation()Deprecated compatibility callback.

For state-backed lists, 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.

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" }}>
        <Item itemId="card-1">
          <button type="button" onClick={() => moveToTarget("card-1")}>Move card</button>
        </Item>
      </Container>
      <Container ref={target} config={{ direction: "column", groupID: "cards" }} />
    </>
  );
}

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