Skip to Content
Delmare Digital
Guides

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:

app/(frontend)/[[...slug]]/page.tsx
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:

payload.config.ts
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():

components/CustomButton.tsx
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.

Edit this page on GitHub

On this page