33import 'chart.js/auto'
44import 'chartjs-adapter-date-fns'
55
6+ import { DialogTrigger } from '@radix-ui/react-dialog'
67import { LazyMotion , m } from 'framer-motion'
7- import { Loader } from 'lucide-react'
8+ import { Loader , MoreVertical } from 'lucide-react'
89import Link from 'next/link'
9- import { PropsWithChildren } from 'react'
10+ import { PropsWithChildren , useState } from 'react'
1011import { TooltipProvider } from '~/components/ui/tooltip'
1112import { useDatabasesQuery } from '~/data/databases/databases-query'
1213import { useBreakpoint } from '~/lib/use-breakpoint'
@@ -17,6 +18,7 @@ import {
1718 legacyDomainUrl ,
1819} from '~/lib/util'
1920import { useApp } from './app-provider'
21+ import { LiveShareIcon } from './live-share-icon'
2022import Sidebar from './sidebar'
2123import { Accordion , AccordionContent , AccordionItem , AccordionTrigger } from './ui/accordion'
2224import { Dialog , DialogContent , DialogHeader , DialogTitle } from './ui/dialog'
@@ -26,15 +28,14 @@ const loadFramerFeatures = () => import('./framer-features').then((res) => res.d
2628export type LayoutProps = PropsWithChildren
2729
2830export default function Layout ( { children } : LayoutProps ) {
29- const { isPreview , isLegacyDomain, isLegacyDomainRedirect } = useApp ( )
31+ const { isLegacyDomain, isLegacyDomainRedirect } = useApp ( )
3032 const isSmallBreakpoint = useBreakpoint ( 'lg' )
3133
3234 return (
3335 < LazyMotion features = { loadFramerFeatures } >
3436 < TooltipProvider delayDuration = { 0 } >
3537 < div className = "w-full h-full flex flex-col overflow-hidden" >
36- { isPreview && < PreviewBanner /> }
37- { /* TODO: re-enable rename banner when ready */ }
38+ { ! isLegacyDomain && < LiveShareBanner /> }
3839 { ( isLegacyDomain || isLegacyDomainRedirect ) && < RenameBanner /> }
3940 < main className = "flex-1 flex flex-col lg:flex-row min-h-0" >
4041 { /* TODO: make sidebar available on mobile */ }
@@ -50,11 +51,82 @@ export default function Layout({ children }: LayoutProps) {
5051 )
5152}
5253
53- function PreviewBanner ( ) {
54+ function LiveShareBanner ( ) {
55+ const [ videoLoaded , setVideoLoaded ] = useState ( false )
56+
5457 return (
55- < div className = "px-3 py-3 flex justify-center text-sm text-center bg-neutral-800 text-white" >
56- Heads up! This is a preview version of { currentDomainHostname } , so expect some changes here
57- and there.
58+ < div className = "px-3 py-3 flex gap-1 justify-center text-sm text-center bg-neutral-800 text-white" >
59+ < span > New: Connect to your in-browser databases from outside the browser.</ span >
60+ < Dialog onOpenChange = { ( ) => setVideoLoaded ( false ) } >
61+ < DialogTrigger asChild >
62+ < span className = "underline cursor-pointer" > Learn more.</ span >
63+ </ DialogTrigger >
64+ < DialogContent className = "max-w-2x max-h-full overflow-y-auto" >
65+ < DialogHeader >
66+ < DialogTitle > Introducing Live Share</ DialogTitle >
67+ < div className = "py-2 border-b" />
68+ </ DialogHeader >
69+
70+ < div className = "prose" >
71+ < p >
72+ With Live Share, you can connect directly to your in-browser PGlite databases from{ ' ' }
73+ < em > outside the browser</ em > .
74+ </ p >
75+ < div
76+ style = { {
77+ position : 'relative' ,
78+ display : 'flex' ,
79+ justifyContent : 'center' ,
80+ alignItems : 'center' ,
81+ } }
82+ >
83+ { ! videoLoaded && (
84+ < div style = { { position : 'absolute' , zIndex : 1 , color : 'white' } } >
85+ < Loader className = "animate-spin" size = { 36 } strokeWidth = { 0.75 } />
86+ </ div >
87+ ) }
88+ < m . video
89+ width = "1860"
90+ height = "1080"
91+ variants = { {
92+ hidden : { opacity : 0 } ,
93+ show : { opacity : 1 } ,
94+ } }
95+ initial = "hidden"
96+ animate = { videoLoaded ? 'show' : 'hidden' }
97+ className = "rounded-sm m-0"
98+ autoPlay
99+ loop
100+ onLoadedData = { ( ) => setVideoLoaded ( true ) }
101+ >
102+ < source
103+ src = "https://github.com/user-attachments/assets/78c45f61-4213-49f0-a563-55b426dd6c35"
104+ type = "video/mp4"
105+ />
106+ </ m . video >
107+ </ div >
108+
109+ < m . div layout className = "inline-block" >
110+ < h4 className = "font-bold" > How does it work?</ h4 >
111+
112+ < ol className = "mb-0" >
113+ < li >
114+ Click on the < MoreVertical size = { 16 } className = "text-muted-foreground inline" /> { ' ' }
115+ menu next your database and tap{ ' ' }
116+ < strong >
117+ < LiveShareIcon size = { 16 } className = "text-muted-foreground inline" /> Live Share
118+ </ strong >
119+ </ li >
120+ < li > A unique connection string will appear for your database</ li >
121+ < li >
122+ Copy-paste the connection string into any Postgres client (like < code > psql</ code > )
123+ and begin querying!
124+ </ li >
125+ </ ol >
126+ </ m . div >
127+ </ div >
128+ </ DialogContent >
129+ </ Dialog >
58130 </ div >
59131 )
60132}
0 commit comments