Customization

Learn how to customize Cerberus to suit your needs.

Cerberus is a highly customizable tool that allows you to define your own rules and configurations. This page will guide you through the process of customizing Cerberus to suit your needs.

Which Option Should I Choose?

  • Use global config when:
  • Create your own design system
  • You need low-level control over your settings
  • Use Cerberus config when:
  • Create app-specific settings
  • You need high-level control over your settings
  • Use component level when:
  • Create one-off component style changes
  • Build your own custom components

Option 1: Global Configuration

Cerberus is built on top of Panda CSS, which allows you to create custom themes and presets. This is the lowest-level way to customize Cerberus.

Step 1: Create a Theme Configuration File

We recommend creating a theme directory and adding a config.ts file to it. This file will contain your custom theme configuration.

theme/config.ts
import { defineTheme } from '@cerberus/panda-preset'
import { semanticTokens } from './semantic-tokens/config'
import { keyframes } from './keyframes'
import { recipes, slotRecipes } from './recipes'
import { textStyles } from './textStyles'
import { tokens } from './tokens'
/**
* This module contains our custom theme to use with Cerberus.
* @module
*/
export const yourCustomTheme = defineTheme({
semanticTokens,
extend: {
keyframes,
recipes,
slotRecipes,
textStyles,
tokens,
},
})

Step 2: Add Your Custom Theme to a preset

Create an entry file in the theme directory that exports your custom theme as a new preset.

theme/index.ts
import { definePreset } from '@pandacss/dev'
import { yourCustomTheme } from './config'
/**
* This module contains our custom preset which registers our custom theme.
* @module
*/
export const yourCustomPreset = definePreset({
// register your custom theme
themes: {
yourCustomThemeName: yourCustomTheme,
},
// opt-into your theme to be used in static css generation
staticCss: {
themes: ['yourCustomThemeName'],
},
})

Step 3: Extend the Cerberus Preset

To use your custom theme, you need to tell Panda it exists.

panda.config.ts
import { defineConfig } from '@pandacss/dev'
import pandaPreset from '@pandacss/preset-panda'
import { cerberusPreset, cerberusConfig } from '@cerberus/panda-preset'
export default defineConfig({
...cerberusConfig,
include: [
'./node_modules/@cerberus/react/src/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx,js,jsx}', // <- Make sure this path is to your project
],
exclude: [],
presets: [pandaPreset, cerberusPreset, yourCustomPreset],
})

Step 4: Use Your Custom Theme

Finally, delcare your theme in your entry file.

app/layout.tsx
import { cx } from '@cerberus/styled-system/css'
import { Poppins, Recursive } from 'next/font/google'
import { type PropsWithChildren } from 'react'
import './globals.css'
const poppins = Poppins({
display: 'swap',
subsets: ['latin'],
weight: ['400', '600', '700'],
variable: '--font-poppins',
})
const recursive = Recursive({
display: 'swap',
subsets: ['latin'],
weight: ['400'],
variable: '--font-recursive',
})
interface RootProps {}
export default async function RootLayout(props: PropsWithChildren<RootProps>) {
return (
<html
lang="en"
data-panda-theme="yourCustomThemeName"
data-color-mode="light"
className={cx(poppins.variable, recursive.variable)}
>
<body>
{props.children}
</body>
</html>
)
}

Option 2: Cerberus Configuration

This is an easier way to customize Cerberus. You just create a client abstracted file to define your Cerberus configuration to export as a component.

Step 1: Create a Configuration File

Create a client file in your project and define your Cerberus configuration.

