From c99c4c4c823ce33fd1a73971c5c3cb40baa51e6c Mon Sep 17 00:00:00 2001 From: Sulthan Nauval Abdillah Date: Tue, 28 Apr 2026 13:39:47 +0700 Subject: [PATCH 1/2] refactor(panel): drop Preview/Code tab pair; preview-first chrome MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - removes the dual-tab affordance at the top of the artifact panel; preview is now the primary view for every artifact type - adds a single Edit pencil to the panel header (gated on onUpdateArtifact, hidden for text/document which keeps its renderer-internal pencil) - adds a discrete bottom-corner Source toggle for non-code, non-document types — matches the document-script-renderer pattern (Code/preview button at the bottom, not a top tab) - application/code drops the redundant Source toggle since its preview is already syntax-highlighted code - text/document keeps its existing controls (script: floating modal pencil; AST: read-only legacy banner) - removes tab state, the tab-bar JSX, and the useEffect that exited edit on tab switch --- .../chat/artifacts/artifact-panel.tsx | 258 +++++++++--------- 1 file changed, 124 insertions(+), 134 deletions(-) diff --git a/src/features/conversations/components/chat/artifacts/artifact-panel.tsx b/src/features/conversations/components/chat/artifacts/artifact-panel.tsx index df7b3df0..5859e7d6 100644 --- a/src/features/conversations/components/chat/artifacts/artifact-panel.tsx +++ b/src/features/conversations/components/chat/artifacts/artifact-panel.tsx @@ -9,7 +9,6 @@ import { Check, Code, Eye, - Play, ChevronLeft, ChevronRight, Pencil, @@ -72,16 +71,15 @@ export function ArtifactPanel({ sessionId, isStreaming = false, }: ArtifactPanelProps) { - const isCodeOnly = artifact.type === "application/code" - const isRunnable = artifact.type === "application/python" - // text/document hides the Code tab — the preview is the source of truth - // (renders the same DOCX bytes the user downloads, so a separate source view - // would just duplicate what's already in the tool call). const isTextDocument = artifact.type === "text/document" - const [tab, setTab] = useState<"preview" | "code">( - isCodeOnly ? "code" : "preview" - ) + const isCodeOnly = artifact.type === "application/code" + // Code-only artifacts are already syntax-highlighted in the preview, so a + // separate "show source" toggle is redundant. text/document uses its own + // renderer-level controls (script has the EditDocumentModal pencil; AST is + // read-only). Everything else gets the bottom-corner Code toggle. + const showSourceToggle = !isCodeOnly && !isTextDocument const [isEditing, setIsEditing] = useState(false) + const [showSource, setShowSource] = useState(false) const [copied, setCopied] = useState(false) const [isFullscreen, setIsFullscreen] = useState(false) const [viewingVersionIdx, setViewingVersionIdx] = useState( @@ -152,11 +150,6 @@ export function ArtifactPanel({ setViewingVersionIdx(null) }, [artifact.version]) - // Exit edit mode when switching tabs - useEffect(() => { - setIsEditing(false) - }, [tab]) - // Escape key exits fullscreen useEffect(() => { if (!isFullscreen) return @@ -712,6 +705,25 @@ export function ArtifactPanel({ )} + {/* Edit toggle — replaces the old Preview/Code tab affordance. + Hidden for text/document (script has its own modal-pencil overlay + on the renderer, AST is read-only legacy) and during edit. */} + {onUpdateArtifact && !isEditing && !isTextDocument && ( + + + + + Edit source + + )} + {/* More menu (delete lives here) */} {onDeleteArtifact && ( @@ -795,104 +807,12 @@ export function ArtifactPanel({ )} - {/* Tab bar — hidden for application/code (preview == code, redundant) - and for text/document (preview is the source of truth for exports; - a separate Code tab would mislead users into thinking they can edit - the .docx directly from there). */} - {!isCodeOnly && !isTextDocument && ( -
- - -
- )} - - {/* Content */} -
- {tab === "preview" || isTextDocument ? ( - // text/document branches on documentFormat: - // "script" → DocumentScriptRenderer (server-rendered PNG carousel) - // "ast" or undefined → legacy DocumentRenderer (via ArtifactRenderer), - // prefixed with a banner steering users toward the - // new format on their next document. - displayArtifact.type === "text/document" && - displayArtifact.documentFormat === "script" ? ( - sessionId ? ( -
- - - - - - Edit document - -
- ) : ( -
- Preview unavailable: missing session context. -
- ) - ) : displayArtifact.type === "text/document" ? ( -
-
- This is a legacy document format. Create a new document to use the latest features. -
-
- onFixWithAI(displayArtifact.id, error) : undefined} - onDownloadXlsx={handleDownload} - /> -
-
- ) : ( - onFixWithAI(displayArtifact.id, error) : undefined} - onDownloadXlsx={handleDownload} - /> - ) - ) : isEditing ? ( - /* Code tab — edit mode */ + {/* Content — preview-first; the old Preview/Code tab pair is replaced + by a header pencil for edit and a bottom-corner Code toggle for the + opt-in source view (matches document-script-renderer's pattern). */} +
+ {isEditing ? ( + /* Edit mode — full-panel textarea with footer */