@metadiv-studio/theme-context
v0.1.0
Published
A lightweight React context provider for managing light/dark theme switching with localStorage persistence and automatic Tailwind CSS dark mode integration.
Downloads
35
Readme
@metadiv-studio/theme-context
A lightweight React context provider for managing light/dark theme switching with localStorage persistence and automatic Tailwind CSS dark mode integration.
🚀 Installation
npm install @metadiv-studio/theme-context📝 Description
This package provides a complete theme management solution for React applications. It includes:
- ThemeProvider: A React context provider that manages theme state
- useThemeContext: A custom hook to access and control theme state
- Automatic persistence: Saves theme preference to localStorage
- Tailwind CSS integration: Automatically applies/removes the
darkclass todocument.documentElement - TypeScript support: Full type safety with TypeScript definitions
The package automatically handles theme persistence across browser sessions and provides a clean API for theme switching in your React components.
🛠️ Setup
1. Wrap your app with ThemeProvider
// pages/_app.tsx (Next.js) or App.tsx (Create React App)
import { ThemeProvider } from '@metadiv-studio/theme-context';
function MyApp({ Component, pageProps }) {
return (
<ThemeProvider>
<Component {...pageProps} />
</ThemeProvider>
);
}
export default MyApp;2. Configure Tailwind CSS for dark mode
Make sure your tailwind.config.js is configured for dark mode:
// tailwind.config.js
module.exports = {
darkMode: 'class', // Enable class-based dark mode
content: [
// ... your content paths
"./node_modules/@metadiv-studio/**/*.{js,ts,jsx,tsx}", // Include this package
],
// ... rest of your config
}📖 Usage
Basic Theme Toggle
import { useThemeContext } from '@metadiv-studio/theme-context';
import { Sun, Moon } from 'lucide-react';
function ThemeToggle() {
const { theme, setTheme } = useThemeContext();
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};
return (
<button
onClick={toggleTheme}
className="p-2 rounded-full bg-gray-200 dark:bg-gray-800"
>
{theme === 'light' ? <Moon className="h-4 w-4" /> : <Sun className="h-4 w-4" />}
</button>
);
}Theme-Aware Component
import { useThemeContext } from '@metadiv-studio/theme-context';
function ThemedCard({ children }) {
const { theme } = useThemeContext();
return (
<div className={`
p-6 rounded-lg border
${theme === 'light'
? 'bg-white border-gray-200 text-gray-900'
: 'bg-gray-800 border-gray-700 text-white'
}
`}>
{children}
</div>
);
}Complete Example with Multiple Components
// App.tsx
import { ThemeProvider, useThemeContext } from '@metadiv-studio/theme-context';
import { Sun, Moon } from 'lucide-react';
function App() {
return (
<ThemeProvider>
<div className="min-h-screen bg-white dark:bg-gray-900 transition-colors">
<Header />
<MainContent />
</div>
</ThemeProvider>
);
}
function Header() {
const { theme, setTheme } = useThemeContext();
return (
<header className="p-4 border-b border-gray-200 dark:border-gray-700">
<div className="flex justify-between items-center">
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">
My App
</h1>
<button
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
className="
p-2 rounded-lg
bg-gray-100 hover:bg-gray-200
dark:bg-gray-800 dark:hover:bg-gray-700
text-gray-900 dark:text-white
transition-colors
"
>
{theme === 'light' ? (
<Moon className="h-5 w-5" />
) : (
<Sun className="h-5 w-5" />
)}
</button>
</div>
</header>
);
}
function MainContent() {
return (
<main className="p-8">
<div className="max-w-4xl mx-auto">
<div className="
p-6 rounded-lg border
bg-gray-50 border-gray-200
dark:bg-gray-800 dark:border-gray-700
">
<h2 className="text-xl font-semibold mb-4 text-gray-900 dark:text-white">
Theme-Aware Content
</h2>
<p className="text-gray-700 dark:text-gray-300">
This content automatically adapts to the current theme.
</p>
</div>
</div>
</main>
);
}
export default App;Theme Selection Menu
import { useThemeContext, ThemeMode } from '@metadiv-studio/theme-context';
function ThemeSelector() {
const { theme, setTheme } = useThemeContext();
const themes: { value: ThemeMode; label: string }[] = [
{ value: 'light', label: 'Light Mode' },
{ value: 'dark', label: 'Dark Mode' },
];
return (
<div className="space-y-2">
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
Choose Theme
</label>
<select
value={theme}
onChange={(e) => setTheme(e.target.value as ThemeMode)}
className="
block w-full px-3 py-2 border border-gray-300 rounded-md
bg-white dark:bg-gray-800
text-gray-900 dark:text-white
dark:border-gray-600
focus:outline-none focus:ring-2 focus:ring-blue-500
"
>
{themes.map(({ value, label }) => (
<option key={value} value={value}>
{label}
</option>
))}
</select>
</div>
);
}🔧 API Reference
ThemeProvider
A React context provider that manages theme state and persistence.
Props:
children: React.ReactNode- The child components to wrap
Features:
- Automatically loads saved theme from localStorage on mount
- Applies/removes
darkclass todocument.documentElement - Defaults to
lighttheme if no saved preference exists
useThemeContext
A custom hook that provides access to the theme context.
Returns:
{
theme: ThemeMode; // Current theme: 'light' | 'dark'
setTheme: (theme: ThemeMode) => void; // Function to change theme
}Example:
const { theme, setTheme } = useThemeContext();
// Get current theme
console.log(theme); // 'light' or 'dark'
// Change theme
setTheme('dark');ThemeMode
TypeScript type definition for theme values.
type ThemeMode = 'light' | 'dark';🎨 Styling Best Practices
Using Tailwind CSS Dark Mode Classes
// Background colors
<div className="bg-white dark:bg-gray-900">
// Text colors
<p className="text-gray-900 dark:text-white">
// Border colors
<div className="border border-gray-200 dark:border-gray-700">
// Hover states
<button className="hover:bg-gray-100 dark:hover:bg-gray-800">
// Transitions for smooth theme switching
<div className="bg-white dark:bg-gray-900 transition-colors duration-200">Creating Theme-Aware Custom CSS
/* globals.css */
.themed-component {
@apply bg-white text-gray-900;
@apply dark:bg-gray-800 dark:text-white;
@apply transition-colors duration-200;
}📚 Dependencies
Peer Dependencies:
react: ^18react-dom: ^18
Internal Dependencies:
@metadiv-studio/context: ^0.2.0- Context creation utilities
🤝 Contributing
This package is part of the MetaDiv Studio UI component library. For contributions and issues, please refer to the main repository.
📄 License
UNLICENSED
Happy theming! 🎨
