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.
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> )}
import { ThemeProvider, useThemeContext } from '@cerberus/react'
function Header() { const { mode } = useThemeContext()
return ( <h1> {mode === 'light' ? 'Hey, friend!' : 'I wear my sunglasses at night.'} </h1> )}
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.
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> )}
'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' | Kexport 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}