implement collapse spine, focus mode, keyboard shortcuts, context rail

Collapsed side panels render as a 12px vertical spine with rotated
label, hover highlight, and badge dot (D-051). Focus mode snapshots
and restores the full layout arrangement (D-052). Fourteen new
commands in the default-layout extension: collapse toggles
(Ctrl+Shift+1/3), panel focus (Ctrl+1/2/3), focus mode (Ctrl+.),
sidebar section switching (Alt+1-5), Escape dismiss (D-054). Right
panel gets a bottom icon rail matching the sidebar pattern (D-047).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-22 22:47:45 +02:00
co-authored by Claude Opus 4.6
parent 9e3a13e7f7
commit 11eb91effe
7 changed files with 456 additions and 46 deletions
@@ -46,5 +46,59 @@ void main() {
expect(r.definitionFor(Slots.sidebar), isNotNull);
expect(r.definitionFor(Slots.statusbar), isNotNull);
});
test('setCollapsed toggles collapsed state', () {
final a = LayoutArrangement()..applyPreset(classicPreset());
expect(a.isCollapsed(Slots.sidebar), false);
a.setCollapsed(Slots.sidebar, true);
expect(a.isCollapsed(Slots.sidebar), true);
expect(a.isVisible(Slots.sidebar), true);
});
test('toggleCollapsed flips collapsed flag', () {
final a = LayoutArrangement()..applyPreset(classicPreset());
a.toggleCollapsed(Slots.sidebar);
expect(a.isCollapsed(Slots.sidebar), true);
a.toggleCollapsed(Slots.sidebar);
expect(a.isCollapsed(Slots.sidebar), false);
});
test('enterFocusMode hides all slots except the focused one', () {
final a = LayoutArrangement()..applyPreset(classicPreset());
a.enterFocusMode(Slots.workspace);
expect(a.isInFocusMode, true);
expect(a.focusModeSlot, Slots.workspace);
expect(a.isVisible(Slots.workspace), true);
expect(a.isVisible(Slots.sidebar), false);
expect(a.isVisible(Slots.contextPanel), false);
});
test('exitFocusMode restores prior layout', () {
final a = LayoutArrangement()..applyPreset(classicPreset());
a.setCollapsed(Slots.sidebar, true);
a.setSize(Slots.contextPanel, 300);
a.enterFocusMode(Slots.workspace);
a.exitFocusMode();
expect(a.isInFocusMode, false);
expect(a.isVisible(Slots.sidebar), true);
expect(a.isCollapsed(Slots.sidebar), true);
expect(a.sizeOf(Slots.contextPanel), 300);
});
test('toggleFocusMode enters then exits', () {
final a = LayoutArrangement()..applyPreset(classicPreset());
a.toggleFocusMode(Slots.workspace);
expect(a.isInFocusMode, true);
a.toggleFocusMode(Slots.workspace);
expect(a.isInFocusMode, false);
expect(a.isVisible(Slots.sidebar), true);
});
test('applyPreset clears focus mode', () {
final a = LayoutArrangement()..applyPreset(classicPreset());
a.enterFocusMode(Slots.workspace);
a.applyPreset(classicPreset());
expect(a.isInFocusMode, false);
});
});
}