Use the separator as border between roomlist and main panel (#33598)

* Remove border from roomlist container

The separator will act as the border so we no longer need the roomlist
border.

* Use pointer events to detect click event

Otherwise the onClick handler would run when you resize the panel.

* Support showing the border in separator

* Update tests

* Disable double click behaviour on separator

* Fix screenshot tests failing
This commit is contained in:
R Midhun Suresh
2026-05-26 11:22:41 +01:00
committed by GitHub
parent 6f549c0672
commit bc7ac39d5b
19 changed files with 155 additions and 58 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 13 KiB

@@ -8,5 +8,4 @@
.mx_RoomListPanel {
background-color: var(--cpd-color-bg-canvas-default);
height: 100%;
border-right: 1px solid var(--cpd-color-bg-subtle-primary);
}
@@ -47,8 +47,15 @@ export class ResizerViewModel
*/
private panelHandle?: PanelImperativeHandle;
/**
* Needed to distinguish between a drag and a click on the separator.
*/
private readonly mouseClickHandler: MouseClickHandler;
public constructor() {
super(undefined, getInitialState());
// Run onSeparatorClick when the separator is clicked.
this.mouseClickHandler = new MouseClickHandler(this.onSeparatorClick);
}
public onLeftPanelResize = debounce((panelSize: PanelSize): void => {
@@ -79,13 +86,25 @@ export class ResizerViewModel
this.panelHandle = handle;
};
public onSeparatorClick = (): void => {
private onSeparatorClick = (): void => {
if (this.panelHandle?.isCollapsed()) {
const lastSize = SettingsStore.getValue("RoomList.panelSize");
this.panelHandle.resize(`${lastSize ?? 100}%`);
}
};
public onPointerUp = (): void => {
this.mouseClickHandler.onPointerUp();
};
public onPointerMove = (): void => {
this.mouseClickHandler.onPointerMove();
};
public onPointerDown = (): void => {
this.mouseClickHandler.onPointerDown();
};
public onFocus = (): void => {
/**
* The intention here is to make the separator visible when it is focused by keyboard
@@ -108,3 +127,26 @@ export class ResizerViewModel
this.snapshot.merge({ isFocusedViaKeyboard: false });
};
}
/**
* Dragging the separator will emit a click event.
* This class uses pointer event handlers to distinguish between a drag and a click
* on the separator.
*/
class MouseClickHandler {
public constructor(private readonly onClick: () => void) {}
private isResize = false;
public onPointerUp = (): void => {
if (!this.isResize) this.onClick();
};
public onPointerDown = (): void => {
this.isResize = false;
};
public onPointerMove = (): void => {
this.isResize = true;
};
}
@@ -63,12 +63,33 @@ describe("LeftPanelResizerViewModel", () => {
});
});
it("should noop on onSeparatorClick() when handle is not yet set", () => {
it("should noop on click when handle is not yet set", () => {
const vm = new ResizerViewModel();
expect(() => vm.onSeparatorClick()).not.toThrow();
expect(() => {
// Click
vm.onPointerDown();
vm.onPointerUp();
}).not.toThrow();
});
describe("should expand panel on onSeparatorClick()", () => {
it("should noop on mouse drag", () => {
const vm = new ResizerViewModel();
SettingsStore.setValue("RoomList.panelSize", null, SettingLevel.DEVICE, 34);
const mockHandle = {
resize: jest.fn(),
isCollapsed: jest.fn().mockReturnValue(true),
} as unknown as PanelImperativeHandle;
vm.setPanelHandle(mockHandle);
// Simulate drag
vm.onPointerDown();
vm.onPointerMove();
vm.onPointerUp();
expect(mockHandle.resize).not.toHaveBeenCalledWith("34%");
});
describe("should expand panel on click()", () => {
it("to last non-zero width that the user set", () => {
const vm = new ResizerViewModel();
SettingsStore.setValue("RoomList.panelSize", null, SettingLevel.DEVICE, 34);
@@ -78,7 +99,9 @@ describe("LeftPanelResizerViewModel", () => {
} as unknown as PanelImperativeHandle;
vm.setPanelHandle(mockHandle);
vm.onSeparatorClick();
// Simulate click
vm.onPointerDown();
vm.onPointerUp();
expect(mockHandle.resize).toHaveBeenCalledWith("34%");
});
@@ -91,7 +114,9 @@ describe("LeftPanelResizerViewModel", () => {
} as unknown as PanelImperativeHandle;
vm.setPanelHandle(mockHandle);
vm.onSeparatorClick();
// Simulate click
vm.onPointerDown();
vm.onPointerUp();
expect(mockHandle.resize).toHaveBeenCalledWith("100%");
});