Getting Started
Dark Mode
How to use dark mode features in Metronic React.
Metronic React provides built-in dark mode support using next-themes. For details on the theme provider implementation, see the Providers guide.
Basic Usage
import { useTheme } from 'next-themes';
function DarkModeToggle() {
const { theme, setTheme } = useTheme();
return (
<button
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
>
{theme === 'dark' ? 'Switch to Light' : 'Switch to Dark'}
</button>
);
}
Theme Options
function ThemeSelector() {
const { theme, setTheme } = useTheme();
return (
<select value={theme} onChange={(e) => setTheme(e.target.value)}>
<option value="light">Light</option>
<option value="dark">Dark</option>
<option value="system">System</option>
</select>
);
}
Using resolvedTheme
When working with the system theme, use resolvedTheme
for accurate styling:
function ThemeAwareComponent() {
const { resolvedTheme } = useTheme();
return (
<div className="p-4 rounded-lg shadow-md">
{resolvedTheme === 'dark' ? (
<span className="text-blue-300">Dark mode content</span>
) : (
<span className="text-blue-700">Light mode content</span>
)}
</div>
);
}
TailwindCSS Dark Mode
The simplest way to create dark mode styles is with Tailwind's dark variant:
function DarkModeCard() {
return (
<div className="bg-white dark:bg-gray-800 text-gray-900 dark:text-white p-4 rounded-md shadow-md">
<h2 className="text-xl font-bold text-primary-600 dark:text-primary-400">
Dark Mode Compatible
</h2>
<p className="mt-2 text-gray-600 dark:text-gray-300">
This card adapts to your theme preference automatically.
</p>
<button className="mt-4 bg-primary-500 hover:bg-primary-600 dark:bg-primary-600 dark:hover:bg-primary-700 text-white px-4 py-2 rounded">
Action Button
</button>
</div>
);
}
Handling Images in Dark Mode
Conditionally load appropriate images for the current theme:
function ThemeAwareImage() {
const { resolvedTheme } = useTheme();
return (
<img
src={resolvedTheme === 'dark'
? '/images/logo-dark.svg'
: '/images/logo-light.svg'
}
alt="Logo"
className="h-8 w-auto"
/>
);
}
Preventing Hydration Mismatch
Since theme information isn't available during server rendering, prevent hydration mismatches:
import { useState, useEffect } from 'react';
import { useTheme } from 'next-themes';
function SafeThemeToggle() {
const [mounted, setMounted] = useState(false);
const { theme, setTheme } = useTheme();
// Wait for component to mount to access theme
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
// Return placeholder with same dimensions
return <div className="w-8 h-8" />;
}
return (
<button
className="w-8 h-8 rounded-full flex items-center justify-center"
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
>
{theme === 'dark' ? '☀️' : '🌙'}
</button>
);
}
Dark Mode with CSS Variables
Access theme variables within your components:
function ThemedComponent() {
return (
<div
style={{
backgroundColor: 'var(--background)',
color: 'var(--foreground)',
borderColor: 'var(--border)'
}}
className="p-4 border rounded"
>
<h3 className="font-medium">Using CSS Variables</h3>
<p>This component uses theme CSS variables.</p>
</div>
);
}