1
1
'use client' ;
2
2
import * as ToggleGroup from '@radix-ui/react-toggle-group' ;
3
3
import { motion } from 'framer-motion' ;
4
- import type * as React from 'react ' ;
4
+ import { usePathname , useRouter , useSearchParams } from 'next/navigation ' ;
5
5
import { cn } from '../utils' ;
6
6
import { tabTransition } from '../utils/constants' ;
7
7
import { Heading } from './heading' ;
8
8
import { IconHideSidebar } from './icons/icon-hide-sidebar' ;
9
9
import { IconMonitor } from './icons/icon-monitor' ;
10
+ import { IconMoon } from './icons/icon-moon' ;
10
11
import { IconPhone } from './icons/icon-phone' ;
11
12
import { IconSource } from './icons/icon-source' ;
13
+ import { IconSun } from './icons/icon-sun' ;
12
14
import { Send } from './send' ;
13
15
import { Tooltip } from './tooltip' ;
14
16
15
17
interface TopbarProps {
16
18
currentEmailOpenSlug : string ;
17
19
pathSeparator : string ;
18
- activeView ?: string ;
19
20
markup ?: string ;
20
21
onToggleSidebar ?: ( ) => void ;
21
- setActiveView ?: ( view : string ) => void ;
22
22
}
23
23
24
24
export const Topbar : React . FC < Readonly < TopbarProps > > = ( {
25
25
currentEmailOpenSlug,
26
26
pathSeparator,
27
27
markup,
28
- activeView,
29
- setActiveView,
30
28
onToggleSidebar,
31
29
} ) => {
30
+ const router = useRouter ( ) ;
31
+ const pathname = usePathname ( ) ;
32
+ const searchParams = useSearchParams ( ) ;
33
+
34
+ const activeTheme = searchParams . get ( 'theme' ) ?? 'light' ;
35
+ const activeView = searchParams . get ( 'view' ) ?? 'desktop' ;
36
+
37
+ const setActiveView = ( view : string ) => {
38
+ const params = new URLSearchParams ( searchParams ) ;
39
+ params . set ( 'view' , view ) ;
40
+ router . push ( `${ pathname } ?${ params . toString ( ) } ` ) ;
41
+ } ;
42
+
43
+ const setTheme = ( theme : string ) => {
44
+ const params = new URLSearchParams ( searchParams ) ;
45
+ params . set ( 'theme' , theme ) ;
46
+ router . push ( `${ pathname } ?${ params . toString ( ) } ` ) ;
47
+ } ;
48
+
32
49
return (
33
50
< Tooltip . Provider >
34
- < header className = "flex relative items-center px-4 justify-between h-[70px] border-b border-slate-6 " >
51
+ < header className = "relative flex h-[70px] items-center justify-between border-slate-6 border-b px-4 " >
35
52
< Tooltip >
36
53
< Tooltip . Trigger asChild >
37
54
< button
38
- className = "hidden lg:flex rounded-lg px-2 py-2 transition ease-in-out duration-200 relative hover:bg-slate-5 text-slate-11 hover:text-slate-12"
55
+ className = "relative hidden rounded-lg px-2 py-2 text-slate-11 transition duration-200 ease-in-out hover:bg-slate-5 hover:text-slate-12 lg:flex "
39
56
onClick = { ( ) => {
40
57
if ( onToggleSidebar ) {
41
58
onToggleSidebar ( ) ;
@@ -49,18 +66,87 @@ export const Topbar: React.FC<Readonly<TopbarProps>> = ({
49
66
< Tooltip . Content > Show/hide sidebar</ Tooltip . Content >
50
67
</ Tooltip >
51
68
52
- < div className = "items-center overflow-hidden hidden lg:flex text-center absolute left- 1/2 transform -translate-x -1/2 top-1/2 -translate-y- 1/2" >
69
+ < div className = "-translate-x- 1/2 -translate-y -1/2 absolute top-1/2 left- 1/2 hidden transform items-center overflow-hidden text-center lg:flex " >
53
70
< Heading as = "h2" className = "truncate" size = "2" weight = "medium" >
54
71
{ currentEmailOpenSlug . split ( pathSeparator ) . pop ( ) }
55
72
</ Heading >
56
73
</ div >
57
74
58
- < div className = "flex gap-3 justify-between lg:justify-start w-full lg:w-fit" >
75
+ < div className = "flex w-full justify-between gap-3 lg:w-fit lg:justify-start" >
76
+ < ToggleGroup . Root
77
+ aria-label = "Color Scheme"
78
+ className = "inline-block items-center bg-slate-2 border border-slate-6 rounded-md overflow-hidden h-[36px]"
79
+ id = "theme-toggle"
80
+ onValueChange = { ( value ) => {
81
+ if ( value ) setTheme ( value ) ;
82
+ } }
83
+ type = "single"
84
+ value = { activeTheme }
85
+ >
86
+ < ToggleGroup . Item value = "light" >
87
+ < Tooltip >
88
+ < Tooltip . Trigger asChild >
89
+ < div
90
+ className = { cn (
91
+ 'relative px-3 py-2 transition duration-200 ease-in-out hover:text-slate-12' ,
92
+ {
93
+ 'text-slate-11' : activeTheme !== 'light' ,
94
+ 'text-slate-12' : activeTheme === 'light' ,
95
+ } ,
96
+ ) }
97
+ >
98
+ { activeTheme === 'light' && (
99
+ < motion . span
100
+ animate = { { opacity : 1 } }
101
+ className = "absolute top-0 right-0 bottom-0 left-0 bg-slate-4"
102
+ exit = { { opacity : 0 } }
103
+ initial = { { opacity : 0 } }
104
+ layoutId = "topbar-theme-tabs"
105
+ transition = { tabTransition }
106
+ />
107
+ ) }
108
+ < IconSun />
109
+ </ div >
110
+ </ Tooltip . Trigger >
111
+ < Tooltip . Content > Light</ Tooltip . Content >
112
+ </ Tooltip >
113
+ </ ToggleGroup . Item >
114
+ < ToggleGroup . Item value = "dark" >
115
+ < Tooltip >
116
+ < Tooltip . Trigger asChild >
117
+ < div
118
+ className = { cn (
119
+ 'relative px-3 py-2 transition duration-200 ease-in-out hover:text-slate-12' ,
120
+ {
121
+ 'text-slate-11' : activeTheme !== 'dark' ,
122
+ 'text-slate-12' : activeTheme === 'dark' ,
123
+ } ,
124
+ ) }
125
+ >
126
+ { activeTheme === 'dark' && (
127
+ < motion . span
128
+ animate = { { opacity : 1 } }
129
+ className = "absolute top-0 right-0 bottom-0 left-0 bg-slate-4"
130
+ exit = { { opacity : 0 } }
131
+ initial = { { opacity : 0 } }
132
+ layoutId = "topbar-theme-tabs"
133
+ transition = { tabTransition }
134
+ />
135
+ ) }
136
+ < IconMoon />
137
+ </ div >
138
+ </ Tooltip . Trigger >
139
+ < Tooltip . Content > Dark</ Tooltip . Content >
140
+ </ Tooltip >
141
+ </ ToggleGroup . Item >
142
+ </ ToggleGroup . Root >
143
+
59
144
< ToggleGroup . Root
60
145
aria-label = "View mode"
61
146
className = "inline-block items-center bg-slate-2 border border-slate-6 rounded-md overflow-hidden h-[36px]"
147
+ id = "view-toggle"
62
148
onValueChange = { ( value ) => {
63
- if ( value ) setActiveView ?. ( value ) ;
149
+ if ( value ) setActiveView ( value ) ;
64
150
} }
65
151
type = "single"
66
152
value = { activeView }
@@ -83,7 +169,7 @@ export const Topbar: React.FC<Readonly<TopbarProps>> = ({
83
169
className = "absolute left-0 right-0 top-0 bottom-0 bg-slate-4"
84
170
exit = { { opacity : 0 } }
85
171
initial = { { opacity : 0 } }
86
- layoutId = "topbar-tabs"
172
+ layoutId = "topbar-view- tabs"
87
173
transition = { tabTransition }
88
174
/>
89
175
) }
@@ -111,7 +197,7 @@ export const Topbar: React.FC<Readonly<TopbarProps>> = ({
111
197
className = "absolute left-0 right-0 top-0 bottom-0 bg-slate-4"
112
198
exit = { { opacity : 0 } }
113
199
initial = { { opacity : 0 } }
114
- layoutId = "topbar-tabs"
200
+ layoutId = "topbar-view- tabs"
115
201
transition = { tabTransition }
116
202
/>
117
203
) }
@@ -139,7 +225,7 @@ export const Topbar: React.FC<Readonly<TopbarProps>> = ({
139
225
className = "absolute left-0 right-0 top-0 bottom-0 bg-slate-4"
140
226
exit = { { opacity : 0 } }
141
227
initial = { { opacity : 0 } }
142
- layoutId = "topbar-tabs"
228
+ layoutId = "topbar-view- tabs"
143
229
transition = { tabTransition }
144
230
/>
145
231
) }
0 commit comments