@@ -2,7 +2,8 @@ import { useForm, getFormProps } from '@conform-to/react'
2
2
import { parseWithZod } from '@conform-to/zod'
3
3
import { invariantResponse } from '@epic-web/invariant'
4
4
import { json , type ActionFunctionArgs } from '@remix-run/node'
5
- import { useFetcher , useFetchers } from '@remix-run/react'
5
+ import { redirect , useFetcher , useFetchers } from '@remix-run/react'
6
+ import { ServerOnly } from 'remix-utils/server-only'
6
7
import { z } from 'zod'
7
8
import { Icon } from '#app/components/ui/icon.tsx'
8
9
import { useHints } from '#app/utils/client-hints.tsx'
@@ -11,6 +12,8 @@ import { type Theme, setTheme } from '#app/utils/theme.server.ts'
11
12
12
13
const ThemeFormSchema = z . object ( {
13
14
theme : z . enum ( [ 'system' , 'light' , 'dark' ] ) ,
15
+ // this is useful for progressive enhancement
16
+ redirectTo : z . string ( ) . optional ( ) ,
14
17
} )
15
18
16
19
export async function action ( { request } : ActionFunctionArgs ) {
@@ -21,12 +24,16 @@ export async function action({ request }: ActionFunctionArgs) {
21
24
22
25
invariantResponse ( submission . status === 'success' , 'Invalid theme received' )
23
26
24
- const { theme } = submission . value
27
+ const { theme, redirectTo } = submission . value
25
28
26
29
const responseInit = {
27
30
headers : { 'set-cookie' : setTheme ( theme ) } ,
28
31
}
29
- return json ( { result : submission . reply ( ) } , responseInit )
32
+ if ( redirectTo ) {
33
+ return redirect ( redirectTo , responseInit )
34
+ } else {
35
+ return json ( { result : submission . reply ( ) } , responseInit )
36
+ }
30
37
}
31
38
32
39
export function ThemeSwitch ( {
@@ -35,6 +42,7 @@ export function ThemeSwitch({
35
42
userPreference ?: Theme | null
36
43
} ) {
37
44
const fetcher = useFetcher < typeof action > ( )
45
+ const requestInfo = useRequestInfo ( )
38
46
39
47
const [ form ] = useForm ( {
40
48
id : 'theme-switch' ,
@@ -69,6 +77,11 @@ export function ThemeSwitch({
69
77
{ ...getFormProps ( form ) }
70
78
action = "/resources/theme-switch"
71
79
>
80
+ < ServerOnly >
81
+ { ( ) => (
82
+ < input type = "hidden" name = "redirectTo" value = { requestInfo . path } />
83
+ ) }
84
+ </ ServerOnly >
72
85
< input type = "hidden" name = "theme" value = { nextMode } />
73
86
< div className = "flex gap-2" >
74
87
< button
0 commit comments