@@ -637,8 +637,16 @@ function SensorStreamControls({
637637 onStartSensorStreaming,
638638 onStopSensorStreaming,
639639} : SensorStreamControlsProps ) {
640+ // Each sensor module is collapsed by default; the play button stays visible.
641+ const [ expandedSensors , setExpandedSensors ] = useState < Set < string > > ( new Set ( ) )
642+ const toggleSensor = ( sensorId : string ) => setExpandedSensors ( prev => {
643+ const next = new Set ( prev )
644+ next . has ( sensorId ) ? next . delete ( sensorId ) : next . add ( sensorId )
645+ return next
646+ } )
647+
640648 return (
641- < div className = "space-y-3 " >
649+ < div className = "space-y-1.5 " >
642650 { sensors . map ( ( sensor ) => {
643651 const sensorStreamConfigs = streamsBySensor [ sensor . sensor_id ] || [ ]
644652 if ( sensorStreamConfigs . length === 0 ) return null
@@ -651,6 +659,7 @@ function SensorStreamControls({
651659 const sensorConfig = sensorConfigs [ sensor . sensor_id ]
652660
653661 const canStartSensor = hasEnabledSensorStreams && streamingMode !== 'pipeline'
662+ const isExpanded = expandedSensors . has ( sensor . sensor_id )
654663
655664 const computeCommonOptions = ( ) => {
656665 const profiles = sensor . supported_stream_profiles
@@ -677,15 +686,26 @@ function SensorStreamControls({
677686 const { resolutions : availableResolutions , fps : availableFps } = computeCommonOptions ( )
678687
679688 return (
680- < div key = { sensor . sensor_id } className = "bg-gray-800/50 rounded-lg p-2" >
681- { /* Sensor header with per-sensor start button */ }
682- < div className = "flex items-center justify-between mb-2" >
683- < div className = "flex items-center gap-2" >
684- < span className = "text-sm font-medium text-gray-300" > { sensor . name } </ span >
689+ < div key = { sensor . sensor_id } className = "bg-gray-800/50 rounded-lg px-2 py-1" >
690+ { /* Sensor header: collapse toggle (name) on the left, start button always visible on the right */ }
691+ < div className = { `flex items-center justify-between ${ isExpanded ? 'mb-2' : '' } ` } >
692+ < button
693+ onClick = { ( ) => toggleSensor ( sensor . sensor_id ) }
694+ className = "flex items-center gap-2 flex-1 min-w-0 text-left"
695+ aria-expanded = { isExpanded }
696+ title = { isExpanded ? 'Collapse' : 'Expand stream settings' }
697+ >
698+ < svg
699+ className = { `w-3 h-3 shrink-0 text-gray-400 transition-transform ${ isExpanded ? 'rotate-90' : '' } ` }
700+ fill = "none" stroke = "currentColor" viewBox = "0 0 24 24"
701+ >
702+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M9 5l7 7-7 7" />
703+ </ svg >
704+ < span className = "text-sm font-medium text-gray-300 truncate" > { sensor . name } </ span >
685705 { isSensorStreaming && (
686- < span className = "w-2 h-2 bg-green-500 rounded-full animate-pulse" />
706+ < span className = "w-2 h-2 bg-green-500 rounded-full animate-pulse shrink-0 " />
687707 ) }
688- </ div >
708+ </ button >
689709 < button
690710 onClick = { ( ) => isSensorStreaming
691711 ? onStopSensorStreaming ( sensor . sensor_id )
@@ -715,6 +735,7 @@ function SensorStreamControls({
715735 </ div >
716736 ) }
717737
738+ { isExpanded && ( < >
718739 { sensorConfig && ! sensorConfig . isMotionSensor && (
719740 < div className = "mb-2 flex items-center gap-2 text-xs" >
720741 < div className = "flex items-center gap-1" >
@@ -765,6 +786,7 @@ function SensorStreamControls({
765786 />
766787 ) ) }
767788 </ div >
789+ </ > ) }
768790 </ div >
769791 )
770792 } ) }
0 commit comments