fix: AI Assist panel as in-flow flex sibling (not fixed/overlay)
Replace fixed positioning with in-flow flex layout. The outermost div is now a horizontal flex row: content column (flex-1 min-w-0) + panel (w-[380px] shrink-0). When the panel opens, the content column automatically shrinks — no padding hacks or z-index stacking needed. This guarantees the content shifts left and stays fully visible. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,8 +6,6 @@ import { ChatTab } from './ChatTab'
|
||||
import { SuggestionsTab } from './SuggestionsTab'
|
||||
import type { EditorAIChatMessage, AISuggestion } from '@/types'
|
||||
|
||||
const PANEL_WIDTH = 380
|
||||
|
||||
interface EditorAIPanelProps {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
@@ -25,8 +23,6 @@ interface EditorAIPanelProps {
|
||||
|
||||
type Tab = 'chat' | 'suggestions'
|
||||
|
||||
export { PANEL_WIDTH }
|
||||
|
||||
export function EditorAIPanel({
|
||||
isOpen,
|
||||
onClose,
|
||||
@@ -49,10 +45,8 @@ export function EditorAIPanel({
|
||||
|
||||
return (
|
||||
<div
|
||||
className="fixed right-0 bottom-0 z-40 flex flex-col border-l"
|
||||
className="flex h-full w-[380px] shrink-0 flex-col border-l"
|
||||
style={{
|
||||
top: '56px',
|
||||
width: `${PANEL_WIDTH}px`,
|
||||
background: 'rgba(16, 17, 20, 0.95)',
|
||||
backdropFilter: 'var(--glass-blur)',
|
||||
WebkitBackdropFilter: 'var(--glass-blur)',
|
||||
|
||||
@@ -10,7 +10,7 @@ import { getScheduleSummary } from '@/components/procedural-editor/scheduleUtils
|
||||
import { StepList } from '@/components/procedural-editor/StepList'
|
||||
import { TagInput } from '@/components/common/TagInput'
|
||||
import { Spinner } from '@/components/common/Spinner'
|
||||
import { EditorAIPanel, PANEL_WIDTH } from '@/components/editor-ai/EditorAIPanel'
|
||||
import { EditorAIPanel } from '@/components/editor-ai/EditorAIPanel'
|
||||
import { ContextMenu } from '@/components/common/ContextMenu'
|
||||
import { useEditorAI } from '@/hooks/useEditorAI'
|
||||
import { cn } from '@/lib/utils'
|
||||
@@ -180,7 +180,9 @@ export function ProceduralEditorPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col overflow-hidden transition-[padding] duration-200" style={{ paddingRight: editorAI.isOpen ? `${PANEL_WIDTH}px` : 0 }}>
|
||||
<div className="flex h-full overflow-hidden">
|
||||
{/* Main content column */}
|
||||
<div className="flex min-w-0 flex-1 flex-col overflow-hidden">
|
||||
{/* Toolbar — sticky */}
|
||||
<div className="flex shrink-0 items-center justify-between border-b border-border bg-card px-4 py-2">
|
||||
<div className="flex items-center gap-3">
|
||||
@@ -320,21 +322,6 @@ export function ProceduralEditorPage() {
|
||||
<StepList onStepContextMenu={editorAI.openContextMenu} />
|
||||
</div>
|
||||
|
||||
<EditorAIPanel
|
||||
isOpen={editorAI.isOpen}
|
||||
onClose={editorAI.closePanel}
|
||||
focalNode={null}
|
||||
flowName={name}
|
||||
flowType={isMaintenance ? 'maintenance' : 'procedural'}
|
||||
nodeCount={steps.length}
|
||||
messages={editorAI.messages}
|
||||
input={editorAI.input}
|
||||
onInputChange={editorAI.setInput}
|
||||
onSend={editorAI.sendMessage}
|
||||
isLoading={editorAI.isLoading}
|
||||
suggestions={editorAI.suggestions}
|
||||
/>
|
||||
|
||||
{editorAI.contextMenu && (
|
||||
<ContextMenu
|
||||
position={editorAI.contextMenu.position}
|
||||
@@ -363,6 +350,22 @@ export function ProceduralEditorPage() {
|
||||
onClose={editorAI.closeContextMenu}
|
||||
/>
|
||||
)}
|
||||
</div>{/* end main content column */}
|
||||
|
||||
<EditorAIPanel
|
||||
isOpen={editorAI.isOpen}
|
||||
onClose={editorAI.closePanel}
|
||||
focalNode={null}
|
||||
flowName={name}
|
||||
flowType={isMaintenance ? 'maintenance' : 'procedural'}
|
||||
nodeCount={steps.length}
|
||||
messages={editorAI.messages}
|
||||
input={editorAI.input}
|
||||
onInputChange={editorAI.setInput}
|
||||
onSend={editorAI.sendMessage}
|
||||
isLoading={editorAI.isLoading}
|
||||
suggestions={editorAI.suggestions}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import { cn, safeGetItem } from '@/lib/utils'
|
||||
import { toast } from '@/lib/toast'
|
||||
import { FlowAnalyticsPanel } from '@/components/analytics/FlowAnalyticsPanel'
|
||||
import { ExportFlowModal } from '@/components/library/ExportFlowModal'
|
||||
import { EditorAIPanel, PANEL_WIDTH } from '@/components/editor-ai/EditorAIPanel'
|
||||
import { EditorAIPanel } from '@/components/editor-ai/EditorAIPanel'
|
||||
import { ContextMenu } from '@/components/common/ContextMenu'
|
||||
import { useEditorAI } from '@/hooks/useEditorAI'
|
||||
import { findNodeInTree } from '@/store/treeEditorStore'
|
||||
@@ -522,7 +522,9 @@ export function TreeEditorPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col overflow-hidden transition-[padding] duration-200" style={{ paddingRight: editorAI.isOpen ? `${PANEL_WIDTH}px` : 0 }}>
|
||||
<div className="flex h-full overflow-hidden">
|
||||
{/* Main content column */}
|
||||
<div className="flex min-w-0 flex-1 flex-col overflow-hidden">
|
||||
|
||||
{/* Draft Restore Prompt */}
|
||||
{showDraftPrompt && (
|
||||
@@ -876,23 +878,6 @@ export function TreeEditorPage() {
|
||||
/>
|
||||
)}
|
||||
|
||||
<EditorAIPanel
|
||||
isOpen={editorAI.isOpen}
|
||||
onClose={handleAIPanelClose}
|
||||
focalNode={editorAI.focalNodeId && treeStructure
|
||||
? findNodeInTree(editorAI.focalNodeId, treeStructure)
|
||||
: null}
|
||||
flowName={name}
|
||||
flowType="troubleshooting"
|
||||
nodeCount={treeStructure ? getAllNodeIds().length : 0}
|
||||
messages={editorAI.messages}
|
||||
input={editorAI.input}
|
||||
onInputChange={editorAI.setInput}
|
||||
onSend={editorAI.sendMessage}
|
||||
isLoading={editorAI.isLoading}
|
||||
suggestions={editorAI.suggestions}
|
||||
/>
|
||||
|
||||
{/* AI Context Menu */}
|
||||
{editorAI.contextMenu && (
|
||||
<ContextMenu
|
||||
@@ -946,6 +931,24 @@ export function TreeEditorPage() {
|
||||
onClose={editorAI.closeContextMenu}
|
||||
/>
|
||||
)}
|
||||
</div>{/* end main content column */}
|
||||
|
||||
<EditorAIPanel
|
||||
isOpen={editorAI.isOpen}
|
||||
onClose={handleAIPanelClose}
|
||||
focalNode={editorAI.focalNodeId && treeStructure
|
||||
? findNodeInTree(editorAI.focalNodeId, treeStructure)
|
||||
: null}
|
||||
flowName={name}
|
||||
flowType="troubleshooting"
|
||||
nodeCount={treeStructure ? getAllNodeIds().length : 0}
|
||||
messages={editorAI.messages}
|
||||
input={editorAI.input}
|
||||
onInputChange={editorAI.setInput}
|
||||
onSend={editorAI.sendMessage}
|
||||
isLoading={editorAI.isLoading}
|
||||
suggestions={editorAI.suggestions}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user