Ultra-lightweight, SSR-safe, zero-dependency dark mode and theme manager for React.
- Zero dependencies — only React
- SSR-safe — no hydration flash
- TypeScript — full type definitions
- Scoped themes — multiple providers support
- Professional styles — built-in gradients and glassmorphism
- Accessible — ARIA labels, keyboard navigation
npm install @tavosud/sky-themeFor professional dark mode with gradients and glassmorphism:
import '@tavosud/sky-theme/styles';Or in CSS:
@import '@tavosud/sky-theme/styles';To prevent flash of wrong theme on SSR, add this to your HTML <head>:
<script>
(function(){
try{
var s=localStorage.getItem('sky-theme');
var p=window.matchMedia('(prefers-color-scheme: dark)').matches;
var d=s==='dark'||(s!=='light'&&(s==='system'||!s)&&p);
d?document.documentElement.classList.add('dark'):document.documentElement.classList.remove('dark');
}catch(e){}
})();
</script>Or use the React component (Next.js, Remix, etc.):
import { ThemeScript } from '@tavosud/sky-theme';
// In your layout root
<ThemeScript storageKey="sky-theme" defaultMode="system" />import { ThemeProvider, ThemeButton } from '@tavosud/sky-theme';
export function App() {
return (
<ThemeProvider defaultMode="system">
<Navbar />
<Content />
</ThemeProvider>
);
}import { useTheme } from '@tavosud/sky-theme';
function MyComponent() {
const { resolvedTheme } = useTheme();
return (
<div className="sky-surface">
Current theme: {resolvedTheme}
</div>
);
}Import @tavosud/sky-theme/styles for professional styling:
| Class | Description |
|---|---|
.sky-surface |
Background with gradient |
.sky-glass |
Glassmorphism effect (blur + transparency) |
.sky-card |
Card with shadow and border |
.sky-border |
Adaptive border color |
.sky-text |
Primary text color |
.sky-text-muted |
Secondary text color |
| Prop | Type | Default | Description |
|---|---|---|---|
defaultMode |
'light' | 'dark' | 'system' |
'system' |
Initial mode |
storageKey |
string |
'sky-theme' |
localStorage key |
persist |
boolean |
true |
Persist to localStorage |
scope |
string |
'default' |
Provider scope (for multiple themes) |
classMap |
Record<string, string> |
{ dark: 'dark' } |
Map modes to CSS classes |
onThemeChange |
(theme: string) => void |
- | Callback on change |
transitionClassName |
string |
- | Class added during transitions |
const { mode, resolvedTheme, toggle, setMode } = useTheme();mode— current setting ('light','dark','system', or custom)resolvedTheme— actual theme ('light'or'dark', never'system')toggle()— cycle to next modesetMode(mode)— set specific mode
import { ThemeButton } from '@tavosud/sky-theme';
// With label
<ThemeButton showLabel />
// With custom styles
<ThemeButton style={{ color: 'red' }} />MIT