React Integration
NightfallProvider, useNightfall hook, and NightfallToggle component — under 3KB total.
Installation
The React integration is included in the main package. No additional install needed:
npm install nightfall-css
# React components are at nightfall-css/reactNightfallProvider
Wrap your app with the provider. It manages theme state, localStorage persistence, and system preference detection:
import { NightfallProvider } from 'nightfall-css/react'
import './nightfall-generated.css'
export default function RootLayout({ children }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<NightfallProvider
defaultTheme="system"
storageKey="nightfall-theme"
attribute="data-theme"
>
{children}
</NightfallProvider>
</body>
</html>
)
}Provider props:
defaultTheme— Initial theme:"light","dark", or"system"(default:"system")storageKey— localStorage key for persistence (default:"nightfall-theme")attribute— HTML attribute set on the root element (default:"data-theme")enableSystem— Whether to respectprefers-color-scheme(default:true)disableTransition— Disable CSS transitions during theme switch to prevent flicker (default:false)
useNightfall Hook
Access theme state and controls from any component:
import { useNightfall } from 'nightfall-css/react'
export function ThemeStatus() {
const {
theme, // 'light' | 'dark' | 'system'
resolvedTheme, // 'light' | 'dark' (actual resolved value)
setTheme, // (theme: string) => void
toggleTheme, // () => void — switches between light and dark
systemTheme, // 'light' | 'dark' — current OS preference
} = useNightfall()
return (
<div>
<p>Setting: {theme}</p>
<p>Resolved: {resolvedTheme}</p>
<p>System prefers: {systemTheme}</p>
<button onClick={() => setTheme('light')}>Light</button>
<button onClick={() => setTheme('dark')}>Dark</button>
<button onClick={() => setTheme('system')}>System</button>
<button onClick={toggleTheme}>Toggle</button>
</div>
)
}NightfallToggle Component
A ready-to-use toggle button with sun/moon icons and smooth transitions:
import { NightfallToggle } from 'nightfall-css/react'
export function Header() {
return (
<header className="flex items-center justify-between p-4">
<h1>My App</h1>
<NightfallToggle
size="md" // 'sm' | 'md' | 'lg'
iconStyle="system" // 'system' | 'emoji' | 'text'
className="custom-toggle-class"
/>
</header>
)
}
// Renders a button that:
// - Shows a sun icon in dark mode (click to switch to light)
// - Shows a moon icon in light mode (click to switch to dark)
// - Animates the icon transition
// - Includes aria-label for accessibilityServer Components (Next.js)
The provider works with React Server Components. Only the provider and toggle are client components — your page content remains a server component:
// This is a Server Component — no 'use client' needed
export default function Page() {
return (
<main>
<h1>Hello from a Server Component</h1>
<p>Theme switching works because the provider is in the layout.</p>
</main>
)
}Avoiding Hydration Mismatch
The provider delays rendering theme-dependent content until after hydration to prevent React hydration mismatches. Add suppressHydrationWarning to your html element and use the FOUC prevention script for seamless loading:
import { nightfallScript } from 'nightfall-css/script'
export default function RootLayout({ children }) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<script dangerouslySetInnerHTML={{ __html: nightfallScript }} />
</head>
<body>
<NightfallProvider>{children}</NightfallProvider>
</body>
</html>
)
}