DocsIntegrating PuckMulti-column Layouts

Multi-column Layouts

Multi-column and other complex layouts can be achieved by nesting components.

Using DropZones

Puck provides support for nesting components via the <DropZone> API.

Nesting components

The <DropZone> component can be rendered anywhere within your component.

import { DropZone } from "@measured/puck";
 
const config = {
  components: {
    Example: {
      render: () => {
        return (
          <div>
            <DropZone zone="my-content" />
          </div>
        );
      },
    },
    HeadingBlock: {
      render: () => <p>Hello, world</p>,
    },
  },
};
Interactive Demo
Nested components example

Creating multi-column layouts

Combine multiple <DropZone> components with something like CSS Grid or Flexbox to achieve multi-column layouts.

import { DropZone } from "@measured/puck";
 
const config = {
  components: {
    Example: {
      render: () => {
        return (
          <div
            style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}
          >
            <DropZone zone="left-column" />
            <DropZone zone="right-column" />
          </div>
        );
      },
    },
    HeadingBlock: {
      render: ({ text }) => <p>{text}</p>,
    },
  },
};
Interactive Demo
Multi-column DropZone example

Reusing the zone

The zone identifier is unique to the component, and can be reused in different components.

import { DropZone } from "@measured/puck";
 
const Columns = () => (
  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
    <DropZone zone="left-column" />
    <DropZone zone="right-column" />
  </div>
);
 
const config = {
  components: {
    Example: {
      render: () => {
        return (
          <div>
            <Columns />
          </div>
        );
      },
    },
    Alternative: {
      render: () => {
        return (
          <div>
            <Columns />
          </div>
        );
      },
    },
  },
};

Restricting components

The allow and disallow props allow us to restrict which components can be dragged into a DropZone.

import { DropZone } from "@measured/puck";
 
const config = {
  components: {
    Example: {
      render: () => {
        return (
          <div>
            <DropZone zone="my-content" allow={["HeadingBlock"]} />
          </div>
        );
      },
    },
  },
};

This can be combined with categories to restrict based on your existing groups:

import { DropZone } from "@measured/puck";
 
const config = {
  categories: {
    typography: {
      components: ["HeadingBlock"],
    },
  },
  components: {
    Example: {
      render: () => {
        return (
          <div>
            <DropZone
              zone="my-content"
              allow={categories.typography.components}
            />
          </div>
        );
      },
    },
  },
};

Further reading