From c8e8e50fd631cdbcf88b82936a9e797366ce02fc Mon Sep 17 00:00:00 2001 From: josedario87 Date: Thu, 19 Feb 2026 14:44:25 -0600 Subject: [PATCH] feat: Animated pixel art ocean floor background for FloatingTranscriptDebug Replace galaxy background with animated underwater scene featuring water depth gradient, pixel art sea floor (sand, seaweed, coral, starfish), rising bubbles with water sway, and swimming pixel art fish. Also update transcript-debug tool cards styling and add .claude-*/tasks/ to gitignore. --- .gitignore | 1 + .../components/FloatingTranscriptDebug.vue | 72 +++++- .../AssistantMessageBubble.vue | 7 +- .../transcript-debug/ChatContainer.vue | 122 +++++++--- .../transcript-debug/UserMessageBubble.vue | 208 ++++++++++++------ .../transcript-debug/toolCards/BashCard.vue | 39 ++-- .../transcript-debug/toolCards/EditCard.vue | 68 ++---- .../transcript-debug/toolCards/GlobCard.vue | 17 +- .../transcript-debug/toolCards/GrepCard.vue | 39 ++-- .../transcript-debug/toolCards/ReadCard.vue | 17 +- .../transcript-debug/toolCards/TaskCard.vue | 60 ++--- .../transcript-debug/toolCards/WriteCard.vue | 33 +-- 12 files changed, 379 insertions(+), 304 deletions(-) diff --git a/.gitignore b/.gitignore index 626e25d..7ad82ec 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ server/recordings/*.webm .claude-*/plugins/ .claude-*/plans/ .claude-*/file-history/ +.claude-*/tasks/ diff --git a/frontend/src/components/FloatingTranscriptDebug.vue b/frontend/src/components/FloatingTranscriptDebug.vue index 467cdb7..c931494 100644 --- a/frontend/src/components/FloatingTranscriptDebug.vue +++ b/frontend/src/components/FloatingTranscriptDebug.vue @@ -665,9 +665,77 @@ onBeforeUnmount(() => { display: flex; flex-direction: column; position: relative; - /* Pixel art galaxy: spiral arms, stars, nebula in bottom-right corner */ + isolation: isolate; + /* Pixel art animated ocean floor */ background: - url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120' shape-rendering='crispEdges'%3E%3C!-- galaxy core --%3E%3Crect x='56' y='56' width='4' height='4' fill='%23fef3c7' opacity='0.35'/%3E%3Crect x='60' y='56' width='4' height='4' fill='%23fde68a' opacity='0.3'/%3E%3Crect x='56' y='60' width='4' height='4' fill='%23fde68a' opacity='0.28'/%3E%3Crect x='60' y='60' width='4' height='4' fill='%23fef9c3' opacity='0.4'/%3E%3Crect x='52' y='56' width='4' height='4' fill='%23c4b5fd' opacity='0.2'/%3E%3Crect x='64' y='56' width='4' height='4' fill='%23a78bfa' opacity='0.18'/%3E%3Crect x='56' y='52' width='4' height='4' fill='%23818cf8' opacity='0.2'/%3E%3Crect x='60' y='64' width='4' height='4' fill='%23c4b5fd' opacity='0.18'/%3E%3C!-- spiral arm top-right --%3E%3Crect x='68' y='48' width='4' height='4' fill='%236366f1' opacity='0.18'/%3E%3Crect x='72' y='44' width='4' height='4' fill='%23818cf8' opacity='0.14'/%3E%3Crect x='76' y='40' width='4' height='4' fill='%236366f1' opacity='0.12'/%3E%3Crect x='80' y='38' width='4' height='2' fill='%23818cf8' opacity='0.1'/%3E%3Crect x='84' y='36' width='4' height='2' fill='%236366f1' opacity='0.08'/%3E%3Crect x='88' y='36' width='2' height='2' fill='%23a78bfa' opacity='0.06'/%3E%3C!-- spiral arm bottom-left --%3E%3Crect x='48' y='68' width='4' height='4' fill='%23818cf8' opacity='0.16'/%3E%3Crect x='44' y='72' width='4' height='4' fill='%236366f1' opacity='0.14'/%3E%3Crect x='40' y='76' width='4' height='4' fill='%23818cf8' opacity='0.12'/%3E%3Crect x='36' y='78' width='4' height='2' fill='%236366f1' opacity='0.1'/%3E%3Crect x='32' y='80' width='4' height='2' fill='%23a78bfa' opacity='0.07'/%3E%3C!-- spiral arm top-left --%3E%3Crect x='48' y='48' width='4' height='4' fill='%23c084fc' opacity='0.15'/%3E%3Crect x='44' y='44' width='4' height='4' fill='%23a855f7' opacity='0.12'/%3E%3Crect x='40' y='40' width='4' height='4' fill='%23c084fc' opacity='0.1'/%3E%3Crect x='36' y='38' width='4' height='2' fill='%23a855f7' opacity='0.08'/%3E%3C!-- spiral arm bottom-right --%3E%3Crect x='68' y='68' width='4' height='4' fill='%23a855f7' opacity='0.14'/%3E%3Crect x='72' y='72' width='4' height='4' fill='%23c084fc' opacity='0.12'/%3E%3Crect x='76' y='76' width='4' height='4' fill='%23a855f7' opacity='0.1'/%3E%3Crect x='80' y='78' width='4' height='2' fill='%23c084fc' opacity='0.07'/%3E%3C!-- nebula clouds --%3E%3Crect x='50' y='40' width='8' height='2' fill='%23f0abfc' opacity='0.07'/%3E%3Crect x='66' y='62' width='6' height='2' fill='%2367e8f9' opacity='0.06'/%3E%3Crect x='42' y='64' width='6' height='2' fill='%23f0abfc' opacity='0.05'/%3E%3Crect x='64' y='44' width='4' height='2' fill='%2367e8f9' opacity='0.06'/%3E%3C!-- scattered stars --%3E%3Crect x='20' y='18' width='2' height='2' fill='white' opacity='0.2'/%3E%3Crect x='95' y='22' width='2' height='2' fill='white' opacity='0.15'/%3E%3Crect x='14' y='90' width='2' height='2' fill='white' opacity='0.12'/%3E%3Crect x='100' y='88' width='2' height='2' fill='white' opacity='0.18'/%3E%3Crect x='30' y='105' width='2' height='2' fill='%23c4b5fd' opacity='0.1'/%3E%3Crect x='108' y='14' width='2' height='2' fill='%23fde68a' opacity='0.12'/%3E%3Crect x='10' y='50' width='2' height='2' fill='white' opacity='0.1'/%3E%3Crect x='110' y='60' width='2' height='2' fill='%2367e8f9' opacity='0.12'/%3E%3Crect x='70' y='20' width='2' height='2' fill='white' opacity='0.08'/%3E%3Crect x='50' y='100' width='2' height='2' fill='white' opacity='0.1'/%3E%3Crect x='85' y='105' width='2' height='2' fill='%23fde68a' opacity='0.08'/%3E%3Crect x='25' y='30' width='2' height='2' fill='%23c4b5fd' opacity='0.08'/%3E%3C/svg%3E") no-repeat center center / 100% 100%; + /* Subtle light rays from surface */ + repeating-linear-gradient( + -25deg, + transparent 0px, + transparent 60px, + rgba(103, 232, 249, 0.018) 60px, + rgba(103, 232, 249, 0.018) 63px, + transparent 63px, + transparent 180px + ), + /* Water depth gradient */ + linear-gradient( + 180deg, + rgba(0, 8, 28, 0.96) 0%, + rgba(0, 18, 48, 0.94) 20%, + rgba(0, 30, 60, 0.92) 40%, + rgba(2, 45, 72, 0.88) 60%, + rgba(5, 55, 70, 0.85) 75%, + rgba(12, 58, 58, 0.82) 88%, + rgba(30, 55, 40, 0.78) 100% + ), + /* Pixel art sea floor: sand, seaweed, coral, rocks, starfish, shell */ + url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='120' viewBox='0 0 240 120' shape-rendering='crispEdges'%3E%3Crect x='0' y='88' width='240' height='32' fill='%23c2a060' opacity='0.6'/%3E%3Crect x='0' y='86' width='240' height='4' fill='%23d4b878' opacity='0.5'/%3E%3Crect x='10' y='92' width='20' height='2' fill='%23a89048' opacity='0.3'/%3E%3Crect x='50' y='96' width='16' height='2' fill='%23b8a060' opacity='0.25'/%3E%3Crect x='90' y='94' width='24' height='2' fill='%23a89048' opacity='0.3'/%3E%3Crect x='140' y='98' width='20' height='2' fill='%23b8a060' opacity='0.25'/%3E%3Crect x='190' y='92' width='18' height='2' fill='%23a89048' opacity='0.28'/%3E%3Crect x='15' y='80' width='12' height='8' fill='%23475569' opacity='0.55'/%3E%3Crect x='17' y='78' width='8' height='4' fill='%2364748b' opacity='0.45'/%3E%3Crect x='19' y='76' width='4' height='4' fill='%23718096' opacity='0.35'/%3E%3Crect x='45' y='48' width='2' height='40' fill='%2316a34a' opacity='0.55'/%3E%3Crect x='47' y='44' width='2' height='12' fill='%2322c55e' opacity='0.5'/%3E%3Crect x='43' y='52' width='2' height='8' fill='%2315803d' opacity='0.45'/%3E%3Crect x='49' y='40' width='2' height='8' fill='%2322c55e' opacity='0.4'/%3E%3Crect x='41' y='56' width='2' height='6' fill='%2316a34a' opacity='0.35'/%3E%3Crect x='75' y='72' width='2' height='16' fill='%23f87171' opacity='0.5'/%3E%3Crect x='73' y='68' width='2' height='8' fill='%23fb7185' opacity='0.45'/%3E%3Crect x='77' y='70' width='2' height='6' fill='%23f472b6' opacity='0.4'/%3E%3Crect x='71' y='66' width='2' height='4' fill='%23f87171' opacity='0.35'/%3E%3Crect x='79' y='68' width='2' height='4' fill='%23fb7185' opacity='0.35'/%3E%3Crect x='69' y='68' width='2' height='2' fill='%23f472b6' opacity='0.3'/%3E%3Crect x='81' y='70' width='2' height='2' fill='%23f87171' opacity='0.3'/%3E%3Crect x='105' y='62' width='2' height='26' fill='%2322c55e' opacity='0.5'/%3E%3Crect x='107' y='58' width='2' height='10' fill='%2316a34a' opacity='0.45'/%3E%3Crect x='103' y='66' width='2' height='6' fill='%2315803d' opacity='0.4'/%3E%3Crect x='125' y='86' width='2' height='8' fill='%23f97316' opacity='0.5'/%3E%3Crect x='121' y='88' width='10' height='2' fill='%23f97316' opacity='0.5'/%3E%3Crect x='123' y='84' width='2' height='2' fill='%23fb923c' opacity='0.4'/%3E%3Crect x='129' y='84' width='2' height='2' fill='%23fb923c' opacity='0.4'/%3E%3Crect x='121' y='92' width='2' height='2' fill='%23fb923c' opacity='0.4'/%3E%3Crect x='131' y='92' width='2' height='2' fill='%23fb923c' opacity='0.4'/%3E%3Crect x='150' y='50' width='2' height='38' fill='%2316a34a' opacity='0.5'/%3E%3Crect x='152' y='46' width='2' height='10' fill='%2322c55e' opacity='0.45'/%3E%3Crect x='148' y='54' width='2' height='8' fill='%2315803d' opacity='0.4'/%3E%3Crect x='154' y='42' width='2' height='8' fill='%2322c55e' opacity='0.35'/%3E%3Crect x='180' y='76' width='2' height='12' fill='%23818cf8' opacity='0.45'/%3E%3Crect x='178' y='72' width='2' height='6' fill='%23a78bfa' opacity='0.4'/%3E%3Crect x='182' y='74' width='2' height='4' fill='%23c084fc' opacity='0.35'/%3E%3Crect x='176' y='74' width='2' height='2' fill='%23818cf8' opacity='0.3'/%3E%3Crect x='184' y='76' width='2' height='2' fill='%23a78bfa' opacity='0.3'/%3E%3Crect x='210' y='86' width='6' height='4' fill='%23fef3c7' opacity='0.4'/%3E%3Crect x='212' y='84' width='4' height='2' fill='%23fde68a' opacity='0.35'/%3E%3Crect x='214' y='82' width='2' height='2' fill='%23fef3c7' opacity='0.3'/%3E%3Crect x='220' y='82' width='10' height='6' fill='%23475569' opacity='0.5'/%3E%3Crect x='222' y='80' width='6' height='4' fill='%2364748b' opacity='0.4'/%3E%3Crect x='35' y='90' width='2' height='2' fill='%2364748b' opacity='0.3'/%3E%3Crect x='60' y='92' width='2' height='2' fill='%2364748b' opacity='0.25'/%3E%3Crect x='95' y='90' width='2' height='2' fill='%23475569' opacity='0.3'/%3E%3Crect x='160' y='92' width='2' height='2' fill='%2364748b' opacity='0.25'/%3E%3Crect x='200' y='90' width='2' height='2' fill='%23475569' opacity='0.28'/%3E%3C/svg%3E") repeat-x bottom center / 240px 120px; +} + +/* Animated bubbles rising through the water */ +.content::before { + content: ''; + position: absolute; + inset: 0; + pointer-events: none; + z-index: -1; + background: + /* Bubble layer 1 - larger, slower */ + url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='200' viewBox='0 0 80 200' shape-rendering='crispEdges'%3E%3Crect x='20' y='30' width='4' height='4' fill='%2367e8f9' opacity='0.22'/%3E%3Crect x='60' y='90' width='4' height='4' fill='%2367e8f9' opacity='0.18'/%3E%3Crect x='35' y='150' width='4' height='4' fill='%2367e8f9' opacity='0.24'/%3E%3Crect x='50' y='20' width='2' height='2' fill='white' opacity='0.16'/%3E%3Crect x='10' y='70' width='2' height='2' fill='white' opacity='0.13'/%3E%3Crect x='70' y='130' width='2' height='2' fill='white' opacity='0.16'/%3E%3Crect x='25' y='180' width='2' height='2' fill='white' opacity='0.13'/%3E%3Crect x='40' y='50' width='2' height='2' fill='%2367e8f9' opacity='0.1'/%3E%3Crect x='5' y='110' width='2' height='2' fill='%2367e8f9' opacity='0.09'/%3E%3Crect x='55' y='170' width='2' height='2' fill='white' opacity='0.11'/%3E%3C/svg%3E") repeat / 80px 200px, + /* Bubble layer 2 - smaller, different rhythm */ + url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='280' viewBox='0 0 100 280' shape-rendering='crispEdges'%3E%3Crect x='30' y='40' width='4' height='4' fill='%2367e8f9' opacity='0.16'/%3E%3Crect x='75' y='110' width='2' height='2' fill='white' opacity='0.13'/%3E%3Crect x='15' y='180' width='4' height='4' fill='%2367e8f9' opacity='0.2'/%3E%3Crect x='55' y='240' width='2' height='2' fill='white' opacity='0.11'/%3E%3Crect x='85' y='60' width='2' height='2' fill='%2367e8f9' opacity='0.1'/%3E%3Crect x='45' y='150' width='2' height='2' fill='white' opacity='0.13'/%3E%3Crect x='10' y='260' width='2' height='2' fill='%2367e8f9' opacity='0.09'/%3E%3Crect x='65' y='20' width='2' height='2' fill='white' opacity='0.11'/%3E%3C/svg%3E") repeat / 100px 280px; + animation: sea-bubbles 14s linear infinite, water-sway 8s ease-in-out infinite alternate; +} + +/* Animated pixel art fish swimming across */ +.content::after { + content: ''; + position: absolute; + inset: 0; + pointer-events: none; + z-index: -1; + background: + /* Fish 1: orange tropical fish (right-facing, swims left→right) */ + url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='10' viewBox='0 0 16 10' shape-rendering='crispEdges'%3E%3Crect x='0' y='1' width='2' height='2' fill='%23f97316' opacity='0.6'/%3E%3Crect x='0' y='7' width='2' height='2' fill='%23f97316' opacity='0.6'/%3E%3Crect x='2' y='2' width='2' height='6' fill='%23fb923c' opacity='0.6'/%3E%3Crect x='4' y='1' width='8' height='8' fill='%23f97316' opacity='0.55'/%3E%3Crect x='7' y='1' width='2' height='8' fill='%23fef3c7' opacity='0.4'/%3E%3Crect x='5' y='0' width='4' height='1' fill='%23fb923c' opacity='0.4'/%3E%3Crect x='5' y='9' width='4' height='1' fill='%23fb923c' opacity='0.4'/%3E%3Crect x='10' y='3' width='2' height='2' fill='%23000' opacity='0.5'/%3E%3Crect x='11' y='3' width='1' height='1' fill='white' opacity='0.4'/%3E%3Crect x='12' y='5' width='2' height='1' fill='%23000' opacity='0.3'/%3E%3C/svg%3E") no-repeat / 32px 20px, + /* Fish 2: blue fish (left-facing, swims right→left) */ + url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' shape-rendering='crispEdges'%3E%3Crect x='10' y='1' width='2' height='2' fill='%236366f1' opacity='0.5'/%3E%3Crect x='10' y='5' width='2' height='2' fill='%236366f1' opacity='0.5'/%3E%3Crect x='8' y='2' width='2' height='4' fill='%23818cf8' opacity='0.5'/%3E%3Crect x='2' y='1' width='6' height='6' fill='%236366f1' opacity='0.45'/%3E%3Crect x='2' y='2' width='2' height='2' fill='%23000' opacity='0.4'/%3E%3Crect x='2' y='2' width='1' height='1' fill='white' opacity='0.3'/%3E%3Crect x='4' y='0' width='3' height='1' fill='%23818cf8' opacity='0.35'/%3E%3C/svg%3E") no-repeat / 24px 16px; + animation: fish-swim 20s linear infinite; +} + +@keyframes sea-bubbles { + from { background-position: 0 0, 40px 0; } + to { background-position: 0 -200px, 0 -280px; } +} + +@keyframes water-sway { + from { transform: translateX(-3px); } + to { transform: translateX(3px); } +} + +@keyframes fish-swim { + 0% { background-position: -40px 25%, calc(100% + 30px) 55%; } + 100% { background-position: calc(100% + 40px) 30%, -30px 50%; } } /* Override ChatContainer backgrounds for black transparency */ diff --git a/frontend/src/components/transcript-debug/AssistantMessageBubble.vue b/frontend/src/components/transcript-debug/AssistantMessageBubble.vue index 195d356..276f157 100644 --- a/frontend/src/components/transcript-debug/AssistantMessageBubble.vue +++ b/frontend/src/components/transcript-debug/AssistantMessageBubble.vue @@ -103,12 +103,9 @@ function formatTokens(n?: number): string { diff --git a/frontend/src/components/transcript-debug/toolCards/BashCard.vue b/frontend/src/components/transcript-debug/toolCards/BashCard.vue index 6fa3f80..eb769f4 100644 --- a/frontend/src/components/transcript-debug/toolCards/BashCard.vue +++ b/frontend/src/components/transcript-debug/toolCards/BashCard.vue @@ -17,8 +17,7 @@ const isError = computed(() => props.call.result?.isError ?? false) const highlightedCommand = computed(() => highlightCode(command.value, 'bash')) -const cmdExpanded = ref(false) -const resultExpanded = ref(false) +const expanded = ref(false) const cmdPreview = computed(() => { const c = command.value.replace(/\n/g, ' ').trim() @@ -28,7 +27,7 @@ const cmdPreview = computed(() => { @@ -88,7 +73,9 @@ const cmdPreview = computed(() => { padding: 0.3rem 0.6rem; background: transparent; min-height: 28px; + cursor: pointer; } +.card-header:hover { background: rgba(245, 158, 11, 0.04); } .card-icon { display: flex; align-items: center; color: rgba(245, 158, 11, 0.6); flex-shrink: 0; } .bash-card.error .card-icon { color: rgba(239, 68, 68, 0.6); } diff --git a/frontend/src/components/transcript-debug/toolCards/EditCard.vue b/frontend/src/components/transcript-debug/toolCards/EditCard.vue index e7dfffe..bd190bc 100644 --- a/frontend/src/components/transcript-debug/toolCards/EditCard.vue +++ b/frontend/src/components/transcript-debug/toolCards/EditCard.vue @@ -27,8 +27,7 @@ const ext = computed(() => { const isError = computed(() => props.call.result?.isError ?? false) -const diffExpanded = ref(false) -const resultExpanded = ref(false) +const expanded = ref(false) const highlightedOld = computed(() => highlightCode(oldString.value, ext.value || undefined)) const highlightedNew = computed(() => highlightCode(newString.value, ext.value || undefined)) @@ -39,7 +38,7 @@ const newLineCount = computed(() => newString.value.split('\n').length) @@ -105,8 +92,11 @@ const newLineCount = computed(() => newString.value.split('\n').length) padding: 0.3rem 0.6rem; background: transparent; min-height: 28px; + cursor: pointer; } +.card-header:hover { background: rgba(99, 102, 241, 0.04); } + .card-icon { display: flex; align-items: center; color: rgba(99, 102, 241, 0.6); flex-shrink: 0; } .edit-card.error .card-icon { color: rgba(239, 68, 68, 0.6); } @@ -147,26 +137,6 @@ const newLineCount = computed(() => newString.value.split('\n').length) .diff-added { color: rgba(34, 197, 94, 0.7); } .error-badge { color: rgba(239, 68, 68, 0.7); } -.header-spacer { flex: 1; } - -.toggle-btn { - display: flex; - align-items: center; - justify-content: center; - width: 20px; - height: 20px; - border: none; - border-radius: 4px; - background: transparent; - color: var(--text-muted); - cursor: pointer; - flex-shrink: 0; - opacity: 0.5; - transition: all 0.15s; -} -.toggle-btn:hover { opacity: 0.8; } -.toggle-btn.active { opacity: 1; color: rgba(99, 102, 241, 0.8); } - /* Diff */ .diff-content { border-top: 1px solid rgba(255, 255, 255, 0.04); } diff --git a/frontend/src/components/transcript-debug/toolCards/GlobCard.vue b/frontend/src/components/transcript-debug/toolCards/GlobCard.vue index d4d3263..0138a70 100644 --- a/frontend/src/components/transcript-debug/toolCards/GlobCard.vue +++ b/frontend/src/components/transcript-debug/toolCards/GlobCard.vue @@ -19,7 +19,7 @@ const fileCount = computed(() => { return content.split('\n').filter(l => l.trim()).length }) -const resultExpanded = ref(false) +const expanded = ref(false) const shortPath = computed(() => { if (!path.value) return '' @@ -29,7 +29,7 @@ const shortPath = computed(() => { @@ -74,7 +65,9 @@ const shortPath = computed(() => { padding: 0.3rem 0.6rem; background: transparent; min-height: 28px; + cursor: pointer; } +.card-header:hover { background: rgba(251, 191, 36, 0.04); } .card-icon { display: flex; align-items: center; color: rgba(251, 191, 36, 0.6); flex-shrink: 0; } .glob-card.error .card-icon { color: rgba(239, 68, 68, 0.6); } diff --git a/frontend/src/components/transcript-debug/toolCards/GrepCard.vue b/frontend/src/components/transcript-debug/toolCards/GrepCard.vue index e58dd96..b1096bb 100644 --- a/frontend/src/components/transcript-debug/toolCards/GrepCard.vue +++ b/frontend/src/components/transcript-debug/toolCards/GrepCard.vue @@ -42,8 +42,7 @@ const flags = computed(() => { return f }) -const detailsExpanded = ref(false) -const resultExpanded = ref(false) +const expanded = ref(false) const shortPath = computed(() => { if (!path.value) return '' @@ -53,7 +52,7 @@ const shortPath = computed(() => { @@ -113,7 +98,9 @@ const shortPath = computed(() => { padding: 0.3rem 0.6rem; background: transparent; min-height: 28px; + cursor: pointer; } +.card-header:hover { background: rgba(236, 72, 153, 0.04); } .card-icon { display: flex; align-items: center; color: rgba(236, 72, 153, 0.6); flex-shrink: 0; } .grep-card.error .card-icon { color: rgba(239, 68, 68, 0.6); } diff --git a/frontend/src/components/transcript-debug/toolCards/ReadCard.vue b/frontend/src/components/transcript-debug/toolCards/ReadCard.vue index d70d2f2..46d8aff 100644 --- a/frontend/src/components/transcript-debug/toolCards/ReadCard.vue +++ b/frontend/src/components/transcript-debug/toolCards/ReadCard.vue @@ -26,12 +26,12 @@ const ext = computed(() => { return dot >= 0 ? name.slice(dot + 1).toLowerCase() : '' }) -const resultExpanded = ref(false) +const expanded = ref(false) @@ -79,7 +70,9 @@ const resultExpanded = ref(false) padding: 0.3rem 0.6rem; background: transparent; min-height: 28px; + cursor: pointer; } +.card-header:hover { background: rgba(6, 182, 212, 0.04); } .card-icon { display: flex; align-items: center; color: rgba(6, 182, 212, 0.6); flex-shrink: 0; } .read-card.error .card-icon { color: rgba(239, 68, 68, 0.6); } diff --git a/frontend/src/components/transcript-debug/toolCards/TaskCard.vue b/frontend/src/components/transcript-debug/toolCards/TaskCard.vue index cd2ed66..f2d8f0a 100644 --- a/frontend/src/components/transcript-debug/toolCards/TaskCard.vue +++ b/frontend/src/components/transcript-debug/toolCards/TaskCard.vue @@ -21,10 +21,7 @@ const subagentType = computed(() => (props.call.input?.subagent_type as string) const model = computed(() => (props.call.input?.model as string) || '') const runInBackground = computed(() => props.call.input?.run_in_background as boolean | undefined) -// Toggles -const showPrompt = ref(false) -const showResult = ref(false) -const showDesc = ref(false) +const expanded = ref(false) // ---- Extract main topics from result ---- interface TopicItem { @@ -124,9 +121,9 @@ const cardColor = computed(() => { } }) -const hasDesc = computed(() => description.value.length > 0) -const hasPrompt = computed(() => prompt.value.length > 0) -const hasResult = computed(() => !!props.call.result) +const hasExpandable = computed(() => + description.value.length > 0 || prompt.value.length > 0 || !!props.call.result +) // Brief for body (only when no topics to show) const descBrief = computed(() => { @@ -143,7 +140,7 @@ const hasBody = computed(() => @@ -245,7 +221,9 @@ const hasBody = computed(() => padding: 0.3rem 0.6rem; background: transparent; min-height: 28px; + cursor: pointer; } +.card-header:hover { background: color-mix(in srgb, var(--card-color) 4%, transparent); } .card-icon { display: flex; align-items: center; color: color-mix(in srgb, var(--card-color) 60%, transparent); flex-shrink: 0; } .task-card.error .card-icon { color: rgba(239, 68, 68, 0.6); } diff --git a/frontend/src/components/transcript-debug/toolCards/WriteCard.vue b/frontend/src/components/transcript-debug/toolCards/WriteCard.vue index 4fc3cd5..188ba1f 100644 --- a/frontend/src/components/transcript-debug/toolCards/WriteCard.vue +++ b/frontend/src/components/transcript-debug/toolCards/WriteCard.vue @@ -25,8 +25,7 @@ const ext = computed(() => { const isError = computed(() => props.call.result?.isError ?? false) -const contentExpanded = ref(false) -const resultExpanded = ref(false) +const expanded = ref(false) const highlightedContent = computed(() => highlightCode(content.value, ext.value || undefined)) @@ -35,7 +34,7 @@ const lineCount = computed(() => content.value.split('\n').length) @@ -93,7 +78,9 @@ const lineCount = computed(() => content.value.split('\n').length) padding: 0.3rem 0.6rem; background: transparent; min-height: 28px; + cursor: pointer; } +.card-header:hover { background: rgba(34, 197, 94, 0.04); } .card-icon { display: flex; align-items: center; color: rgba(34, 197, 94, 0.6); flex-shrink: 0; } .write-card.error .card-icon { color: rgba(239, 68, 68, 0.6); }