@@ -74,6 +74,10 @@ interface RoundtableProps {
7474 readonly onPrevSlide ?: ( ) => void ;
7575 readonly onNextSlide ?: ( ) => void ;
7676 readonly onWhiteboardClose ?: ( ) => void ;
77+ readonly isPresenting ?: boolean ;
78+ readonly controlsVisible ?: boolean ;
79+ readonly onTogglePresentation ?: ( ) => void ;
80+ readonly onPresentationInteractionChange ?: ( active : boolean ) => void ;
7781}
7882
7983const DEFAULT_TEACHER_AVATAR = '/avatars/teacher.png' ;
@@ -131,6 +135,10 @@ export function Roundtable({
131135 onPrevSlide,
132136 onNextSlide,
133137 onWhiteboardClose,
138+ isPresenting,
139+ controlsVisible,
140+ onTogglePresentation,
141+ onPresentationInteractionChange,
134142} : RoundtableProps ) {
135143 const { t } = useI18n ( ) ;
136144 const ttsMuted = useSettingsStore ( ( s ) => s . ttsMuted ) ;
@@ -308,6 +316,18 @@ export function Roundtable({
308316 }
309317 } ;
310318
319+ const isPresentationInteractionActive = isInputOpen || isVoiceOpen || isRecording || isProcessing ;
320+
321+ useEffect ( ( ) => {
322+ onPresentationInteractionChange ?.( isPresentationInteractionActive ) ;
323+
324+ return ( ) => {
325+ if ( isPresentationInteractionActive ) {
326+ onPresentationInteractionChange ?.( false ) ;
327+ }
328+ } ;
329+ } , [ isPresentationInteractionActive , onPresentationInteractionChange ] ) ;
330+
311331 // Determine active speaking state and bubble ownership
312332 // Check if current speaker is a student agent (not teacher)
313333 const speakingStudent = speakingAgentId
@@ -387,46 +407,66 @@ export function Roundtable({
387407 } , [ playbackSpeed , setPlaybackSpeed ] ) ;
388408
389409 return (
390- < div className = "h-[192px] w-full flex flex-col relative z-10 border-t border-gray-100 dark:border-gray-800 bg-white/60 dark:bg-gray-800/60 backdrop-blur-md" >
410+ < div
411+ className = { cn (
412+ 'h-[192px] w-full flex flex-col relative z-10 transition-all duration-300' ,
413+ isPresenting && ! controlsVisible
414+ ? 'border-t border-transparent bg-transparent backdrop-blur-none'
415+ : 'border-t border-gray-100 dark:border-gray-800 bg-white/60 dark:bg-gray-800/60 backdrop-blur-md' ,
416+ ) }
417+ >
391418 { /* ── Toolbar strip — merged from CanvasArea ── */ }
392- < CanvasToolbar
393- className = "shrink-0 h-8 px-3 border-b border-gray-100/40 dark:border-gray-700/30"
394- currentSceneIndex = { currentSceneIndex }
395- scenesCount = { scenesCount }
396- engineState = {
397- engineMode === 'playing' || engineMode === 'live'
398- ? 'playing'
399- : engineMode === 'paused'
400- ? 'paused'
401- : 'idle'
402- }
403- isLiveSession = { isStreaming || isTopicPending || engineMode === 'live' }
404- whiteboardOpen = { whiteboardOpen }
405- sidebarCollapsed = { sidebarCollapsed }
406- chatCollapsed = { chatCollapsed }
407- onToggleSidebar = { onToggleSidebar }
408- onToggleChat = { onToggleChat }
409- onPrevSlide = { onPrevSlide ?? ( ( ) => { } ) }
410- onNextSlide = { onNextSlide ?? ( ( ) => { } ) }
411- onPlayPause = { onPlayPause ?? ( ( ) => { } ) }
412- onWhiteboardClose = { onWhiteboardClose ?? ( ( ) => { } ) }
413- showStopDiscussion = { showStopButton }
414- onStopDiscussion = { onStopDiscussion }
415- ttsEnabled = { ttsEnabled }
416- ttsMuted = { ttsMuted }
417- ttsVolume = { ttsVolume }
418- onToggleMute = { ( ) => ttsEnabled && setTTSMuted ( ! ttsMuted ) }
419- onVolumeChange = { ( v ) => setTTSVolume ( v ) }
420- autoPlayLecture = { autoPlayLecture }
421- onToggleAutoPlay = { ( ) => setAutoPlayLecture ( ! autoPlayLecture ) }
422- playbackSpeed = { playbackSpeed }
423- onCycleSpeed = { handleCycleSpeed }
424- />
425-
419+ < div
420+ className = { cn (
421+ 'transition-opacity duration-300' ,
422+ isPresenting && ! controlsVisible && 'opacity-0 pointer-events-none' ,
423+ ) }
424+ >
425+ < CanvasToolbar
426+ className = "shrink-0 h-8 px-3 border-b border-gray-100/40 dark:border-gray-700/30"
427+ currentSceneIndex = { currentSceneIndex }
428+ scenesCount = { scenesCount }
429+ engineState = {
430+ engineMode === 'playing' || engineMode === 'live'
431+ ? 'playing'
432+ : engineMode === 'paused'
433+ ? 'paused'
434+ : 'idle'
435+ }
436+ isLiveSession = { isStreaming || isTopicPending || engineMode === 'live' }
437+ whiteboardOpen = { whiteboardOpen }
438+ sidebarCollapsed = { sidebarCollapsed }
439+ chatCollapsed = { chatCollapsed }
440+ onToggleSidebar = { onToggleSidebar }
441+ onToggleChat = { onToggleChat }
442+ onPrevSlide = { onPrevSlide ?? ( ( ) => { } ) }
443+ onNextSlide = { onNextSlide ?? ( ( ) => { } ) }
444+ onPlayPause = { onPlayPause ?? ( ( ) => { } ) }
445+ onWhiteboardClose = { onWhiteboardClose ?? ( ( ) => { } ) }
446+ isPresenting = { isPresenting }
447+ onTogglePresentation = { onTogglePresentation }
448+ showStopDiscussion = { showStopButton }
449+ onStopDiscussion = { onStopDiscussion }
450+ ttsEnabled = { ttsEnabled }
451+ ttsMuted = { ttsMuted }
452+ ttsVolume = { ttsVolume }
453+ onToggleMute = { ( ) => ttsEnabled && setTTSMuted ( ! ttsMuted ) }
454+ onVolumeChange = { ( v ) => setTTSVolume ( v ) }
455+ autoPlayLecture = { autoPlayLecture }
456+ onToggleAutoPlay = { ( ) => setAutoPlayLecture ( ! autoPlayLecture ) }
457+ playbackSpeed = { playbackSpeed }
458+ onCycleSpeed = { handleCycleSpeed }
459+ />
460+ </ div >
426461 { /* ── Interaction area — three-column layout ── */ }
427462 < div className = "flex-1 flex items-stretch min-h-0" >
428463 { /* Left: Teacher identity */ }
429- < div className = "w-[90px] shrink-0 flex flex-col border-r border-gray-100/50 dark:border-gray-700/50 bg-white/40 dark:bg-gray-900/40 overflow-visible relative" >
464+ < div
465+ className = { cn (
466+ 'w-[90px] shrink-0 flex flex-col border-r border-gray-100/50 dark:border-gray-700/50 bg-white/40 dark:bg-gray-900/40 overflow-visible relative transition-opacity duration-300' ,
467+ isPresenting && ! controlsVisible && 'opacity-0 pointer-events-none' ,
468+ ) }
469+ >
430470 { /* Decorative Element (Top) */ }
431471 < div className = "absolute top-0 inset-x-0 h-16 bg-gradient-to-b from-purple-50/50 dark:from-purple-900/10 to-transparent pointer-events-none" />
432472 < div className = "absolute top-3 inset-x-0 flex flex-col items-center justify-center gap-1 opacity-10 pointer-events-none" >
@@ -1099,7 +1139,12 @@ export function Roundtable({
10991139 </ div >
11001140
11011141 { /* Right: Participants area */ }
1102- < div className = "w-[140px] shrink-0 flex flex-col py-3 border-l border-gray-100/50 dark:border-gray-700/50 bg-gray-50/30 dark:bg-gray-900/30 overflow-visible" >
1142+ < div
1143+ className = { cn (
1144+ 'w-[140px] shrink-0 flex flex-col py-3 border-l border-gray-100/50 dark:border-gray-700/50 bg-gray-50/30 dark:bg-gray-900/30 overflow-visible transition-opacity duration-300' ,
1145+ isPresenting && ! controlsVisible && 'opacity-0 pointer-events-none' ,
1146+ ) }
1147+ >
11031148 { /* Companion agent avatars — horizontal row, scrollable on overflow, arrows on hover */ }
11041149 < div className = "flex-none relative group/scroll" >
11051150 { /* Left arrow */ }
0 commit comments