useThemeContext

The useThemeContext hook allows you to access or modify the theme and mode properties of the Cerberus Design System in multiple components.

Client Usage

To use the useThemeContext hook, you need to wrap the component using the hook with the Cerberus ThemeProvider component.

nav.tsx
import { ThemeProvider, useThemeContext } from '@cerberus/react'
function Nav() {
const { theme, mode, udpateTheme, updateMode } = useThemeContext()
function handleSetTheme(theme: string) {
updateTheme('party-town')
}
function handleToggleMode() {
updateMode((prev) => (prev === 'light' ? 'dark' : 'light'))
}
return (
<nav>
<button onClick={handleSetTheme} type="button">
update theme to party-town
</button>
<button onClick={handleToggleMode} type="button">
toggle mode
</button>
</nav>
)
}
header.tsx
import { ThemeProvider, useThemeContext } from '@cerberus/react'
function Header() {
const { mode } = useThemeContext()
return (
<h1>
{mode === 'light' ? 'Hey, friend!' : 'I wear my sunglasses at night.'}
</h1>
)
}
layout.tsx
import { ThemeProvider } from '@cerberus/react'
import Header from './header'
import Nav from './nav'
function Layout() {
return (
<ThemeProvider>
<Nav />
<Header />
</ThemeProvider>
)
}

Server Usage

If you are using NextJS, you can utilize cookies to store the theme and mode properties. This way, the user's theme and mode preferences persist between page loads.

app/layout.tsx
import { type PropsWithChildren } from 'react'
import {
ThemeProvider,
type ColorModes,
type DefaultThemes,
} from '@cerberus-design/react'
import { getTheme, injectTheme, type ThemeName } from '@/styled-system/themes'
import { Nav } from './components/Nav'
import { getCookie, setCookie } from './actions/cookies'
import './globals.css'
interface RootProps {}
export default async function RootLayout(props: PropsWithChildren<RootProps>) {
const themeName = (await getCookie('theme')) as ThemeName
const theme = themeName && (await getTheme(themeName))
const colorModeName = (await getCookie('colorMode')) as ColorModes | undefined
const handleUpdateTheme = async (theme: DefaultThemes) => {
'use server'
const newTheme = await getTheme(theme as ThemeName)
setCookie('theme', newTheme)
injectTheme(document.documentElement, newTheme)
}
const handleUpdateMode = async (mode: ColorModes) => {
'use server'
setCookie('colorMode', mode)
}
return (
<html
lang="en"
data-panda-theme={themeName || 'cerberus'}
data-color-mode={colorModeName || 'system'}
>
{themeName && (
<head>
<style
type="text/css"
id={theme.id}
dangerouslySetInnerHTML={{ __html: theme.css }}
/>
</head>
)}
<body>
<ThemeProvider
defaultTheme={themeName || 'cerberus'}
defaultColorMode={colorModeName || 'system'}
updateTheme={handleUpdateTheme}
updateMode={handleUpdateMode}
>
<Nav />
{props.children}
</ThemeProvider>
</body>
</html>
)
}
app/components/Nav.tsx
'use client';
export function Nav() {
const pathname = usePathname()
const { mode, updateMode } = useThemeContext()
const ariaLabel = useMemo(() => {
return mode === 'light' ? 'Switch to dark mode' : 'Switch to light mode'
}, [mode])
const handleUpdateMode = useCallback((e: MouseEvent<HTMLButtonElement>) => {
const currentMode = e.currentTarget.value as ColorModes
const newMode = getColorMode(currentMode)
updateMode(newMode)
}, [])
return (
<nav>
<button
onClick={handleUpdateMode}
value={mode}
aria-label={ariaLabel}
type="button"
value={mode}
>
{mode}
</button>
</nav>
)
})

API

The useThemeContext does not accept any arguments. Instead, everything is passed as props to the ThemeProvider component.

export type DefaultThemes = 'cerberus' | 'acheron'
export type CustomThemes<K extends string = DefaultThemes> = 'cerberus' | K
export type ColorModes = 'light' | 'dark' | 'system'
export interface ThemeContextValue<T extends string = DefaultThemes> {
theme: CustomThemes<T>
mode: ColorModes
updateTheme: (theme: T) => void
updateMode: (mode: ColorModes) => void
}
export interface ThemeProviderProps extends UseThemeOptions {
defaultTheme?: DefaultThemes
defaultColorMode?: ColorModes
}
define function useThemeContext(
defaultTheme: DefaultThemes = 'cerberus',
defaultColorMode: ColorModes = 'light',
): {
theme: DefaultThemes
mode: ColorModes
updateTheme: (theme: DefaultThemes) => void
updateMode: (mode: ColorModes) => void
}

On this page