implement editor-above-Claude split in workspace

Editor opens above Claude via Ctrl+E with a draggable divider at
35% height (clamped 15-70%). Ctrl+W or Escape closes it. The
workspace no longer renders a tab bar — Claude is the always-visible
primary surface per D-047/D-048; the editor is a split overlay
per D-049, not a tab. The _WorkspaceSlot separates editor from
primary content tabs and renders them as a vertical split when the
editor is open.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-22 23:01:02 +02:00
co-authored by Claude Opus 4.6
parent 3f19eca059
commit 43901bc387
5 changed files with 207 additions and 0 deletions
@@ -81,6 +81,21 @@ class DefaultLayoutExtension extends ClideExtension {
defaultBinding: 'escape',
run: _exitFocusMode,
),
// Editor split (D-049, D-054)
CommandContribution(
id: 'editor.open',
command: 'editor.open',
title: 'Open Editor',
defaultBinding: 'ctrl+e',
run: _openEditor,
),
CommandContribution(
id: 'editor.close',
command: 'editor.close',
title: 'Close Editor',
defaultBinding: 'ctrl+w',
run: _closeEditor,
),
// Sidebar section switching (D-054): alt+1 through alt+5
for (var i = 0; i < 5; i++)
CommandContribution(
@@ -182,6 +197,10 @@ class DefaultLayoutExtension extends ClideExtension {
ctx.arrangement.exitFocusMode();
return IpcResponse.ok(id: '', data: {'focusMode': false});
}
if (ctx.arrangement.editorOpen) {
ctx.arrangement.closeEditor();
return IpcResponse.ok(id: '', data: {'editorOpen': false});
}
if (ctx.palette.isOpen) {
ctx.palette.toggle();
return IpcResponse.ok(id: '', data: {'palette': false});
@@ -189,6 +208,23 @@ class DefaultLayoutExtension extends ClideExtension {
return IpcResponse.ok(id: '', data: {});
}
Future<IpcResponse> _openEditor(List<String> args) async {
final ctx = _ctx;
if (ctx == null) return _notActivated();
ctx.arrangement.openEditor();
return IpcResponse.ok(id: '', data: {'editorOpen': true});
}
Future<IpcResponse> _closeEditor(List<String> args) async {
final ctx = _ctx;
if (ctx == null) return _notActivated();
if (ctx.arrangement.editorOpen) {
ctx.arrangement.closeEditor();
return IpcResponse.ok(id: '', data: {'editorOpen': false});
}
return IpcResponse.ok(id: '', data: {});
}
Future<IpcResponse> _switchSidebarSection(int index) async {
final ctx = _ctx;
if (ctx == null) return _notActivated();