context/cerberus-config.tsx
'use client'
import {
CerberusProvider,
defineIcons,
makeSystemConfig,
} from '@cerberus-design/react'
import {
Calendar,
Checkmark,
CheckmarkOutline,
ChevronDown,
ChevronLeft,
ChevronRight,
Close,
CloudUpload,
Information,
Restart,
TrashCan,
UserFilled,
Warning,
WarningAlt,
WarningFilled,
} from '@carbon/icons-react'
import type { PropsWithChildren } from 'react'
/**
* This module provides a Cerberus configuration component which has to be used
* in a client abstraction because of R19 rules around data passing into props.
*/
const icons = defineIcons({
accordionIndicator: ChevronDown,
avatar: UserFilled,
calendar: Calendar,
calendarPrev: ChevronLeft,
calendarNext: ChevronRight,
close: Close,
confirmModal: Information,
delete: TrashCan,
promptModal: Information,
waitingFileUploader: CloudUpload,
infoNotification: Information,
successNotification: CheckmarkOutline,
warningNotification: WarningAlt,
dangerNotification: WarningFilled,
invalid: WarningFilled,
invalidAlt: Warning,
redo: Restart,
selectArrow: ChevronDown,
selectChecked: Checkmark,
toggleChecked: Checkmark,
})
const config = makeSystemConfig({
icons,
})
export default function CerberusConfig(props: PropsWithChildren<{}>) {
return <CerberusProvider config={config}>{props.children}</CerberusProvider>
}

Step 2: Use Your Configuration

Finally, use your configuration in your entry file.

app/layout.tsx
import { Poppins, Recursive } from 'next/font/google'
import { type PropsWithChildren } from 'react'
import { css, cx } from '@cerberus/styled-system/css'
import CerberusConfig from '@/context/cerberus-config'
import './globals.css'
const poppins = Poppins({
display: 'swap',
subsets: ['latin'],
weight: ['400', '600', '700'],
variable: '--font-poppins',
})
const recursive = Recursive({
display: 'swap',
subsets: ['latin'],
weight: ['400'],
variable: '--font-recursive',
})
interface RootProps {}
export default async function RootLayout(props: PropsWithChildren<RootProps>) {
return (
<html
className={cx(poppins.variable, recursive.variable)}
lang="en"
>
<body>
<CerberusConfig>
{props.children}
</CerberusConfig>
</body>
</html>
)
}

Option 3: Component-Specific Configuration

This is the easiest way to customize Cerberus. You simply just add custom styles to a component in Cerberus.

Customizing a Button
import { Button, type ButtonProps } from '@cerberus/react'
import { css } from '@cerberus/styled-system'
export function CustomButton(props: ButtonProps) {
return (
<Button
{...props}
className={css({
backgroundColor: 'red',
color: 'white',
borderRadius: '8px',
})}
/>
)
}

Customizing Icons

Some components in Cerberus use icons. You can customize these icons by providing your own icon components.

In your entry file, call defineIcons with an object that maps icon names to icon components.

The following code replaces all instances of the invalid icon with a custom Lucide icon.

app/layout.tsx
import { defineIcons } from '@cerberus/react'
import { cx } from '@cerberus/styled-system/css'
import { Poppins, Recursive } from 'next/font/google'
import { type PropsWithChildren } from 'react'
import { CircleAlert } from 'lucide-react';
import './globals.css'
const poppins = Poppins({
display: 'swap',
subsets: ['latin'],
weight: ['400', '600', '700'],
variable: '--font-poppins',
})
const recursive = Recursive({
display: 'swap',
subsets: ['latin'],
weight: ['400'],
variable: '--font-recursive',
})
defineIcons({
invalid: CircleAlert,
})
interface RootProps {}
export default async function RootLayout(props: PropsWithChildren<RootProps>) {
return (
<html
className={cx(poppins.variable, recursive.variable)}
lang="en"
data-panda-theme="cerberus"
data-color-mode="light"
>
<body>
{props.children}
</body>
</html>
)
}

API

The defineIcons function takes an object that maps icon names to icon components.

export type IconType = CarbonIconType | ElementType
export interface DefinedIcons {
avatar?: IconType
checkbox?: IconType
close?: IconType
confirmModal?: IconType
delete?: IconType
promptModal?: IconType
fileUploader?: IconType
indeterminate?: IconType
infoNotification?: IconType
successNotification?: IconType
warningNotification?: IconType
dangerNotification?: IconType
invalid: IconType
invalidAlt?: IconType
redo?: IconType
selectArrow?: IconType
toggleChecked?: IconType
}

On this page