@space-man/react-theme-animation 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -432
- package/dist/cjs/components/NextThemeProvider.d.ts +81 -0
- package/dist/cjs/components/NextThemeProvider.js +223 -0
- package/dist/cjs/components/TanStackThemeProvider.d.ts +68 -0
- package/dist/cjs/components/TanStackThemeProvider.js +183 -0
- package/dist/cjs/components/ViteThemeProvider.d.ts +27 -4
- package/dist/cjs/components/ViteThemeProvider.js +31 -8
- package/dist/cjs/hooks/use-theme-animation.js +8 -8
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.js +8 -1
- package/dist/cjs/types/index.d.ts +4 -4
- package/dist/esm/components/NextThemeProvider.d.ts +81 -0
- package/dist/esm/components/NextThemeProvider.js +185 -0
- package/dist/esm/components/TanStackThemeProvider.d.ts +68 -0
- package/dist/esm/components/TanStackThemeProvider.js +178 -0
- package/dist/esm/components/ViteThemeProvider.d.ts +27 -4
- package/dist/esm/components/ViteThemeProvider.js +31 -8
- package/dist/esm/hooks/use-theme-animation.js +8 -8
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/types/index.d.ts +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,82 +4,29 @@ https://github.com/user-attachments/assets/2819cf70-c474-478e-b821-6b26457c8d4a
|
|
|
4
4
|
|
|
5
5
|
React theme switching with smooth view transition animations, multi-theme support, and synchronized state management.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## What's New in v2.1
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
- Functions to toggle light and dark themes directly
|
|
15
|
-
|
|
16
|
-
```tsx
|
|
17
|
-
import { useThemeAnimation } from '@space-man/react-theme-animation'
|
|
18
|
-
|
|
19
|
-
function ColorThemeDemo() {
|
|
20
|
-
const { createColorThemeToggle, isColorThemeActive, toggleDarkTheme, toggleLightTheme } =
|
|
21
|
-
useThemeAnimation({
|
|
22
|
-
colorThemes: ['supabase'],
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<>
|
|
27
|
-
<button onClick={createColorThemeToggle('supabase')} className="theme-toggle-btn">
|
|
28
|
-
Supabase Theme {isColorThemeActive('supabase') ? '✅' : '❌'}
|
|
29
|
-
</button>
|
|
30
|
-
<button ref={ref} onClick={toggleDarkTheme} className="theme-toggle-btn">
|
|
31
|
-
Dark Theme
|
|
32
|
-
</button>
|
|
33
|
-
<button ref={ref} onClick={toggleLightTheme} className="theme-toggle-btn">
|
|
34
|
-
Light Theme
|
|
35
|
-
</button>
|
|
36
|
-
</>
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Vite Theme Provider Example
|
|
41
|
-
function App() {
|
|
42
|
-
return (
|
|
43
|
-
<ViteThemeProvider
|
|
44
|
-
themes={['light', 'dark', 'system']}
|
|
45
|
-
colorThemes={['default', 'supabase']}
|
|
46
|
-
defaultTheme="system"
|
|
47
|
-
defaultColorTheme="default"
|
|
48
|
-
>
|
|
49
|
-
<ThemeToggle />
|
|
50
|
-
</ViteThemeProvider>
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function ThemeToggle() {
|
|
55
|
-
const { createColorThemeToggle, isColorThemeActive } = useViteTheme()
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<button onClick={createColorThemeToggle('supabase')} className="theme-toggle-btn">
|
|
59
|
-
Supabase Theme {isColorThemeActive('supabase') ? '✅' : '❌'}
|
|
60
|
-
</button>
|
|
61
|
-
)
|
|
62
|
-
}
|
|
63
|
-
```
|
|
9
|
+
- **animationOff Parameter**: Instantly switch themes without animation via optional parameter on all toggle functions
|
|
10
|
+
- **Universal SSR Support**: Pre-hydration script prevents flash in Next.js, Remix, and SSR frameworks
|
|
11
|
+
- **Three Framework-Specific Providers**: NextThemeProvider (SSR/Next.js), TanStackThemeProvider (TanStack Start), ViteThemeProvider (Vite SPAs)
|
|
12
|
+
- **Consistent Hook API**: All providers expose identical hook interface with 15+ methods
|
|
13
|
+
- **Enhanced Theme Control**: Direct functions for toggleLightTheme(), toggleDarkTheme(), createColorThemeToggle()
|
|
64
14
|
|
|
65
15
|
## Live Demo
|
|
66
16
|
|
|
67
|
-
[Live Demo
|
|
17
|
+
[View Live Demo](https://spaceman-rta-vite.netlify.app/)
|
|
68
18
|
|
|
69
19
|
## Features
|
|
70
20
|
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
- **TypeScript**: Full TypeScript support with comprehensive types
|
|
81
|
-
- **Customizable**: Extensive configuration options
|
|
82
|
-
- **Backward Compatible**: Works with existing implementations
|
|
21
|
+
- Smooth view transition animations with customizable origins
|
|
22
|
+
- Multi-theme support (light, dark, system)
|
|
23
|
+
- Color theme variants (brand colors, custom themes)
|
|
24
|
+
- Three framework-optimized providers
|
|
25
|
+
- Powerful useThemeAnimation hook for custom implementations
|
|
26
|
+
- Ready-to-use ThemeSwitcher and ThemeSelector components
|
|
27
|
+
- State synchronization across components
|
|
28
|
+
- Full TypeScript support
|
|
29
|
+
- Performance optimized with reduced motion support
|
|
83
30
|
|
|
84
31
|
## Installation
|
|
85
32
|
|
|
@@ -87,435 +34,184 @@ function ThemeToggle() {
|
|
|
87
34
|
npm install @space-man/react-theme-animation
|
|
88
35
|
```
|
|
89
36
|
|
|
90
|
-
##
|
|
91
|
-
|
|
92
|
-
This library supports multiple usage patterns:
|
|
93
|
-
|
|
94
|
-
1. **Hook-Only Usage**: Direct hook usage for custom implementations
|
|
95
|
-
2. **Provider Pattern**: Centralized state management (recommended)
|
|
96
|
-
3. **ViteThemeProvider**: Specialized provider for Vite React SPAs
|
|
97
|
-
|
|
98
|
-
**[See the complete Getting Started Guide](./getting-started.md)** for detailed examples, advanced configurations, and best practices.
|
|
99
|
-
|
|
100
|
-
**[View the Next.js Code Example](./example/)** to see this package in action with a complete implementation of both hook and provider pattern.
|
|
101
|
-
|
|
102
|
-
**[View the Vite React SPA Demo](https://github.com/tonyedgal/spaceman-rta-framework-guides/tree/main/example-vite)** for a complete Vite implementation using ViteThemeProvider.
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
## 1. Hook-Only Usage For Light and Dark mode animation
|
|
107
|
-
|
|
108
|
-
Perfect for custom theme toggle buttons and complete control over animated theme logic.
|
|
109
|
-
|
|
110
|
-
### Basic Theme Toggle
|
|
111
|
-
|
|
112
|
-
```tsx
|
|
113
|
-
import { useThemeAnimation } from '@space-man/react-theme-animation'
|
|
114
|
-
|
|
115
|
-
function ThemeToggle() {
|
|
116
|
-
const { theme, toggleTheme, ref } = useThemeAnimation()
|
|
117
|
-
|
|
118
|
-
return (
|
|
119
|
-
<button ref={ref} onClick={toggleTheme} className="theme-toggle-btn">
|
|
120
|
-
{theme === 'light' ? '🌙' : '🌞'} {theme}
|
|
121
|
-
</button>
|
|
122
|
-
)
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
## 2. Provider Pattern (Recommended)
|
|
129
|
-
|
|
130
|
-
The most powerful pattern using `SpacemanThemeProvider` for centralized theme state management. This prevents state drift and provides synchronized animations.
|
|
131
|
-
|
|
132
|
-
### Basic Provider Setup
|
|
37
|
+
## Provider Selection
|
|
133
38
|
|
|
134
|
-
|
|
135
|
-
import {
|
|
136
|
-
SpacemanThemeProvider,
|
|
137
|
-
ThemeSwitcher,
|
|
138
|
-
ThemeSelector,
|
|
139
|
-
} from '@space-man/react-theme-animation'
|
|
140
|
-
|
|
141
|
-
function App() {
|
|
142
|
-
return (
|
|
143
|
-
<SpacemanThemeProvider>
|
|
144
|
-
<div className="app">
|
|
145
|
-
<header>
|
|
146
|
-
<ThemeSwitcher />
|
|
147
|
-
</header>
|
|
148
|
-
|
|
149
|
-
<aside>
|
|
150
|
-
<ThemeSelector colorThemes={['default', 'supabase', 'mono']} />
|
|
151
|
-
</aside>
|
|
152
|
-
|
|
153
|
-
<main>
|
|
154
|
-
<YourAppContent />
|
|
155
|
-
</main>
|
|
156
|
-
</div>
|
|
157
|
-
</SpacemanThemeProvider>
|
|
158
|
-
)
|
|
159
|
-
}
|
|
160
|
-
```
|
|
39
|
+
Choose the right provider for your framework:
|
|
161
40
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
41
|
+
| Provider | Best For | Key Features |
|
|
42
|
+
| --------------------- | ------------------------------ | ------------------------------------------------ |
|
|
43
|
+
| NextThemeProvider | Next.js, Remix, SSR frameworks | Pre-hydration script, CSP support, animations |
|
|
44
|
+
| TanStackThemeProvider | TanStack Start apps | Isomorphic rendering, useHydrated() integration |
|
|
45
|
+
| ViteThemeProvider | Vite React SPAs | Lightweight, transition control, no SSR overhead |
|
|
165
46
|
|
|
166
|
-
|
|
47
|
+
## Quick Start
|
|
167
48
|
|
|
168
|
-
|
|
49
|
+
Basic pattern that works across all providers:
|
|
169
50
|
|
|
170
51
|
```tsx
|
|
171
|
-
import {
|
|
52
|
+
import { SpacemanThemeProvider, useSpacemanTheme } from '@space-man/react-theme-animation'
|
|
172
53
|
|
|
173
54
|
function App() {
|
|
174
55
|
return (
|
|
175
|
-
<
|
|
176
|
-
<
|
|
177
|
-
<header>
|
|
178
|
-
<ThemeToggle />
|
|
179
|
-
</header>
|
|
180
|
-
<main>
|
|
181
|
-
<ThemeSection />
|
|
182
|
-
</main>
|
|
183
|
-
</div>
|
|
184
|
-
</ViteThemeProvider>
|
|
185
|
-
)
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function ThemeSection() {
|
|
189
|
-
return (
|
|
190
|
-
<SpacemanThemeProvider>
|
|
191
|
-
<div className="app">
|
|
192
|
-
<header>
|
|
193
|
-
<ThemeSwitcher />
|
|
194
|
-
</header>
|
|
195
|
-
|
|
196
|
-
<aside>
|
|
197
|
-
<ThemeSelector colorThemes={['default', 'supabase', 'mono']} />
|
|
198
|
-
</aside>
|
|
199
|
-
|
|
200
|
-
<main>
|
|
201
|
-
<YourAppContent />
|
|
202
|
-
</main>
|
|
203
|
-
</div>
|
|
56
|
+
<SpacemanThemeProvider defaultTheme="system" defaultColorTheme="default">
|
|
57
|
+
<YourApp />
|
|
204
58
|
</SpacemanThemeProvider>
|
|
205
59
|
)
|
|
206
60
|
}
|
|
207
61
|
|
|
208
62
|
function ThemeToggle() {
|
|
209
|
-
const { theme,
|
|
63
|
+
const { theme, toggleTheme, ref } = useSpacemanTheme()
|
|
210
64
|
|
|
211
65
|
return (
|
|
212
|
-
<button onClick={() =>
|
|
213
|
-
{
|
|
66
|
+
<button ref={ref} onClick={() => toggleTheme()}>
|
|
67
|
+
{theme === 'light' ? 'Dark' : 'Light'}
|
|
214
68
|
</button>
|
|
215
69
|
)
|
|
216
70
|
}
|
|
217
71
|
```
|
|
218
72
|
|
|
219
|
-
|
|
73
|
+
**Choose your framework setup guide:**
|
|
220
74
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
75
|
+
- **[Next.js / SSR Setup Guide](./docs/nextjs-setup.md)** - Complete guide with App Router, Pages Router, CSP support
|
|
76
|
+
- **[TanStack Start Setup Guide](./docs/tanstack-start-setup.md)** - Isomorphic rendering, hydration-safe patterns
|
|
77
|
+
- **[Vite React SPA Setup Guide](./docs/vite-setup.md)** - Client-side setup, flash prevention, routing
|
|
78
|
+
|
|
79
|
+
**[View Complete Examples](./example/)** - Next.js implementation with both hook and provider patterns
|
|
80
|
+
|
|
81
|
+
## API Reference
|
|
82
|
+
|
|
83
|
+
### Shared Hook Return (All Providers)
|
|
84
|
+
|
|
85
|
+
All providers expose the same hook interface:
|
|
86
|
+
|
|
87
|
+
| Property | Type | Description |
|
|
88
|
+
| ---------------------- | ------------------------------------------------------- | ---------------------------------- |
|
|
89
|
+
| theme | Theme | Current theme |
|
|
90
|
+
| colorTheme | ColorTheme | Current color theme |
|
|
91
|
+
| resolvedTheme | 'light' \| 'dark' | Resolved theme (system → actual) |
|
|
92
|
+
| systemTheme | 'light' \| 'dark' | OS theme preference |
|
|
93
|
+
| ref | RefObject<HTMLElement> | Ref for animation origin |
|
|
94
|
+
| setTheme | (theme: Theme) => void | Set theme instantly |
|
|
95
|
+
| setColorTheme | (colorTheme: ColorTheme) => void | Set color theme |
|
|
96
|
+
| switchTheme | (theme: Theme, animationOff?: boolean) => Promise<void> | Switch with animation |
|
|
97
|
+
| switchColorTheme | (colorTheme: string) => void | Switch color theme with animation |
|
|
98
|
+
| toggleTheme | (animationOff?: boolean) => Promise<void> | Toggle light/dark |
|
|
99
|
+
| toggleLightTheme | (animationOff?: boolean) => Promise<void> | Toggle to light |
|
|
100
|
+
| toggleDarkTheme | (animationOff?: boolean) => Promise<void> | Toggle to dark |
|
|
101
|
+
| toggleColorTheme | () => void | Toggle between color themes |
|
|
102
|
+
| createColorThemeToggle | (colorTheme: string) => () => void | Create color theme toggle |
|
|
103
|
+
| isColorThemeActive | (colorTheme: string) => boolean | Check if color theme active |
|
|
104
|
+
| switchThemeFromElement | (theme: Theme, element: HTMLElement) => Promise<void> | Switch with animation from element |
|
|
105
|
+
|
|
106
|
+
### Provider Props
|
|
107
|
+
|
|
108
|
+
| Prop | Spaceman | NextTheme | TanStack | Vite | Type | Default |
|
|
109
|
+
| ------------------------- | -------- | --------- | -------- | ---- | ------------------ | --------------------------- |
|
|
110
|
+
| defaultTheme | ✓ | ✓ | ✓ | ✓ | Theme | 'system' |
|
|
111
|
+
| defaultColorTheme | ✓ | ✓ | ✓ | ✓ | ColorTheme | 'default' |
|
|
112
|
+
| themes | ✓ | ✓ | ✓ | ✓ | Theme[] | ['light', 'dark', 'system'] |
|
|
113
|
+
| colorThemes | ✓ | ✓ | ✓ | ✓ | ColorTheme[] | ['default'] |
|
|
114
|
+
| animationType | ✓ | ✓ | ✓ | ✓ | ThemeAnimationType | CIRCLE |
|
|
115
|
+
| duration | ✓ | ✓ | ✓ | ✓ | number | 500 |
|
|
116
|
+
| storageKey | ✓ | ✓ | ✓ | ✓ | string | varies |
|
|
117
|
+
| colorStorageKey | ✓ | ✓ | ✓ | ✓ | string | varies |
|
|
118
|
+
| nonce | ✗ | ✓ | ✗ | ✗ | string | - |
|
|
119
|
+
| disablePreHydrationScript | ✗ | ✓ | ✗ | ✗ | boolean | false |
|
|
120
|
+
| disableTransitionOnChange | ✗ | ✗ | ✗ | ✓ | boolean | false |
|
|
121
|
+
| onThemeChange | ✓ | ✓ | ✓ | ✓ | function | - |
|
|
122
|
+
| onColorThemeChange | ✓ | ✓ | ✓ | ✓ | function | - |
|
|
123
|
+
|
|
124
|
+
### Components
|
|
125
|
+
|
|
126
|
+
**ThemeSwitcher**: Pre-built theme toggle buttons with animations
|
|
127
|
+
**ThemeSelector**: Dropdown selector for color themes
|
|
128
|
+
|
|
129
|
+
See framework-specific guides for component usage examples.
|
|
229
130
|
|
|
230
131
|
---
|
|
231
132
|
|
|
232
|
-
|
|
133
|
+
<details>
|
|
134
|
+
<summary>CSS Variables Setup</summary>
|
|
233
135
|
|
|
234
|
-
|
|
136
|
+
Define theme variables in your global CSS file:
|
|
235
137
|
|
|
236
138
|
```css
|
|
237
|
-
/* Base theme variables */
|
|
238
139
|
:root {
|
|
239
140
|
--background: 0 0% 100%;
|
|
240
141
|
--foreground: 222.2 84% 4.9%;
|
|
142
|
+
--primary: 221.2 83.2% 53.3%;
|
|
241
143
|
}
|
|
242
144
|
|
|
243
|
-
/* Dark theme */
|
|
244
145
|
.dark {
|
|
245
146
|
--background: 222.2 84% 4.9%;
|
|
246
147
|
--foreground: 210 40% 98%;
|
|
148
|
+
--primary: 217.2 91.2% 59.8%;
|
|
247
149
|
}
|
|
248
150
|
|
|
249
|
-
/*
|
|
250
|
-
|
|
251
|
-
.
|
|
252
|
-
--background: oklch(0.9911 0 0);
|
|
253
|
-
--foreground: oklch(0.2046 0 0);
|
|
151
|
+
/* Color theme variants */
|
|
152
|
+
.theme-blue {
|
|
153
|
+
--primary: 221.2 83.2% 53.3%;
|
|
254
154
|
}
|
|
255
155
|
|
|
256
|
-
.theme-
|
|
257
|
-
--
|
|
258
|
-
--foreground: oklch(0.9288 0.0126 255.5078);
|
|
156
|
+
.theme-blue.dark {
|
|
157
|
+
--primary: 217.2 91.2% 59.8%;
|
|
259
158
|
}
|
|
260
159
|
|
|
261
|
-
.theme-
|
|
262
|
-
--
|
|
263
|
-
--foreground: oklch(0.1448 0 0);
|
|
160
|
+
.theme-green {
|
|
161
|
+
--primary: 142.1 76.2% 36.3%;
|
|
264
162
|
}
|
|
265
163
|
|
|
266
|
-
.theme-
|
|
267
|
-
--
|
|
268
|
-
--foreground: oklch(1 0 0);
|
|
164
|
+
.theme-green.dark {
|
|
165
|
+
--primary: 142.1 70.6% 45.3%;
|
|
269
166
|
}
|
|
270
167
|
```
|
|
271
168
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
## API Reference
|
|
275
|
-
|
|
276
|
-
### SpacemanThemeProvider
|
|
277
|
-
|
|
278
|
-
Context provider for centralized theme state management for the ThemeSelector and ThemeSwitcher components. The SpacemanThemeProvider allows you to manage themes and color themes in your application with smooth animations and synchronized state and provide a state reference for the ThemeSelector and ThemeSwitcher components.
|
|
279
|
-
|
|
280
|
-
```tsx
|
|
281
|
-
<SpacemanThemeProvider
|
|
282
|
-
defaultTheme="system"
|
|
283
|
-
defaultColorTheme="blue"
|
|
284
|
-
themes={['light', 'dark', 'system']}
|
|
285
|
-
colorThemes={['default', 'blue', 'green', 'purple']}
|
|
286
|
-
animationType={ThemeAnimationType.CIRCLE}
|
|
287
|
-
duration={800}
|
|
288
|
-
onThemeChange={theme => console.log('Theme:', theme)}
|
|
289
|
-
onColorThemeChange={colorTheme => console.log('Color:', colorTheme)}
|
|
290
|
-
>
|
|
291
|
-
{children}
|
|
292
|
-
</SpacemanThemeProvider>
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
#### SpacemanThemeProvider Props
|
|
169
|
+
</details>
|
|
296
170
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
| `defaultTheme` | `Theme` | `'system'` | Initial theme |
|
|
300
|
-
| `defaultColorTheme` | `ColorTheme` | `'default'` | Initial color theme |
|
|
301
|
-
| `themes` | `Theme[]` | `['light', 'dark', 'system']` | Available themes |
|
|
302
|
-
| `colorThemes` | `ColorTheme[]` | `['default']` | Available color themes |
|
|
303
|
-
| `animationType` | `ThemeAnimationType` | `ThemeAnimationType.CIRCLE` | Animation type |
|
|
304
|
-
| `duration` | `number` | `500` | Animation duration in ms |
|
|
305
|
-
| `blurAmount` | `number` | `2` | Blur amount for blur-circle animation |
|
|
306
|
-
| `onThemeChange` | `(theme: Theme) => void` | - | Global theme change callback |
|
|
307
|
-
| `onColorThemeChange` | `(colorTheme: ColorTheme) => void` | - | Global color theme change callback |
|
|
308
|
-
|
|
309
|
-
### useSpacemanTheme
|
|
310
|
-
|
|
311
|
-
Hook to access theme state from SpacemanThemeProvider context.
|
|
312
|
-
|
|
313
|
-
```tsx
|
|
314
|
-
const { theme, colorTheme, switchTheme, setColorTheme, switchThemeFromElement, ref } =
|
|
315
|
-
useSpacemanTheme()
|
|
316
|
-
```
|
|
171
|
+
<details>
|
|
172
|
+
<summary>Browser Support</summary>
|
|
317
173
|
|
|
318
|
-
|
|
174
|
+
- View Transitions API: Chrome 111+, Edge 111+
|
|
175
|
+
- Fallback: All modern browsers with CSS transitions
|
|
176
|
+
- Reduced Motion: Respects prefers-reduced-motion
|
|
177
|
+
- Framework Support: React 16.8+ (hooks required)
|
|
319
178
|
|
|
320
|
-
|
|
321
|
-
| ------------------------ | ------------------------------------------------------- | ------------------------------------------------- |
|
|
322
|
-
| `theme` | `Theme` | Current theme |
|
|
323
|
-
| `colorTheme` | `ColorTheme` | Current color theme |
|
|
324
|
-
| `switchTheme` | `(theme: Theme) => Promise<void>` | Switch to specific theme |
|
|
325
|
-
| `setColorTheme` | `(colorTheme: ColorTheme) => void` | Set color theme |
|
|
326
|
-
| `switchThemeFromElement` | `(theme: Theme, element: HTMLElement) => Promise<void>` | Switch theme with animation from specific element |
|
|
327
|
-
| `ref` | `RefObject<HTMLElement>` | Ref for animation origin |
|
|
179
|
+
</details>
|
|
328
180
|
|
|
329
|
-
|
|
181
|
+
<details>
|
|
182
|
+
<summary>Advanced Configuration</summary>
|
|
330
183
|
|
|
331
|
-
|
|
184
|
+
### Animation Control
|
|
332
185
|
|
|
333
186
|
```tsx
|
|
334
|
-
const {
|
|
335
|
-
themes: ['light', 'dark', 'system'],
|
|
336
|
-
colorThemes: ['default', 'blue', 'green', 'purple'],
|
|
337
|
-
animationType: ThemeAnimationType.SLIDE,
|
|
338
|
-
duration: 800,
|
|
339
|
-
onThemeChange: theme => console.log('Theme changed:', theme),
|
|
340
|
-
onColorThemeChange: colorTheme => console.log('Color changed:', colorTheme),
|
|
341
|
-
})
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
#### Options
|
|
345
|
-
|
|
346
|
-
| Property | Type | Default | Description |
|
|
347
|
-
| -------------------- | ---------------------------------- | ----------------------------- | --------------------------------------------------- |
|
|
348
|
-
| `themes` | `Theme[]` | `['light', 'dark', 'system']` | Available themes |
|
|
349
|
-
| `colorThemes` | `ColorTheme[]` | `['default']` | Available color themes |
|
|
350
|
-
| `theme` | `Theme` | `'system'` | Initial theme |
|
|
351
|
-
| `colorTheme` | `ColorTheme` | `'default'` | Initial color theme |
|
|
352
|
-
| `animationType` | `ThemeAnimationType` | `ThemeAnimationType.CIRCLE` | Animation type. Options: CIRCLE, BLUR_CIRCLE, SLIDE |
|
|
353
|
-
| `duration` | `number` | `500` | Animation duration in ms |
|
|
354
|
-
| `blurAmount` | `number` | `2` | Blur amount for blur-circle animation |
|
|
355
|
-
| `onThemeChange` | `(theme: Theme) => void` | - | Theme change callback |
|
|
356
|
-
| `onColorThemeChange` | `(colorTheme: ColorTheme) => void` | - | Color theme change callback |
|
|
357
|
-
| `slideDirection` | `SlideDirection` | `left` | Animation slide direction |
|
|
358
|
-
|
|
359
|
-
#### Return
|
|
360
|
-
|
|
361
|
-
| Property | Type | Description |
|
|
362
|
-
| --------------- | ---------------------------------- | ------------------------- |
|
|
363
|
-
| `theme` | `Theme` | Current theme |
|
|
364
|
-
| `colorTheme` | `ColorTheme` | Current color theme |
|
|
365
|
-
| `switchTheme` | `(theme: Theme) => Promise<void>` | Switch to specific theme |
|
|
366
|
-
| `setColorTheme` | `(colorTheme: ColorTheme) => void` | Set color theme |
|
|
367
|
-
| `toggleTheme` | `() => Promise<void>` | Toggle between light/dark |
|
|
368
|
-
| `ref` | `RefObject<HTMLElement>` | Ref for animation origin |
|
|
369
|
-
|
|
370
|
-
### ThemeSwitcher
|
|
187
|
+
const { switchTheme, toggleTheme } = useSpacemanTheme()
|
|
371
188
|
|
|
372
|
-
|
|
189
|
+
// With animation (default)
|
|
190
|
+
await switchTheme('dark')
|
|
373
191
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
currentTheme="light"
|
|
378
|
-
onThemeChange={theme => console.log(theme)}
|
|
379
|
-
animationType={ThemeAnimationType.CIRCLE}
|
|
380
|
-
duration={600}
|
|
381
|
-
className="custom-class"
|
|
382
|
-
/>
|
|
192
|
+
// Without animation
|
|
193
|
+
await switchTheme('dark', true)
|
|
194
|
+
await toggleTheme(true)
|
|
383
195
|
```
|
|
384
196
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
| Property | Type | Default | Description |
|
|
388
|
-
| --------------- | ------------------------ | ----------------------------- | ----------------------------------- |
|
|
389
|
-
| `themes` | `Theme[]` | `['light', 'dark', 'system']` | Available themes |
|
|
390
|
-
| `currentTheme` | `Theme` | - | Controlled current theme (optional) |
|
|
391
|
-
| `onThemeChange` | `(theme: Theme) => void` | - | Theme change callback (optional) |
|
|
392
|
-
| `animationType` | `ThemeAnimationType` | `ThemeAnimationType.CIRCLE` | Animation type |
|
|
393
|
-
| `duration` | `number` | `500` | Animation duration in ms |
|
|
394
|
-
| `className` | `string` | - | Additional CSS classes |
|
|
395
|
-
|
|
396
|
-
> **Note**: When used with `SpacemanThemeProvider`, `currentTheme` and `onThemeChange` are automatically handled by the context.
|
|
397
|
-
|
|
398
|
-
### ThemeSelector
|
|
399
|
-
|
|
400
|
-
Dropdown selector for color themes.
|
|
197
|
+
### Custom Hook Usage
|
|
401
198
|
|
|
402
199
|
```tsx
|
|
403
|
-
|
|
404
|
-
colorThemes={['default', 'blue', 'green', 'purple']}
|
|
405
|
-
currentColorTheme="blue"
|
|
406
|
-
onColorThemeChange={colorTheme => console.log(colorTheme)}
|
|
407
|
-
animationType={ThemeAnimationType.BLUR_CIRCLE}
|
|
408
|
-
duration={400}
|
|
409
|
-
/>
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
#### ThemeSelector Props
|
|
413
|
-
|
|
414
|
-
| Property | Type | Default | Description |
|
|
415
|
-
| -------------------- | ---------------------------------- | ----------------------------- | ----------------------------------------- |
|
|
416
|
-
| `themes` | `Theme[]` | `['light', 'dark', 'system']` | Available themes (for standalone hook) |
|
|
417
|
-
| `colorThemes` | `ColorTheme[]` | `['default']` | Available color themes |
|
|
418
|
-
| `currentColorTheme` | `ColorTheme` | - | Controlled current color theme (optional) |
|
|
419
|
-
| `onColorThemeChange` | `(colorTheme: ColorTheme) => void` | - | Color theme change callback (optional) |
|
|
420
|
-
| `animationType` | `ThemeAnimationType` | `ThemeAnimationType.CIRCLE` | Animation type |
|
|
421
|
-
| `duration` | `number` | `500` | Animation duration in ms |
|
|
422
|
-
|
|
423
|
-
> **Note**: When used with `SpacemanThemeProvider`, `currentColorTheme` and `onColorThemeChange` are automatically handled by the context.
|
|
424
|
-
|
|
425
|
-
### ThemeAnimationType
|
|
426
|
-
|
|
427
|
-
Animation types for theme transitions.
|
|
428
|
-
|
|
429
|
-
```tsx
|
|
430
|
-
enum ThemeAnimationType {
|
|
431
|
-
CIRCLE = 'circle',
|
|
432
|
-
BLUR_CIRCLE = 'blur-circle',
|
|
433
|
-
}
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
### Types
|
|
437
|
-
|
|
438
|
-
```tsx
|
|
439
|
-
type Theme = 'light' | 'dark' | 'system'
|
|
440
|
-
type ColorTheme = string // e.g., 'default', 'blue', 'green', etc.
|
|
441
|
-
|
|
442
|
-
interface SpacemanThemeProviderProps {
|
|
443
|
-
children: React.ReactNode
|
|
444
|
-
defaultTheme?: Theme
|
|
445
|
-
defaultColorTheme?: ColorTheme
|
|
446
|
-
themes?: Theme[]
|
|
447
|
-
colorThemes?: ColorTheme[]
|
|
448
|
-
animationType?: ThemeAnimationType
|
|
449
|
-
duration?: number
|
|
450
|
-
blurAmount?: number
|
|
451
|
-
onThemeChange?: (theme: Theme) => void
|
|
452
|
-
onColorThemeChange?: (colorTheme: ColorTheme) => void
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
interface UseThemeAnimationProps {
|
|
456
|
-
themes?: Theme[]
|
|
457
|
-
colorThemes?: ColorTheme[]
|
|
458
|
-
theme?: Theme
|
|
459
|
-
colorTheme?: ColorTheme
|
|
460
|
-
animationType?: ThemeAnimationType
|
|
461
|
-
duration?: number
|
|
462
|
-
blurAmount?: number
|
|
463
|
-
onThemeChange?: (theme: Theme) => void
|
|
464
|
-
onColorThemeChange?: (colorTheme: ColorTheme) => void
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
interface UseThemeAnimationReturn {
|
|
468
|
-
theme: Theme
|
|
469
|
-
colorTheme: ColorTheme
|
|
470
|
-
switchTheme: (theme: Theme) => Promise<void>
|
|
471
|
-
setColorTheme: (colorTheme: ColorTheme) => void
|
|
472
|
-
toggleTheme: () => Promise<void>
|
|
473
|
-
ref: RefObject<HTMLElement>
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
interface ThemeSwitcherProps {
|
|
477
|
-
themes?: Theme[]
|
|
478
|
-
currentTheme?: Theme
|
|
479
|
-
onThemeChange?: (theme: Theme) => void
|
|
480
|
-
animationType?: ThemeAnimationType
|
|
481
|
-
duration?: number
|
|
482
|
-
className?: string
|
|
483
|
-
}
|
|
200
|
+
import { useThemeAnimation } from '@space-man/react-theme-animation'
|
|
484
201
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
duration?: number
|
|
492
|
-
}
|
|
202
|
+
const { theme, toggleTheme, ref } = useThemeAnimation({
|
|
203
|
+
animationType: ThemeAnimationType.BLUR_CIRCLE,
|
|
204
|
+
duration: 750,
|
|
205
|
+
colorThemes: ['default', 'blue', 'green'],
|
|
206
|
+
onThemeChange: theme => console.log('Theme:', theme),
|
|
207
|
+
})
|
|
493
208
|
```
|
|
494
209
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
---
|
|
498
|
-
|
|
499
|
-
## Browser Support
|
|
500
|
-
|
|
501
|
-
- **View Transitions API**: Chrome 111+, Edge 111+
|
|
502
|
-
- **Fallback**: All modern browsers with CSS transitions
|
|
503
|
-
- **Reduced Motion**: Respects `prefers-reduced-motion` setting
|
|
504
|
-
- **Framework Support**: React 16.8+ (hooks required)
|
|
505
|
-
|
|
506
|
-
---
|
|
507
|
-
|
|
508
|
-
## Performance
|
|
509
|
-
|
|
510
|
-
- Animations use the View Transitions API when available
|
|
511
|
-
- Optimized for 60fps animations
|
|
512
|
-
- Respects `prefers-reduced-motion` setting
|
|
513
|
-
|
|
514
|
-
---
|
|
210
|
+
</details>
|
|
515
211
|
|
|
516
212
|
## Contributing
|
|
517
213
|
|
|
518
|
-
|
|
214
|
+
Fork the repository, make your changes, and submit a merge request for review.
|
|
519
215
|
|
|
520
216
|
## License
|
|
521
217
|
|