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>
);
},
},
},
};