feat(editor): add sidebar mode to CodeEditor component

Add an optional  prop to the CodeEditor component to support
rendering in both modal and sidebar layouts. When enabled, the editor
adapts its container styling and removes the fixed overlay positioning,
allowing it to be embedded inline. This includes conditional rendering
of the loading state and main container to properly display within a
sidebar context while maintaining the existing modal behavior as the
default.
This commit is contained in:
simos
2025-10-31 09:47:30 +00:00
parent 4e14222487
commit 36f8f50d63
2 changed files with 135 additions and 44 deletions

View File

@@ -13,7 +13,7 @@ import { showMinimap } from '@replit/codemirror-minimap';
import { X, Save, Download, Maximize2, Minimize2, Eye, EyeOff } from 'lucide-react';
import { api } from '../utils/api';
function CodeEditor({ file, onClose, projectPath }) {
function CodeEditor({ file, onClose, projectPath, isSidebar = false }) {
const [content, setContent] = useState('');
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
@@ -321,14 +321,23 @@ function CodeEditor({ file, onClose, projectPath }) {
}
`}
</style>
<div className="fixed inset-0 z-50 md:bg-black/50 md:flex md:items-center md:justify-center">
<div className="code-editor-loading w-full h-full md:rounded-lg md:w-auto md:h-auto p-8 flex items-center justify-center">
{isSidebar ? (
<div className="w-full h-full flex items-center justify-center bg-white dark:bg-gray-900">
<div className="flex items-center gap-3">
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600"></div>
<span className="text-gray-900 dark:text-white">Loading {file.name}...</span>
</div>
</div>
</div>
) : (
<div className="fixed inset-0 z-50 md:bg-black/50 md:flex md:items-center md:justify-center">
<div className="code-editor-loading w-full h-full md:rounded-lg md:w-auto md:h-auto p-8 flex items-center justify-center">
<div className="flex items-center gap-3">
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600"></div>
<span className="text-gray-900 dark:text-white">Loading {file.name}...</span>
</div>
</div>
</div>
)}
</>
);
}
@@ -403,33 +412,32 @@ function CodeEditor({ file, onClose, projectPath }) {
}
`}
</style>
<div className={`fixed inset-0 z-50 ${
<div className={isSidebar ?
'w-full h-full flex flex-col' :
`fixed inset-0 z-50 ${
// Mobile: native fullscreen, Desktop: modal with backdrop
'md:bg-black/50 md:flex md:items-center md:justify-center md:p-4'
} ${isFullscreen ? 'md:p-0' : ''}`}>
<div className={`bg-white shadow-2xl flex flex-col ${
// Mobile: always fullscreen, Desktop: modal sizing
'w-full h-full md:rounded-lg md:shadow-2xl' +
(isFullscreen ? ' md:w-full md:h-full md:rounded-none' : ' md:w-full md:max-w-6xl md:h-[80vh] md:max-h-[80vh]')
}`}>
<div className={isSidebar ?
'bg-white dark:bg-gray-900 flex flex-col w-full h-full' :
`bg-white shadow-2xl flex flex-col ${
// Mobile: always fullscreen, Desktop: modal sizing
'w-full h-full md:rounded-lg md:shadow-2xl' +
(isFullscreen ? ' md:w-full md:h-full md:rounded-none' : ' md:w-full md:max-w-6xl md:h-[80vh] md:max-h-[80vh]')
}`}>
{/* Header */}
<div className="flex items-center justify-between p-4 border-b border-gray-200 flex-shrink-0 min-w-0">
<div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700 flex-shrink-0 min-w-0">
<div className="flex items-center gap-3 min-w-0 flex-1">
<div className="w-8 h-8 bg-blue-600 rounded flex items-center justify-center flex-shrink-0">
<span className="text-white text-sm font-mono">
{file.name.split('.').pop()?.toUpperCase() || 'FILE'}
</span>
</div>
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2 min-w-0">
<h3 className="font-medium text-gray-900 truncate">{file.name}</h3>
<h3 className="font-medium text-gray-900 dark:text-white truncate">{file.name}</h3>
{file.diffInfo && (
<span className="text-xs bg-blue-100 text-blue-600 px-2 py-1 rounded whitespace-nowrap">
<span className="text-xs bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-300 px-2 py-1 rounded whitespace-nowrap">
📝 Has changes
</span>
)}
</div>
<p className="text-sm text-gray-500 truncate">{file.path}</p>
<p className="text-sm text-gray-500 dark:text-gray-400 truncate">{file.path}</p>
</div>
</div>
@@ -496,13 +504,15 @@ function CodeEditor({ file, onClose, projectPath }) {
)}
</button>
<button
onClick={toggleFullscreen}
className="hidden md:flex p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 items-center justify-center"
title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}
>
{isFullscreen ? <Minimize2 className="w-4 h-4" /> : <Maximize2 className="w-4 h-4" />}
</button>
{!isSidebar && (
<button
onClick={toggleFullscreen}
className="hidden md:flex p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 items-center justify-center"
title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}
>
{isFullscreen ? <Minimize2 className="w-4 h-4" /> : <Maximize2 className="w-4 h-4" />}
</button>
)}
<button
onClick={onClose}
@@ -565,7 +575,6 @@ function CodeEditor({ file, onClose, projectPath }) {
<div className="flex items-center gap-4 text-sm text-gray-600 dark:text-gray-400">
<span>Lines: {content.split('\n').length}</span>
<span>Characters: {content.length}</span>
<span>Language: {file.name.split('.').pop()?.toUpperCase() || 'Text'}</span>
</div>
<div className="text-sm text-gray-500 dark:text-gray-400">