Cross-framework UI theme switching library
npm install @ui-theme/webWeb framework agnostic UI theme switching library. Built with a framework-agnostic core and React adapter. Additional framework support planned for future releases.
Introducing version 1 of @ui-theme/web, a comprehensive solution for managing UI themes across web applications. This release marks a significant milestone in our journey to provide developers with a robust, flexible, and easy-to-use theming library, that supports all web javascript UI frameworks.
``bash`
npm install @ui-theme/web
`bash`
pnpm add @ui-theme/web
`bash`
yarn add @ui-theme/web
Choose the right provider for your framework:
| Provider | Best For | Key Features |
| ----------------------- | ------------------------------ | ------------------------------------------------ |
| UIThemeProvider | All React apps | Universal provider with full feature set |
| NextUIThemeProvider | Next.js, Remix, SSR frameworks | Pre-hydration script, CSP support, animations |
| TanStackUIThemeProvider | TanStack Start apps | Isomorphic rendering, useHydrated() integration |
| ViteUIThemeProvider | Vite React SPAs | Lightweight, transition control, no SSR overhead |
Basic pattern that works across all providers:
`tsx
import { UIThemeProvider, useUITheme } from '@ui-theme/web/react';
function App() {
return (
);
}
function ThemeToggle() {
const { theme, toggleTheme, ref } = useUITheme();
return (
);
}
`
Framework Setup Guides:
- Next.js / SSR Setup Guide - Complete guide with App Router, Pages Router, CSP support
- TanStack Start Setup Guide - Isomorphic rendering, hydration-safe patterns
- Vite React SPA Setup Guide - Client-side setup, flash prevention, routing
All providers expose the same hook interface:
| Property | Type | Description |
| ---------------------- | ------------------------------------------------------- | ---------------------------------- |
| theme | Theme | Current theme |
| colorTheme | ColorTheme | Current color theme |
| resolvedTheme | 'light' \| 'dark' | Resolved theme (system → actual) |
| systemTheme | 'light' \| 'dark' | OS theme preference |
| ref | RefObject
| setTheme | (theme: Theme) => void | Set theme instantly |
| setColorTheme | (colorTheme: ColorTheme) => void | Set color theme |
| switchTheme | (theme: Theme, animationOff?: boolean) => Promise
| switchColorTheme | (colorTheme: string) => void | Switch color theme with animation |
| toggleTheme | (animationOff?: boolean) => Promise
| toggleLightTheme | (animationOff?: boolean) => Promise
| toggleDarkTheme | (animationOff?: boolean) => Promise
| toggleColorTheme | () => void | Toggle between color themes |
| createColorThemeToggle | (colorTheme: string) => () => void | Create color theme toggle |
| isColorThemeActive | (colorTheme: string) => boolean | Check if color theme active |
| switchThemeFromElement | (theme: Theme, element: HTMLElement) => Promise
| Prop | UITheme | NextUITheme | TanStackUITheme | ViteUITheme | Type | Default |
| ------------------------- | ------- | ----------- | --------------- | ----------- | ------------------ | --------------------------- |
| defaultTheme | ✓ | ✓ | ✓ | ✓ | Theme | 'system' |
| defaultColorTheme | ✓ | ✓ | ✓ | ✓ | ColorTheme | 'default' |
| themes | ✓ | ✓ | ✓ | ✓ | Theme[] | ['light', 'dark', 'system'] |
| colorThemes | ✓ | ✓ | ✓ | ✓ | ColorTheme[] | ['default'] |
| animationType | ✓ | ✓ | ✓ | ✓ | ThemeAnimationType | CIRCLE |
| duration | ✓ | ✓ | ✓ | ✓ | number | 500 |
| storageKey | ✓ | ✓ | ✓ | ✓ | string | varies |
| colorStorageKey | ✓ | ✓ | ✓ | ✓ | string | varies |
| nonce | ✗ | ✓ | ✗ | ✗ | string | - |
| disablePreHydrationScript | ✗ | ✓ | ✗ | ✗ | boolean | false |
| disableTransitionOnChange | ✗ | ✗ | ✗ | ✓ | boolean | false |
| onThemeChange | ✓ | ✓ | ✓ | ✓ | function | - |
| onColorThemeChange | ✓ | ✓ | ✓ | ✓ | function | - |
UIThemeSwitcher: Pre-built theme toggle buttons with animations
UIThemeSelector: Dropdown selector for color themes
See framework-specific guides for component usage examples.
---
CSS Variables Setup
Define theme variables in your global CSS file:
`css
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 221.2 83.2% 53.3%;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--primary: 217.2 91.2% 59.8%;
}
/ Color theme variants /
.theme-blue {
--primary: 221.2 83.2% 53.3%;
}
.theme-blue.dark {
--primary: 217.2 91.2% 59.8%;
}
.theme-green {
--primary: 142.1 76.2% 36.3%;
}
.theme-green.dark {
--primary: 142.1 70.6% 45.3%;
}
`
Browser Support
- View Transitions API: Chrome 111+, Edge 111+
- Fallback: All modern browsers with CSS transitions
- Reduced Motion: Respects prefers-reduced-motion
- Framework Support: React 16.8+ (hooks required)
Advanced Configuration
`tsx
const { switchTheme, toggleTheme } = useUITheme();
// With animation (default)
await switchTheme('dark');
// Without animation
await switchTheme('dark', true);
await toggleTheme(true);
`
`tsx
import { useTheme } from '@ui-theme/web/react';
const { theme, toggleTheme, ref } = useTheme({
animationType: ThemeAnimationType.BLUR_CIRCLE,
duration: 750,
colorThemes: ['default', 'blue', 'green'],
onThemeChange: (theme) => console.log('Theme:', theme),
});
``
- Multiple theme support (light, dark, system)
- Framework-agnostic core
- Persistent theme storage
- SSR/SSG compatible
- Tree-shakeable
- TypeScript support
- Zero dependencies (per framework)
MIT