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 ? (
-
From 47b66bd164bf7d5b7d05a811130b4c1d0267841d Mon Sep 17 00:00:00 2001
From: Sulthan Nauval Abdillah
Date: Tue, 28 Apr 2026 13:43:28 +0700
Subject: [PATCH 2/2] fix(panel): drop redundant language suffix from artifact
type badges
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- "Spreadsheet · json" → "Spreadsheet"; "Slides · json" → "Slides"; etc.
- language suffix is preserved only for application/code, where TS / Python / Rust is the actual differentiator
- applies to two callsites: panel header pill and the artifacts-list entries in chat-workspace's right rail
---
.../components/chat/artifacts/artifact-panel.tsx | 6 +++++-
.../conversations/components/chat/chat-workspace.tsx | 4 +++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/features/conversations/components/chat/artifacts/artifact-panel.tsx b/src/features/conversations/components/chat/artifacts/artifact-panel.tsx
index 5859e7d6..dacf4e74 100644
--- a/src/features/conversations/components/chat/artifacts/artifact-panel.tsx
+++ b/src/features/conversations/components/chat/artifacts/artifact-panel.tsx
@@ -545,7 +545,11 @@ export function ArtifactPanel({
{TYPE_SHORT_LABELS[artifact.type] || artifact.type}
- {artifact.language ? ` · ${artifact.language}` : ""}
+ {/* Language suffix only carries information for application/code,
+ where TypeScript vs Python vs Rust is the actual differentiator.
+ For Spreadsheet / Slides / Mermaid / SVG / etc. the type label
+ already conveys the format, so appending "· json" is just noise. */}
+ {isCodeOnly && artifact.language ? ` · ${artifact.language}` : ""}
{/* Version pill (inline in header) */}
diff --git a/src/features/conversations/components/chat/chat-workspace.tsx b/src/features/conversations/components/chat/chat-workspace.tsx
index c97a0826..3658c0f1 100644
--- a/src/features/conversations/components/chat/chat-workspace.tsx
+++ b/src/features/conversations/components/chat/chat-workspace.tsx
@@ -3746,7 +3746,9 @@ Use update_artifact with id="${artifactId}" to update the existing artifact with