Component Configuration
Puck's core behaviour is configured via the Config. This describes:
- which components are available to Puck
- how to render each component
- which fields to show when the user selects a component
- additional information, like category grouping
The Config is provided via the config
prop to the main Puck components:
<Puck>
reads the Config and renders an editor UI. The user interacts with the editor to produce a data payload.<Render>
walks a data payload and renders it according to the provided Config.
The render
function
Components can be defined by via the components
object in Config. Every definition must provide a render
function:
const config = {
components: {
HeadingBlock: {
render: () => {
return <h1>Hello, world</h1>;
},
},
},
};
This tells Puck that HeadingBlock is a valid component, and describes how to render it.
When the user drags the component onto the preview and hits Publish in the editor UI via the <Puck>
component, this Config will produce a data payload like this:
{
"content": [
{
"type": "HeadingBlock",
"props": {
"id": "HeadingBlock-1234"
}
}
],
"root": {}
}
The data payload and Config together tell <Render>
how to render the page. It can also be provided to <Puck>
as an initial data
payload.
TypeScript
If you're using TypeScript, we recommend strictly typing your config:
import type { Config } from "@measured/puck";
type Components = {
HeadingBlock: {};
};
const config: Config<Components> = {
components: {
HeadingBlock: {
render: () => {
return <h1>Hello, world</h1>;
},
},
},
};
Adding fields
Fields allow users to provide input to components. The value of each field is passed in as a prop to the render
function.
You can define a field via the fields
parameter:
const config = {
components: {
HeadingBlock: {
fields: {
title: {
type: "text",
},
},
render: ({ title }) => {
return <h1>{title}</h1>;
},
},
},
};
This will render a Text field when the user selects an instance of the HeadingBlock component in the editor UI.
When the user modifies the input, the editor will produce a data payload like this:
{
"content": [
{
"type": "HeadingBlock",
"props": {
"id": "HeadingBlock-1234",
"title": "Hello, world"
}
}
],
"root": {}
}
TypeScript
It's best to define the props for the component if using TypeScript. This enables strict type checking for your fields.
import type { Config } from "@measured/puck";
type Components = {
HeadingBlock: {
title: string;
};
};
const config: Config<Components> = {
// ...
};
Setting default props
Default props allow you to set an initial value for a prop when a new component is added.
Provide an object to the defaultProps
parameter to configure this:
const config = {
components: {
HeadingBlock: {
fields: {
title: {
type: "text",
},
},
defaultProps: {
title: "Hello, world",
},
render: ({ title }) => {
return <h1>{title}</h1>;
},
},
},
};
Unlike default parameters (opens in a new tab), defaultProps
are stored in the data payload and will populate the Puck fields.