diff --git a/lib/kernel/src/panels/drag_resize.dart b/lib/kernel/src/panels/drag_resize.dart index b1f578ca..c1cdf688 100644 --- a/lib/kernel/src/panels/drag_resize.dart +++ b/lib/kernel/src/panels/drag_resize.dart @@ -119,15 +119,10 @@ class _DragResizeHandleState extends State { }; } - /// Apply a raw delta in the natural axis direction. The drag handler - /// inverts the sign for context-panel because its handle sits on the - /// left edge of the right-anchored slot; arrow keys follow the same - /// convention so right-arrow always moves the boundary rightward. void _bump(double rawDelta) { final current = widget.arrangement.sizeOf(widget.slot); if (current == null) return; - final delta = widget.slot == Slots.contextPanel ? -rawDelta : rawDelta; - widget.arrangement.setSize(widget.slot, current + delta); + widget.arrangement.setSize(widget.slot, bumpedSlotSize(slot: widget.slot, current: current, rawDelta: rawDelta)); } void _onDown(PointerDownEvent e) { @@ -154,3 +149,17 @@ class _BumpIntent extends Intent { const _BumpIntent(this.delta); final double delta; } + +/// Apply a raw delta in the natural axis direction. Drag and arrow +/// keys both call this so the keyboard mirrors the drag: positive +/// delta = right/down. Context-panel sits on the right edge of the +/// app, so we flip the sign there — right-arrow should *shrink* it, +/// matching how dragging the left-edge handle rightward works. +double bumpedSlotSize({ + required SlotId slot, + required double current, + required double rawDelta, +}) { + final delta = slot == Slots.contextPanel ? -rawDelta : rawDelta; + return current + delta; +} diff --git a/test/kernel/src/panels/drag_resize_test.dart b/test/kernel/src/panels/drag_resize_test.dart index 1d6f5f72..b0d1be3f 100644 --- a/test/kernel/src/panels/drag_resize_test.dart +++ b/test/kernel/src/panels/drag_resize_test.dart @@ -118,6 +118,48 @@ void main() { semHandle.dispose(); }); + testWidgets('contextPanel slider Semantics label matches the slot', (tester) async { + final arr = LayoutArrangement(); + arr.applyPreset(const LayoutPresetContribution( + id: 'test-preset', + displayName: 'Test', + slots: [ + LayoutSlot(slot: Slots.contextPanel, position: SlotPosition.right, defaultSize: 320), + ], + )); + final semHandle = tester.ensureSemantics(); + await tester.pumpWidget(harness( + f, + Center( + child: SizedBox( + width: 40, + height: 200, + child: DragResizeHandle( + arrangement: arr, + slot: Slots.contextPanel, + axis: Axis.horizontal, + ), + ), + ), + )); + await tester.pumpAndSettle(); + final data = tester.getSemantics(find.byType(DragResizeHandle)); + expect(data.label, 'Context panel width'); + expect(data.value, '320 pixels'); + semHandle.dispose(); + }); + + test('bumpedSlotSize keeps natural sign for left-anchored slots', () { + expect(bumpedSlotSize(slot: Slots.sidebar, current: 200, rawDelta: 10), 210); + expect(bumpedSlotSize(slot: Slots.sidebar, current: 200, rawDelta: -10), 190); + expect(bumpedSlotSize(slot: Slots.workspace, current: 500, rawDelta: 50), 550); + }); + + test('bumpedSlotSize flips sign for the right-anchored context panel', () { + expect(bumpedSlotSize(slot: Slots.contextPanel, current: 200, rawDelta: 10), 190); + expect(bumpedSlotSize(slot: Slots.contextPanel, current: 200, rawDelta: -10), 210); + }); + testWidgets('hovered state flips the line colour without throwing', (tester) async { final arr = LayoutArrangement(); arr.applyPreset(const LayoutPresetContribution(