Multi-column Layouts
Multi-column layouts can be achieved with two Puck APIs:
- The
<DropZone>
component, enabling you to nest components - The
inline
parameter, enable multi-directional drag-and-drop
Nesting components with DropZones
Puck provides support for nesting components via the <DropZone>
API.
The <DropZone>
component can be rendered anywhere within your component, creating a zone that you can drop components into.
import { DropZone } from "@measured/puck";
const config = {
components: {
Example: {
render: () => {
return (
<div>
<DropZone zone="my-content" />
</div>
);
},
},
Card: {
render: () => <div>Hello, world</div>,
},
},
};
The zone
identifier is unique to the component, and can be reused in different components.
You can combine multiple DropZones to achieve fixed 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>
);
},
},
Card: {
render: () => <div>Hello, world</div>,
},
},
};
Advanced CSS layouts
By default, Puck will wrap your components in a div
element for a vertical block
layout, restricting drag-and-drop to the y-axis.
The inline
component parameter allows you to eliminate the wrapping element. Combining this with DropZones enables advanced CSS layouts with multi-directional drag-and-drop.
Basic CSS grid example
For example, set inline: true
to implement CSS grid layouts. When using inline mode, you must specify which element is draggable by passing the puck.dragRef
prop to your element’s ref
prop.
import { DropZone } from "@measured/puck";
const config = {
components: {
Example: {
render: () => (
<DropZone
zone="my-content"
style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }} // Use CSS grid in this DropZone
/>
),
},
Card: {
inline: true, // Enable inline mode, removing the Puck wrapper
render: ({ text, puck }) => (
<div
ref={puck.dragRef} // Let Puck know this element is draggable
>
{text}
</div>
),
},
},
};
Advanced CSS grid example
You can create more sophisticated layouts, too. Here’s an advanced CSS grid example, with items spanning multiple rows and columns.
import { DropZone } from "@measured/puck";
const config = {
components: {
Example: {
render: () => (
<DropZone
zone="my-content"
style={{
display: "grid",
gridTemplateColumns: "1fr 1fr 1fr 1fr",
gridTemplateRows: "1fr 1fr 1fr 1fr",
gap: 16,
}}
/>
),
},
Card: {
inline: true, // Enable inline mode, removing the Puck wrapper
render: ({ text, puck }) => (
<div
ref={puck.dragRef} // Let Puck know this element is draggable
style={{
gridColumn: `span ${spanCol}`,
gridRow: `span ${spanRow}`,
}}
>
{text}
</div>
),
},
},
};
Restricting components
The allow
and disallow
DropZone props allow you 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={["Card"]} />
</div>
);
},
},
},
};
This can be combined with categories to restrict based on your existing groups:
import { DropZone } from "@measured/puck";
const config = {
categories: {
typography: {
components: ["Card"],
},
},
components: {
Example: {
render: () => {
return (
<div>
<DropZone
zone="my-content"
allow={categories.typography.components}
/>
</div>
);
},
},
},
};