Skip to content

Commit 332c65a

Browse files
MarkoVcodeclaude
andcommitted
Prevent collapsing all channels - ensure at least one remains expanded
Resolves issue where collapsing all channels would result in an empty window with no way to recover. The last remaining expanded channel is now protected from being collapsed. Changes: - Added logic in toggleChannelCollapse to check if collapsing would hide all channels - If attempting to collapse the last expanded channel, the action is prevented - Added disabled state to collapse button when it's the last expanded channel - Button shows tooltip "Cannot collapse last channel" when disabled - Added CSS for disabled button state (reduced opacity, not-allowed cursor) - Expanding channels is always allowed regardless of state This ensures users always have at least one visible channel to interact with and prevents the unrecoverable empty window state. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent c847596 commit 332c65a

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

benchmesh-serial-service/frontend/src/ui/workbench/EditorArea/MosaicInstrumentWindow.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,19 @@ export const MosaicInstrumentWindow: React.FC<MosaicInstrumentWindowProps> = ({
8888
const toggleChannelCollapse = (channelPath: string) => {
8989
setCollapsedChannels(prev => {
9090
const newSet = new Set(prev);
91+
92+
// Calculate total number of channels across all classes
93+
const totalChannels = classesToDisplay.reduce((sum: number, c: any) => sum + c.channels.length, 0);
94+
9195
if (newSet.has(channelPath)) {
96+
// Expanding - always allow
9297
newSet.delete(channelPath);
9398
} else {
99+
// Collapsing - prevent if this is the last expanded channel
100+
if (newSet.size >= totalChannels - 1) {
101+
// Would collapse all channels - prevent this
102+
return prev;
103+
}
94104
newSet.add(channelPath);
95105
}
96106
return newSet;
@@ -118,6 +128,10 @@ export const MosaicInstrumentWindow: React.FC<MosaicInstrumentWindowProps> = ({
118128
const channelColor = channelColors[channelNum] || '#808080'; // Gray fallback
119129
const isCollapsed = collapsedChannels.has(channelPath);
120130

131+
// Calculate if this is the last expanded channel
132+
const totalChannels = classesToDisplay.reduce((sum: number, cls: any) => sum + cls.channels.length, 0);
133+
const isLastExpanded = !isCollapsed && collapsedChannels.size >= totalChannels - 1;
134+
121135
return (
122136
<div
123137
key={channelPath}
@@ -136,7 +150,14 @@ export const MosaicInstrumentWindow: React.FC<MosaicInstrumentWindowProps> = ({
136150
<button
137151
className="channel-collapse-toggle"
138152
onClick={() => toggleChannelCollapse(channelPath)}
139-
title={isCollapsed ? 'Expand channel' : 'Collapse channel'}
153+
disabled={isLastExpanded}
154+
title={
155+
isCollapsed
156+
? 'Expand channel'
157+
: isLastExpanded
158+
? 'Cannot collapse last channel'
159+
: 'Collapse channel'
160+
}
140161
>
141162
{isCollapsed ? <VscChevronDown size={16} /> : <VscChevronUp size={16} />}
142163
</button>

benchmesh-serial-service/frontend/src/ui/workbench/EditorArea/editor.css

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,16 @@
241241
transition: all 0.2s ease;
242242
}
243243

244-
.channel-collapse-toggle:hover {
244+
.channel-collapse-toggle:hover:not(:disabled) {
245245
opacity: 1;
246246
background-color: var(--activity-bar-hover);
247247
}
248248

249+
.channel-collapse-toggle:disabled {
250+
opacity: 0.3;
251+
cursor: not-allowed;
252+
}
253+
249254
/* Collapsed channel state */
250255
.channel-column--collapsed {
251256
flex: 0 0 40px !important;

0 commit comments

Comments
 (0)