Skip to Content
snapgrid is a react-grid-layout v2 alternative built on dnd-kit. Drag, resize, repack, and drag between grids.
DocumentationGuidesNested grids

Nested grids

A grid can live inside a tile of another grid. Because every standalone <GridLayout> provides its own dnd-kit context, the inner and outer grids run independent drag sessions. Dragging an inner tile rearranges only the inner grid, and dragging the outer tile carries the whole nested grid along.

Nested grids
drag the panel by its header; drag the inner tiles freely

The one rule that keeps them from fighting: the outer grid must drag from a handle that sits outside the inner grid. Give the outer tile a header (the drag handle) and put the inner grid in the body. A pointer-down inside the inner grid then never arms the outer drag.

<GridLayout layout={outer} width={w} onLayoutChange={setOuter} dragConfig={{ handle: ".panel-head" }} > {outer.map((it) => it.i === "panel" ? ( <div key={it.i} className="panel"> <div className="panel-head">Nested board</div> {/* outer drag handle */} <div className="panel-body"> <InnerBoard /> {/* its own <GridLayout> */} </div> </div> ) : ( <div key={it.i} className="tile"> {it.i} </div> ), )} </GridLayout>

Why it works

Each <GridLayout> (or <SnapGridProvider>) that isn’t inside a <SnapGridGroup> creates its own dnd-kit provider and its own grid registry. So the inner grid’s draggables, droppable surface, and drag session are entirely separate from the outer’s. The handle gating (dragConfig.handle) is what keeps the shared pointer event from arming both. The inner tiles sit outside the outer’s handle, so only the inner grid responds.

Without a handle the outer tile drags from anywhere, including the inner grid, so a single pointer-down would arm both grids. Always give the outer grid a handle that lives outside the inner area.

Limits

  • Don’t nest inside one <SnapGridGroup>. A group resolves which grid the pointer is over by geometry, with no “innermost wins” rule, so an inner grid nested in the same group would be ambiguous. Keep nested grids as independent standalone grids.
  • No cross-level dragging. You can’t drag a tile out of the inner grid into the outer (or vice versa). Each grid commits its own layout independently. Nesting is for composition, not for moving tiles between levels. To exchange tiles between grids, use cross-grid dragging with sibling (not nested) grids.
  • Size the inner grid to its cell. The inner grid measures its own container with useContainerWidth, so it reflows naturally as the outer tile is resized.
Last updated on