1
- import { type Interpolation , type Theme , css , useTheme } from "@emotion/react" ;
2
- import MenuIcon from "@mui/icons-material/Menu" ;
3
- import Drawer from "@mui/material/Drawer" ;
4
- import IconButton from "@mui/material/IconButton" ;
5
1
import type * as TypesGen from "api/typesGenerated" ;
6
2
import { ExternalImage } from "components/ExternalImage/ExternalImage" ;
7
3
import { CoderIcon } from "components/Icons/CoderIcon" ;
8
4
import type { ProxyContextValue } from "contexts/ProxyContext" ;
9
- import { type FC , useState } from "react" ;
10
- import { Link , NavLink , useLocation } from "react-router-dom" ;
5
+ import type { FC } from "react" ;
6
+ import { NavLink , useLocation } from "react-router-dom" ;
11
7
import { DeploymentDropdown } from "./DeploymentDropdown" ;
12
8
import { ProxyMenu } from "./ProxyMenu" ;
13
9
import { UserDropdown } from "./UserDropdown/UserDropdown" ;
14
10
import { cn } from "utils/cn" ;
11
+ import { Button } from "components/Button/Button" ;
12
+ import { ChevronRightIcon , MenuIcon } from "lucide-react" ;
13
+ import {
14
+ DropdownMenu ,
15
+ DropdownMenuContent ,
16
+ DropdownMenuItem ,
17
+ DropdownMenuTrigger ,
18
+ } from "components/DropdownMenu/DropdownMenu" ;
19
+ import { Avatar } from "components/Avatar/Avatar" ;
20
+ import { Latency } from "components/Latency/Latency" ;
15
21
16
- export const Language = {
17
- workspaces : "Workspaces" ,
18
- templates : "Templates" ,
19
- users : "Users" ,
20
- audit : "Audit Logs" ,
21
- deployment : "Deployment" ,
22
- } ;
23
22
export interface NavbarViewProps {
24
23
logo_url ?: string ;
25
24
user ?: TypesGen . User ;
@@ -41,6 +40,9 @@ const linkClassNames = {
41
40
active : "text-content-primary" ,
42
41
} ;
43
42
43
+ const mobileDropdownItemClassName =
44
+ "px-9 h-[60px] border-0 border-b border-solid" ;
45
+
44
46
export const NavbarView : FC < NavbarViewProps > = ( {
45
47
user,
46
48
logo_url,
@@ -55,40 +57,8 @@ export const NavbarView: FC<NavbarViewProps> = ({
55
57
canViewAuditLog,
56
58
proxyContextValue,
57
59
} ) => {
58
- const [ isDrawerOpen , setIsDrawerOpen ] = useState ( false ) ;
59
-
60
60
return (
61
61
< div className = "border-0 border-b border-solid h-[72px] flex items-center leading-none px-6" >
62
- < IconButton
63
- aria-label = "Open menu"
64
- css = { styles . mobileMenuButton }
65
- onClick = { ( ) => {
66
- setIsDrawerOpen ( true ) ;
67
- } }
68
- size = "large"
69
- >
70
- < MenuIcon />
71
- </ IconButton >
72
-
73
- < Drawer
74
- anchor = "left"
75
- open = { isDrawerOpen }
76
- onClose = { ( ) => setIsDrawerOpen ( false ) }
77
- >
78
- < div css = { { width : 250 } } >
79
- < div css = { styles . drawerHeader } >
80
- < div css = { [ "h-7" , styles . drawerLogo ] } >
81
- { logo_url ? (
82
- < ExternalImage src = { logo_url } alt = "Custom Logo" />
83
- ) : (
84
- < CoderIcon />
85
- ) }
86
- </ div >
87
- </ div >
88
- < NavItems />
89
- </ div >
90
- </ Drawer >
91
-
92
62
< NavLink to = "/workspaces" >
93
63
{ logo_url ? (
94
64
< ExternalImage className = "h-7" src = { logo_url } alt = "Custom Logo" />
@@ -99,7 +69,7 @@ export const NavbarView: FC<NavbarViewProps> = ({
99
69
100
70
< NavItems className = "ml-4" />
101
71
102
- < div className = "flex items-center gap-3 ml-auto" >
72
+ < div className = " hidden md: flex items-center gap-3 ml-auto" >
103
73
{ proxyContextValue && (
104
74
< ProxyMenu proxyContextValue = { proxyContextValue } />
105
75
) }
@@ -130,10 +100,70 @@ export const NavbarView: FC<NavbarViewProps> = ({
130
100
/>
131
101
) }
132
102
</ div >
103
+
104
+ < MobileMenu proxyContextValue = { proxyContextValue } user = { user } />
133
105
</ div >
134
106
) ;
135
107
} ;
136
108
109
+ type MobileMenuProps = {
110
+ proxyContextValue ?: ProxyContextValue ;
111
+ user ?: TypesGen . User ;
112
+ } ;
113
+
114
+ const MobileMenu : FC < MobileMenuProps > = ( { proxyContextValue, user } ) => {
115
+ const selectedProxy = proxyContextValue ?. proxy . proxy ;
116
+ const latency = selectedProxy
117
+ ? proxyContextValue ?. proxyLatencies [ selectedProxy ?. id ]
118
+ : undefined ;
119
+
120
+ return (
121
+ < DropdownMenu >
122
+ < DropdownMenuTrigger asChild >
123
+ < Button
124
+ aria-label = "Open Menu"
125
+ size = "icon"
126
+ variant = "ghost"
127
+ className = "ml-auto md:hidden"
128
+ >
129
+ < MenuIcon />
130
+ </ Button >
131
+ </ DropdownMenuTrigger >
132
+ < DropdownMenuContent className = "w-screen border-0 p-0" sideOffset = { 17 } >
133
+ { selectedProxy && (
134
+ < DropdownMenuItem className = { mobileDropdownItemClassName } >
135
+ Workspace proxy settings:
136
+ < span className = "leading-[0px] flex items-center gap-1" >
137
+ < img
138
+ className = "w-4 h-4"
139
+ src = { selectedProxy . icon_url }
140
+ alt = { selectedProxy . name }
141
+ />
142
+ { latency && < Latency latency = { latency . latencyMS } /> }
143
+ </ span >
144
+ < ChevronRightIcon className = "ml-auto" />
145
+ </ DropdownMenuItem >
146
+ ) }
147
+ < DropdownMenuItem className = { mobileDropdownItemClassName } >
148
+ Admin settings
149
+ < ChevronRightIcon className = "ml-auto" />
150
+ </ DropdownMenuItem >
151
+ < DropdownMenuItem className = { mobileDropdownItemClassName } >
152
+ Docs
153
+ </ DropdownMenuItem >
154
+ < DropdownMenuItem className = { mobileDropdownItemClassName } >
155
+ < Avatar
156
+ src = { user ?. avatar_url }
157
+ fallback = { user ?. name || user ?. username }
158
+ />
159
+ User settings
160
+ < ChevronRightIcon className = "ml-auto" />
161
+ </ DropdownMenuItem >
162
+ </ DropdownMenuContent >
163
+ </ DropdownMenu >
164
+ ) ;
165
+ } ;
166
+
137
167
interface NavItemsProps {
138
168
className ?: string ;
139
169
}
@@ -155,7 +185,7 @@ const NavItems: FC<NavItemsProps> = ({ className }) => {
155
185
} }
156
186
to = "/workspaces"
157
187
>
158
- { Language . workspaces }
188
+ Workspaces
159
189
</ NavLink >
160
190
< NavLink
161
191
className = { ( { isActive } ) => {
@@ -166,26 +196,8 @@ const NavItems: FC<NavItemsProps> = ({ className }) => {
166
196
} }
167
197
to = "/templates"
168
198
>
169
- { Language . templates }
199
+ Templates
170
200
</ NavLink >
171
201
</ nav >
172
202
) ;
173
203
} ;
174
-
175
- const styles = {
176
- mobileMenuButton : ( theme ) => css `
177
- ${ theme . breakpoints . up ( "md" ) } {
178
- display : none;
179
- }
180
- ` ,
181
-
182
- drawerHeader : {
183
- padding : 16 ,
184
- paddingTop : 32 ,
185
- paddingBottom : 32 ,
186
- } ,
187
- drawerLogo : {
188
- padding : 0 ,
189
- maxHeight : 40 ,
190
- } ,
191
- } satisfies Record < string , Interpolation < Theme > > ;
0 commit comments