feat: Add FloatingTranscriptDebug with pixel art dark theme
Floating chat window reusing ChatContainer with draggable/resizable window, agent/session selector overlay, and pixel art decorations (galaxy, minecraft dirt block, LED strip) on black transparent backdrop.
This commit is contained in:
@@ -6,6 +6,7 @@ import TorchButton from './components/TorchButton.vue'
|
||||
import FloatingTerminal from './components/FloatingTerminal.vue'
|
||||
import FloatingResponse from './components/FloatingResponse.vue'
|
||||
import FloatingVoice from './components/FloatingVoice.vue'
|
||||
import FloatingTranscriptDebug from './components/FloatingTranscriptDebug.vue'
|
||||
import AgentBar from './components/AgentBar.vue'
|
||||
import PwaInstallBanner from './components/PwaInstallBanner.vue'
|
||||
import HooksApprovalModal from './components/HooksApprovalModal.vue'
|
||||
@@ -23,6 +24,7 @@ const route = useRoute()
|
||||
const router = useRouter()
|
||||
const showTerminal = ref(false)
|
||||
const showVoice = ref(false)
|
||||
const showTranscriptDebug = ref(false)
|
||||
const showDebugConsole = ref(false)
|
||||
const toolbarVisible = ref(true)
|
||||
const forceWco = ref(false)
|
||||
@@ -450,7 +452,7 @@ watch(() => route.name, (newPage) => {
|
||||
'session-start': showSessionStart,
|
||||
notification: showNotification,
|
||||
'tool-flash': showToolFlash,
|
||||
'sheet-open': showTerminal || showVoice,
|
||||
'sheet-open': showTerminal || showVoice || showTranscriptDebug,
|
||||
'keyboard-visible': keyboardVisible
|
||||
}"
|
||||
@click="showTerminal = !showTerminal"
|
||||
@@ -521,10 +523,22 @@ watch(() => route.name, (newPage) => {
|
||||
</template>
|
||||
</button>
|
||||
|
||||
<!-- Transcript Debug FAB Button -->
|
||||
<button
|
||||
class="transcript-fab"
|
||||
:class="{ active: showTranscriptDebug, 'sheet-open': showTerminal || showVoice || showTranscriptDebug, 'keyboard-visible': keyboardVisible }"
|
||||
@click="showTranscriptDebug = !showTranscriptDebug"
|
||||
title="Transcript Debug"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Voice FAB Button -->
|
||||
<button
|
||||
class="voice-fab"
|
||||
:class="{ active: showVoice, 'sheet-open': showTerminal || showVoice, 'ptt-active': voicePTTActive, 'keyboard-visible': keyboardVisible }"
|
||||
:class="{ active: showVoice, 'sheet-open': showTerminal || showVoice || showTranscriptDebug, 'ptt-active': voicePTTActive, 'keyboard-visible': keyboardVisible }"
|
||||
@click="handleVoiceFabClick"
|
||||
@touchstart="handleVoiceFabTouchStart"
|
||||
@touchend="handleVoiceFabTouchEnd"
|
||||
@@ -552,6 +566,9 @@ watch(() => route.name, (newPage) => {
|
||||
<!-- Floating Voice Input -->
|
||||
<FloatingVoice ref="voiceRef" v-model="showVoice" />
|
||||
|
||||
<!-- Floating Transcript Debug -->
|
||||
<FloatingTranscriptDebug v-model="showTranscriptDebug" />
|
||||
|
||||
<!-- Global Hooks Approval Modal -->
|
||||
<HooksApprovalModal />
|
||||
|
||||
@@ -1309,6 +1326,49 @@ watch(() => route.name, (newPage) => {
|
||||
50% { box-shadow: 0 0 50px rgba(249, 115, 22, 0.9); }
|
||||
}
|
||||
|
||||
/* Transcript Debug FAB */
|
||||
.transcript-fab {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 80px;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 4px;
|
||||
background: rgba(15, 15, 20, 0.85);
|
||||
color: #818cf8;
|
||||
border: 1px solid rgba(99, 102, 241, 0.2);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
|
||||
transition: all 0.2s ease;
|
||||
z-index: 9998;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
touch-action: manipulation;
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.transcript-fab:hover {
|
||||
transform: translateY(-2px);
|
||||
border-color: rgba(99, 102, 241, 0.4);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5), 0 0 12px rgba(99, 102, 241, 0.15);
|
||||
color: #a5b4fc;
|
||||
}
|
||||
|
||||
.transcript-fab.active {
|
||||
background: rgba(99, 102, 241, 0.15);
|
||||
border-color: rgba(99, 102, 241, 0.4);
|
||||
color: #c7d2fe;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4), 0 0 8px rgba(99, 102, 241, 0.2);
|
||||
}
|
||||
|
||||
.transcript-fab.active:hover {
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5), 0 0 12px rgba(99, 102, 241, 0.3);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.terminal-fab {
|
||||
bottom: 80px;
|
||||
@@ -1340,28 +1400,39 @@ watch(() => route.name, (newPage) => {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.transcript-fab {
|
||||
bottom: 80px;
|
||||
left: 68px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile: FABs above bottom sheets */
|
||||
@media (max-width: 1024px) and (pointer: coarse) {
|
||||
.terminal-fab,
|
||||
.voice-fab {
|
||||
.voice-fab,
|
||||
.transcript-fab {
|
||||
z-index: 10001;
|
||||
transition: bottom 0.25s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s ease;
|
||||
}
|
||||
|
||||
.terminal-fab.sheet-open,
|
||||
.voice-fab.sheet-open {
|
||||
.voice-fab.sheet-open,
|
||||
.transcript-fab.sheet-open {
|
||||
bottom: calc(15vh + 100px);
|
||||
}
|
||||
|
||||
.terminal-fab.keyboard-visible,
|
||||
.voice-fab.keyboard-visible {
|
||||
.voice-fab.keyboard-visible,
|
||||
.transcript-fab.keyboard-visible {
|
||||
bottom: 35vh;
|
||||
}
|
||||
|
||||
.terminal-fab.keyboard-visible.sheet-open,
|
||||
.voice-fab.keyboard-visible.sheet-open {
|
||||
.voice-fab.keyboard-visible.sheet-open,
|
||||
.transcript-fab.keyboard-visible.sheet-open {
|
||||
bottom: 45vh;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user