From ad39354a8ee5e2158f47d65b6cae52c106222ff7 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sat, 17 Jan 2026 00:12:23 +0000 Subject: [PATCH] Generated by Spark: Add preview button to toolbar --- src/App.tsx | 7 +++ src/components/PreviewDialog.tsx | 67 +++++++++++++++++++++ src/components/organisms/AppHeader.tsx | 3 + src/components/organisms/ToolbarActions.tsx | 12 ++++ 4 files changed, 89 insertions(+) create mode 100644 src/components/PreviewDialog.tsx diff --git a/src/App.tsx b/src/App.tsx index de0b48e..154b547 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -37,6 +37,7 @@ const componentMap: Record> = { const GlobalSearch = lazy(() => import('@/components/GlobalSearch').then(m => ({ default: m.GlobalSearch }))) const KeyboardShortcutsDialog = lazy(() => import('@/components/KeyboardShortcutsDialog').then(m => ({ default: m.KeyboardShortcutsDialog }))) +const PreviewDialog = lazy(() => import('@/components/PreviewDialog').then(m => ({ default: m.PreviewDialog }))) const PWAInstallPrompt = lazy(() => import('@/components/PWAInstallPrompt').then(m => ({ default: m.PWAInstallPrompt }))) const PWAUpdatePrompt = lazy(() => import('@/components/PWAUpdatePrompt').then(m => ({ default: m.PWAUpdatePrompt }))) const PWAStatusBar = lazy(() => import('@/components/PWAStatusBar').then(m => ({ default: m.PWAStatusBar }))) @@ -81,6 +82,7 @@ function App() { const [activeTab, setActiveTab] = useState('dashboard') const [searchOpen, setSearchOpen] = useState(false) const [shortcutsOpen, setShortcutsOpen] = useState(false) + const [previewOpen, setPreviewOpen] = useState(false) const [lastSaved] = useState(Date.now()) const [errorCount] = useState(0) const [appReady, setAppReady] = useState(false) @@ -116,6 +118,7 @@ function App() { })), { key: 'k', ctrl: true, description: 'Search', action: () => setSearchOpen(true) }, { key: '/', ctrl: true, description: 'Shortcuts', action: () => setShortcutsOpen(true) }, + { key: 'p', ctrl: true, description: 'Preview', action: () => setPreviewOpen(true) }, ]) const getCurrentProject = () => ({ @@ -324,6 +327,7 @@ function App() { onShowShortcuts={() => setShortcutsOpen(true)} onGenerateAI={() => toast.info('AI generation coming soon')} onExport={() => toast.info('Export coming soon')} + onPreview={() => setPreviewOpen(true)} onShowErrors={() => setActiveTab('errors')} /> @@ -358,6 +362,9 @@ function App() { + + + diff --git a/src/components/PreviewDialog.tsx b/src/components/PreviewDialog.tsx new file mode 100644 index 0000000..8efb048 --- /dev/null +++ b/src/components/PreviewDialog.tsx @@ -0,0 +1,67 @@ +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' +import { Button } from '@/components/ui/button' +import { X, ArrowSquareOut } from '@phosphor-icons/react' +import { useEffect, useState } from 'react' + +interface PreviewDialogProps { + open: boolean + onOpenChange: (open: boolean) => void +} + +export function PreviewDialog({ open, onOpenChange }: PreviewDialogProps) { + const [previewUrl, setPreviewUrl] = useState('') + + useEffect(() => { + if (open) { + const currentUrl = window.location.href + const url = new URL(currentUrl) + url.searchParams.set('preview', 'true') + setPreviewUrl(url.toString()) + } + }, [open]) + + const handleOpenInNewTab = () => { + if (previewUrl) { + window.open(previewUrl, '_blank', 'noopener,noreferrer') + } + } + + return ( + + + + Preview +
+ + +
+
+
+ {previewUrl && ( +