Skip to content

Commit ddf54a5

Browse files
committed
builder fixes
1 parent 47227ab commit ddf54a5

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

src/components/builder/BuilderLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function BuilderLayout() {
2929
{/* Right panel - Explorer/Preview */}
3030
<div
3131
className={`
32-
flex-1 min-w-0
32+
flex-1 min-w-0 min-h-0 overflow-hidden
3333
bg-white dark:bg-gray-900
3434
${isMobileConfigOpen ? 'hidden md:flex' : 'flex'}
3535
flex-col

src/components/builder/explorer/ExplorerPanel.tsx

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import * as React from 'react'
66
import { twMerge } from 'tailwind-merge'
77
import { useNavigate, useSearch } from '@tanstack/react-router'
8+
import { useIsFetching } from '@tanstack/react-query'
89
import { FileExplorer } from '~/components/FileExplorer'
910
import { CodeViewer } from './CodeViewer'
1011
import { LivePreview } from '../preview/LivePreview'
@@ -121,18 +122,34 @@ export function ExplorerPanel({
121122
}
122123

123124
const dryRun = useDryRun()
125+
const isFetchingDryRun = useIsFetching({ queryKey: ['dry-run'] }) > 0
124126
const files = React.useMemo(
125127
() => (dryRun?.files ?? {}) as Record<string, string>,
126128
[dryRun?.files],
127129
)
130+
const hasFiles = Object.keys(files).length > 0
131+
132+
// Keep track of previous files to avoid blank state during loading
133+
const previousFilesRef = React.useRef<Record<string, string>>(files)
134+
React.useEffect(() => {
135+
if (hasFiles) {
136+
previousFilesRef.current = files
137+
}
138+
}, [files, hasFiles])
139+
140+
// Use previous files while loading to avoid blank state
141+
const displayFiles = hasFiles ? files : previousFilesRef.current
128142

129143
// Convert flat files to tree structure for FileExplorer
130-
const fileTree = React.useMemo(() => filesToGitHubTree(files), [files])
144+
const fileTree = React.useMemo(
145+
() => filesToGitHubTree(displayFiles),
146+
[displayFiles],
147+
)
131148

132149
// Auto-select first file if none selected
133150
React.useEffect(() => {
134-
if (!selectedFile && Object.keys(files).length > 0) {
135-
const fileKeys = Object.keys(files)
151+
if (!selectedFile && Object.keys(displayFiles).length > 0) {
152+
const fileKeys = Object.keys(displayFiles)
136153
const preferredFiles = [
137154
'src/routes/index.tsx',
138155
'src/routes/__root.tsx',
@@ -157,17 +174,17 @@ export function ExplorerPanel({
157174
setSelectedFile(fileKeys[0].replace(/^\.\//, ''))
158175
}
159176
// eslint-disable-next-line react-hooks/exhaustive-deps -- setSelectedFile is stable from useState
160-
}, [files, selectedFile])
177+
}, [displayFiles, selectedFile])
161178

162179
// Try to find file content - files may have ./ prefix or not
163180
const selectedFileContent = selectedFile
164-
? (files[selectedFile] ?? files[`./${selectedFile}`] ?? null)
181+
? (displayFiles[selectedFile] ?? displayFiles[`./${selectedFile}`] ?? null)
165182
: null
166183

167184
return (
168-
<div className="flex flex-col h-full">
185+
<div className="flex flex-col h-full min-h-0 overflow-hidden">
169186
{/* Tab bar */}
170-
<div className="flex items-center border-b border-gray-200 dark:border-gray-800 bg-gray-50 dark:bg-gray-900/50">
187+
<div className="flex items-center shrink-0 border-b border-gray-200 dark:border-gray-800 bg-gray-50 dark:bg-gray-900/50">
171188
{/* Mobile config toggle */}
172189
<button
173190
type="button"
@@ -233,7 +250,7 @@ export function ExplorerPanel({
233250
</div>
234251

235252
{/* Content area */}
236-
<div className="flex-1 overflow-hidden flex flex-col">
253+
<div className="flex-1 overflow-hidden flex flex-col relative">
237254
{activeTab === 'files' ? (
238255
<div className="flex-1 flex min-h-0 overflow-hidden">
239256
{/* File tree sidebar using existing FileExplorer */}
@@ -264,6 +281,18 @@ export function ExplorerPanel({
264281
{canPreview && previewActivated && isTerminalOpen && (
265282
<Terminal onClose={() => setIsTerminalOpen(false)} />
266283
)}
284+
285+
{/* Loading overlay */}
286+
{isFetchingDryRun && (
287+
<div className="absolute inset-0 bg-white/50 dark:bg-gray-900/50 backdrop-blur-[1px] flex items-center justify-center z-10">
288+
<div className="flex items-center gap-3 px-4 py-2 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700">
289+
<div className="w-5 h-5 border-2 border-gray-300 dark:border-gray-600 border-t-blue-500 rounded-full animate-spin" />
290+
<span className="text-sm text-gray-600 dark:text-gray-300">
291+
Generating...
292+
</span>
293+
</div>
294+
</div>
295+
)}
267296
</div>
268297
</div>
269298
)

0 commit comments

Comments
 (0)