[ Web Proxy ]
URL:
Viewing: https://snapgrid.dev [Back]  [Original]

snapgrid react-grid-layout alternative for React, Svelte & VueSkip to Content
New snapgrid now ships for Svelte 5: the same dnd-kit-native, headless-first grid drag, resize, repack, and drag between grids. See it in Svelte
ReactSvelteVueShowcaseRoadmapChangelog
RoadmapNext: Solid & vanilla-TS bindings on snapgrid's framework-agnostic core.See the roadmap

a dnd-kit grid react-grid-layout alternative

Grids that drag, resize, and repack.

A headless-first grid layout built on dnd-kit draggable, resizable, repacking tiles that compose with the sortables and droppables you already have. A component layer makes react-grid-layout users feel right at home too.

pnpm add @snapgridjs/react @dnd-kit/react @dnd-kit/dom
38kB brotlisnapgrid~8kB + dnd-kit~30kB

Why snapgrid

A 30-second example

Headless
import { DragDropProvider } from "@dnd-kit/react";
import { useContainerWidth, useGridContainer, useGridItem } from "@snapgridjs/react";
import { useState } from "react";

function Board() {
  const { width, containerRef } = useContainerWidth();
  const [layout, setLayout] = useState([
    { i: "a", x: 0, y: 0, w: 4, h: 2 },
    { i: "b", x: 4, y: 0, w: 4, h: 2 },
    { i: "c", x: 8, y: 0, w: 4, h: 2 },
  ]);

  // DragDropProvider is the outermost element; the grid host (Surface) sits
  // inside it, so useGridContainer resolves the provider's dnd-kit manager. A
  // dragged tile floats itself, so there's no overlay to render.
  return (
    <div ref={containerRef}>
      <DragDropProvider>
        <Surface layout={layout} width={width} onLayoutChange={setLayout} />
      </DragDropProvider>
    </div>
  );
}

function Surface({ layout, width, onLayoutChange }) {
  // useGridContainer is the grid host; it returns the grid's `group`.
  const { containerProps, group } = useGridContainer({ layout, width, onLayoutChange });
  return (
    <div {...containerProps}>
      {layout.map((it) => <Tile key={it.i} id={it.i} group={group} />)}
    </div>
  );
}

function Tile({ id, group }) {
  // each tile resolves its grid by `group`  like a dnd-kit sortable
  const { ref, style } = useGridItem({ id, group });
  return <div ref={ref} style={style} className="tile">{id}</div>;
}

Coming from react-grid-layout?

The <GridLayout> component layer mirrors react-grid-layout v2's model same controlled layout, onLayoutChange, and config objects so RGL users adopt it quickly, then drop any grid down to the headless hooks at their own pace. Same engine, no second migration.

react-grid-layout v2 snapgrid
import ReactGridLayout, { useContainerWidth, verticalCompactor } from "react-grid-layout";
import "react-grid-layout/css/styles.css";
import { GridLayout, useContainerWidth, verticalCompactor } from "@snapgridjs/react";

function Board() {
  const { width, containerRef, mounted } = useContainerWidth();

  return (
    <div ref={containerRef}>
      {mounted && (
        <ReactGridLayout
        <GridLayout
          width={width}
          layout={layout}
          gridConfig={{ cols: 12, rowHeight: 30 }}
          dragConfig={{ enabled: true, handle: ".handle" }}
          compactor={verticalCompactor}
        >
          {children}
        </ReactGridLayout>
        </GridLayout>
      )}
    </div>
  );
}

Migration path

Full comparison & migration guide
Light


Web Proxy Viewer  |  New URL  |  Original Page