1+ import  {  OrganizationSwitcher ,  useClerk  }  from  "@clerk/clerk-react" ; 
12import  { 
23	faArrowUpRight , 
3- 	faCheck , 
44	faLink , 
55	faServer , 
66	faSpinnerThird , 
7- 	faTriangleExclamation , 
87	Icon , 
98}  from  "@rivet-gg/icons" ; 
109import  {  useQuery  }  from  "@tanstack/react-query" ; 
11- import  {  Link ,  useMatchRoute ,  useNavigate  }  from  "@tanstack/react-router" ; 
10+ import  { 
11+ 	Link , 
12+ 	useMatch , 
13+ 	useMatchRoute , 
14+ 	useNavigate , 
15+ }  from  "@tanstack/react-router" ; 
1216import  { 
1317	type  ComponentProps , 
1418	createContext , 
@@ -22,8 +26,10 @@ import {
2226	useState , 
2327}  from  "react" ; 
2428import  type  {  ImperativePanelGroupHandle  }  from  "react-resizable-panels" ; 
29+ import  {  match  }  from  "ts-pattern" ; 
2530import  { 
2631	Button , 
32+ 	type  ButtonProps , 
2733	cn , 
2834	DocsSheet , 
2935	type  ImperativePanelHandle , 
@@ -148,13 +154,25 @@ const Sidebar = ({
148154						/> 
149155					</ Link > 
150156					< div  className = "flex flex-1 flex-col gap-4 px-2 min-h-0" > 
151- 						{ __APP_TYPE__  ===  "inspector"  ? ( 
152- 							< ConnectionStatus  /> 
153- 						)  : null } 
154- 						{ __APP_TYPE__  ===  "engine"  ? < Breadcrumbs  />  : null } 
155- 						< ScrollArea > 
156- 							< Subnav  /> 
157- 						</ ScrollArea > 
157+ 						{ match ( __APP_TYPE__ ) 
158+ 							. with ( "engine" ,  ( )  =>  ( 
159+ 								< > 
160+ 									< ConnectionStatus  /> 
161+ 									< ScrollArea > 
162+ 										< Subnav  /> 
163+ 									</ ScrollArea > 
164+ 								</ > 
165+ 							) ) 
166+ 							. with ( "inspector" ,  ( )  =>  ( 
167+ 								< > 
168+ 									< Breadcrumbs  /> 
169+ 									< ScrollArea > 
170+ 										< Subnav  /> 
171+ 									</ ScrollArea > 
172+ 								</ > 
173+ 							) ) 
174+ 							. with ( "cloud" ,  ( )  =>  < CloudSidebar  /> ) 
175+ 							. exhaustive ( ) } 
158176					</ div > 
159177					< div > 
160178						< div  className = "border-t p-2 flex flex-col gap-[1px] text-sm" > 
@@ -233,7 +251,7 @@ const Footer = () => {
233251
234252export  {  Root ,  Main ,  Header ,  Footer ,  VisibleInFull ,  Sidebar  } ; 
235253
236- const  Breadcrumbs  =  ( )  =>  { 
254+ const  Breadcrumbs  =  ( ) :  ReactNode  =>  { 
237255	const  matchRoute  =  useMatchRoute ( ) ; 
238256	const  nsMatch  =  matchRoute ( { 
239257		to : "/ns/$namespace" , 
@@ -333,26 +351,37 @@ const Subnav = () => {
333351
334352function  HeaderLink ( {  icon,  children,  className,  ...props  } : HeaderLinkProps )  { 
335353	return  ( 
336- 		< Button 
354+ 		< HeaderButton 
337355			asChild 
338356			variant = "ghost" 
339357			{ ...props } 
340- 			className = { cn ( 
341- 				"text-muted-foreground px-2 aria-current-page:text-foreground relative h-auto py-1 justify-start" , 
342- 				className , 
343- 			) } 
344358			startIcon = { 
345359				icon  ? ( 
346360					< Icon  className = { cn ( "size-5 opacity-80" ) }  icon = { icon }  /> 
347361				)  : undefined 
348362			} 
349363		> 
350364			< Link  to = { props . to } > { children } </ Link > 
365+ 		</ HeaderButton > 
366+ 	) ; 
367+ } 
368+ 
369+ function  HeaderButton ( {  children,  className,  ...props  } : ButtonProps )  { 
370+ 	return  ( 
371+ 		< Button 
372+ 			variant = "ghost" 
373+ 			{ ...props } 
374+ 			className = { cn ( 
375+ 				"text-muted-foreground px-2 aria-current-page:text-foreground relative h-auto py-1 justify-start" , 
376+ 				className , 
377+ 			) } 
378+ 		> 
379+ 			{ children } 
351380		</ Button > 
352381	) ; 
353382} 
354383
355- function  ConnectionStatus ( )  { 
384+ function  ConnectionStatus ( ) :  ReactNode  { 
356385	const  {  endpoint,  ...queries  }  =  useManager ( ) ; 
357386	const  {  setCredentials }  =  useInspectorCredentials ( ) ; 
358387	const  {  isLoading,  isError,  isSuccess }  =  useQuery ( 
@@ -406,4 +435,48 @@ function ConnectionStatus() {
406435			</ div > 
407436		) ; 
408437	} 
438+ 
439+ 	return  null ; 
440+ } 
441+ 
442+ function  CloudSidebar ( ) : ReactNode  { 
443+ 	const  match  =  useMatch ( { 
444+ 		from : "/_layout/orgs/$organization/" , 
445+ 		shouldThrow : false , 
446+ 	} ) ; 
447+ 
448+ 	const  clerk  =  useClerk ( ) ; 
449+ 	return  ( 
450+ 		< > 
451+ 			< OrganizationSwitcher  /> 
452+ 
453+ 			< ScrollArea > 
454+ 				< div  className = "flex gap-1.5 flex-col" > 
455+ 					< HeaderLink 
456+ 						to = "/orgs/$organization" 
457+ 						className = "font-normal" 
458+ 						params = { match ?. params } 
459+ 					> 
460+ 						Projects
461+ 					</ HeaderLink > 
462+ 					< HeaderButton 
463+ 						onClick = { ( )  =>  { 
464+ 							clerk . openUserProfile ( { 
465+ 								__experimental_startPath : "/billing" , 
466+ 							} ) ; 
467+ 						} } 
468+ 					> 
469+ 						Billing
470+ 					</ HeaderButton > 
471+ 					< HeaderButton 
472+ 						onClick = { ( )  =>  { 
473+ 							clerk . openUserProfile ( ) ; 
474+ 						} } 
475+ 					> 
476+ 						Settings
477+ 					</ HeaderButton > 
478+ 				</ div > 
479+ 			</ ScrollArea > 
480+ 		</ > 
481+ 	) ; 
409482} 
0 commit comments