Theming
Customise button variants, colour presets and focus rings with ThemeProvider, and read the theme in your own components.
The theme controls the classes the built-in components use for button variants, the colour presets offered by colour pickers, and the focus ring. Anything you leave out falls back to the defaults, which use shadcn/ui-style classes such as bg-primary text-primary-foreground.
On the frontend
Wrap the renderer in ThemeProvider:
import { PageRenderer } from '@delmaredigital/payload-puck/render'
import { baseConfig } from '@delmaredigital/payload-puck/config'
import { ThemeProvider } from '@delmaredigital/payload-puck/theme'
<ThemeProvider theme={{
buttonVariants: {
default: { classes: 'bg-primary text-white hover:bg-primary/90' },
secondary: { classes: 'bg-secondary text-foreground hover:bg-secondary/90' },
},
focusRingColor: 'focus:ring-primary',
colorPresets: [
{ hex: '#3b82f6', label: 'Brand Blue' },
{ hex: '#10b981', label: 'Success' },
],
}}>
<PageRenderer config={baseConfig} data={page.puckData} />
</ThemeProvider>In the admin editor
Pass the theme to the plugin, and the editor inside the Payload admin uses it for its canvas and preview:
import { createPuckPlugin } from '@delmaredigital/payload-puck/plugin'
import { puckTheme } from './lib/puck-theme'
createPuckPlugin({ theme: puckTheme })The plugin's theme wins over a PuckConfigProvider theme in the admin editor. Before 0.11.0 this option is ignored, so pass the theme to PuckConfigProvider instead.
In a standalone editor
Pass the same theme to PuckConfigProvider (or PuckEditor) as theme, so the editor preview and the colour pickers match:
import { puckTheme } from '@/lib/puck-theme'
<PuckConfigProvider config={editorConfig} theme={puckTheme}>
{children}
</PuckConfigProvider>Keep the theme in one module and import it in both places. The starter files include a complete puck-theme.ts.
Theme options
Prop
Type
In custom components
Read the resolved theme with useTheme():
import { useTheme } from '@delmaredigital/payload-puck/theme'
function CustomButton({ variant }) {
const theme = useTheme()
const classes = theme.buttonVariants[variant]?.classes
return <button className={classes}>...</button>
}/theme also exports useHasThemeProvider(), getDefaultTheme(), resolveTheme(), getVariantClasses(), getBackgroundClasses(), the defaults (DEFAULT_THEME, DEFAULT_BUTTON_VARIANTS, DEFAULT_COLOR_PRESETS, DEFAULT_FOCUS_RING and the CTA defaults) and exampleTheme, a starting point to copy.

