Extending PuckUI overrides

UI overrides

đź’ˇ

The overrides API is highly experimental and is likely to experience breaking changes.

Overrides allow you to change how Puck renders its default interface. It can be used with or without composition.

There are many different overrides available. See the overrides API reference for the full list.

Implementing an override

Use the overrides prop to implement an override:

import { Puck } from "@measured/puck"; export function Editor() { return ( <Puck // ... overrides={{ // Render a custom element for each item in the component list componentItem: ({ name }) => ( <div style={{ backgroundColor: "hotpink" }}>{name}</div> ), }} /> ); }

Examples

Custom publish button

A common use case is to override the Puck header. You can either use the header override to change the entire header, or use the headerActions override to inject new controls into the header and change the publish button.

Here’s an example that also leverage the internal Puck API to replace the default publish button with a custom one:

import { Puck, createUsePuck } from "@measured/puck"; const usePuck = createUsePuck(); const save = () => {}; export function Editor() { return ( <Puck // ... overrides={{ headerActions: ({ children }) => { const appState = usePuck((s) => s.appState); return ( <> <button onClick={() => { save(appState.data); }} > Save </button> {/* Render default header actions, such as the default Button */} {/*{children}*/} </> ); }, }} /> ); }

Custom field type

An advanced use case is overriding all fields of a certain type by specifying the fieldTypes override.

import { Puck } from "@measured/puck"; export function Editor() { return ( <Puck // ... overrides={{ fieldTypes: { // Override all text fields with a custom input text: ({ name, onChange, value }) => ( <input defaultValue={value} name={name} onChange={(e) => onChange(e.currentTarget.value)} style={{ border: "1px solid black", padding: 4 }} /> ), }, }} /> ); }

Further reading