Skip to content

Commit 4144de6

Browse files
committed
chore: prepare demos for Vercel
1 parent c7993e0 commit 4144de6

14 files changed

+605
-282
lines changed

README.md

+138
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,141 @@ await themeStore.restore() // restore persisted theme selection
204204
themeStore.sync() // useful for syncing theme selection across tabs and windows
205205
themeStore.subscribe((themes, resolvedThemes) => { /* ... */ }) // return unsubscribe function
206206
```
207+
208+
## React Integration
209+
210+
### Client-only persistence
211+
212+
Ensure that you have initialized Palettez as per instructions under [Basic Usage](#basic-usage). As theme selection is only known on the client, you should only render component with `usePalettez` once the app has mounted.
213+
214+
```tsx
215+
import * as React from 'react'
216+
import { usePalettez } from 'palettez/react'
217+
218+
function Component() {
219+
const [mounted, setMounted] = useState(false)
220+
221+
useEffect(() => {
222+
setMounted(true)
223+
}, [])
224+
225+
return mounted ? <ThemeSelect /> : null
226+
}
227+
228+
function ThemeSelect() {
229+
const {
230+
themesAndOptions,
231+
themes,
232+
setThemes,
233+
234+
getResolvedThemes,
235+
restore,
236+
sync,
237+
subscribe,
238+
} = usePalettez(window.palettez.getThemeStore())
239+
240+
return themesAndOptions.map((theme) => (
241+
<div key={theme.key}>
242+
<label htmlFor={theme.key}>{theme.label}</label>
243+
<select
244+
id={theme.key}
245+
name={theme.key}
246+
onChange={(e) => {
247+
setThemes({ [theme.key]: e.target.value })
248+
}}
249+
value={themes[theme.key]}
250+
>
251+
{theme.options.map((option) => (
252+
<option key={option.key} value={option.key}>
253+
{option.value}
254+
</option>
255+
))}
256+
</select>
257+
</div>
258+
))
259+
}
260+
```
261+
262+
### Server-side persistence
263+
264+
If you are storing theme selection on the server, you can choose to use `memoryStorageAdapter` to avoid storing any data client-side. There's no need to initialize Palettez in a synchronous script. Ensure you pass the persisted theme selection when initializing Palettez as `initialThemes`.
265+
266+
```tsx
267+
import { createThemeStore, memoryStorageAdapter } from 'palettez'
268+
import { usePalettez } from 'palettez/react'
269+
import * as React from 'react'
270+
271+
export function ThemeSelect({
272+
persistedServerThemes,
273+
}: { persistedServerThemes: Record<string, string> }) {
274+
const [themeStore] = React.useState(() =>
275+
createThemeStore({
276+
config: {
277+
colorScheme: {
278+
label: 'Color scheme',
279+
options: {
280+
system: {
281+
value: 'System',
282+
isDefault: true,
283+
media: {
284+
query: '(prefers-color-scheme: dark)',
285+
ifMatch: 'dark',
286+
ifNotMatch: 'light',
287+
},
288+
},
289+
light: { value: 'Light' },
290+
dark: { value: 'Dark' },
291+
},
292+
},
293+
contrast: {
294+
label: 'Contrast',
295+
options: {
296+
standard: { value: 'Standard', isDefault: true },
297+
high: { value: 'High' },
298+
},
299+
},
300+
},
301+
initialThemes: persistedServerThemes,
302+
storage: memoryStorageAdapter(),
303+
}),
304+
)
305+
306+
const { themesAndOptions, themes, setThemes, subscribe } = usePalettez(themeStore)
307+
308+
React.useEffect(() => {
309+
const unsubscribe = subscribe((_, resolvedThemes) => {
310+
for (const [theme, optionKey] of Object.entries(resolvedThemes)) {
311+
;(
312+
(document.querySelector('.theme') as
313+
| HTMLElementTagNameMap['main']
314+
| null) || document.documentElement
315+
).dataset[theme] = optionKey
316+
}
317+
})
318+
319+
return () => {
320+
unsubscribe()
321+
}
322+
}, [subscribe])
323+
324+
return themesAndOptions.map((theme) => (
325+
<div key={theme.key}>
326+
<label htmlFor={theme.key}>{theme.label}</label>{' '}
327+
<select
328+
id={theme.key}
329+
name={theme.key}
330+
onChange={(e) => {
331+
setThemes({ [theme.key]: e.target.value })
332+
}}
333+
value={themes[theme.key]}
334+
>
335+
{theme.options.map((option) => (
336+
<option key={option.key} value={option.key}>
337+
{option.value}
338+
</option>
339+
))}
340+
</select>
341+
</div>
342+
))
343+
}
344+
```

demos/astro/astro.config.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
import node from '@astrojs/node'
21
import react from '@astrojs/react'
2+
import vercel from '@astrojs/vercel/serverless'
33
import { defineConfig } from 'astro/config'
44

55
export default defineConfig({
6-
adapter: node({
7-
mode: 'standalone',
8-
}),
6+
adapter: vercel(),
97
integrations: [react()],
108
output: 'hybrid',
119
})

demos/astro/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
"react-dom": "18.3.1"
1313
},
1414
"devDependencies": {
15-
"@astrojs/node": "8.3.3",
1615
"@astrojs/react": "3.6.2",
16+
"@astrojs/vercel": "7.7.2",
1717
"@types/react": "18.3.3",
1818
"@types/react-dom": "18.3.0",
1919
"typescript": "5.5.4"

demos/remix/app/entry.client.tsx

-18
This file was deleted.

demos/remix/app/entry.server.tsx

-140
This file was deleted.

demos/remix/app/root.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import type { MetaFunction } from '@remix-run/node'
2-
import { Outlet } from '@remix-run/react'
1+
import { type MetaFunction, Outlet } from '@remix-run/react'
32
import type * as React from 'react'
43
import './style.css'
54

demos/remix/app/routes/multi-store-with-server-persistence.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import {
2-
type ActionFunctionArgs,
3-
type LoaderFunctionArgs,
4-
json,
5-
} from '@remix-run/node'
61
import {
72
Links,
83
Meta,
94
Scripts,
105
useActionData,
116
useLoaderData,
127
} from '@remix-run/react'
8+
import {
9+
type ActionFunctionArgs,
10+
type LoaderFunctionArgs,
11+
json,
12+
} from '@vercel/remix'
1313
import { getThemeAndOptions } from 'palettez'
1414
import palettez from 'palettez/raw?raw'
1515
import { createStoresScript } from '../multi-store-scripts'

demos/remix/app/routes/no-hydration-mismatch.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import {
2-
type ActionFunctionArgs,
3-
type LoaderFunctionArgs,
4-
json,
5-
} from '@remix-run/node'
61
import {
72
Links,
83
Meta,
94
Scripts,
105
useActionData,
116
useLoaderData,
127
} from '@remix-run/react'
8+
import {
9+
type ActionFunctionArgs,
10+
type LoaderFunctionArgs,
11+
json,
12+
} from '@vercel/remix'
1313
import { getThemeAndOptions } from 'palettez'
1414
import { ThemeSelect } from '../theme-select'
1515
import { ThemeStoreProvider } from '../theme-store-provider'

0 commit comments

Comments
 (0)