Implement new separator design (#33599)
* Remove `onFocus` and `onBlur` handlers react-resizable-panels fixed the issue where focus-visible was not working as expected, so we no longer need this bit of code. * Implement new hover/focus separator * Collapse the panel when clicking on the new focus separator * Remove `isFocusedViaKeyboard` from snapshot * Update tests and storybook * Expand panel only on double click * Add animation * Fix tests * Don't render border when type is bar * Single click to expand, double click to collapse * Change focus separator color
This commit is contained in:
@@ -15,7 +15,6 @@ import {
|
||||
type ResizerViewSnapshot,
|
||||
} from "@element-hq/web-shared-components";
|
||||
import { debounce } from "lodash";
|
||||
import whatInput from "what-input";
|
||||
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import { SettingLevel } from "../../settings/SettingLevel";
|
||||
@@ -25,13 +24,11 @@ function getInitialState(): ResizerViewSnapshot {
|
||||
return {
|
||||
isCollapsed: true,
|
||||
initialSize: 0,
|
||||
isFocusedViaKeyboard: false,
|
||||
};
|
||||
}
|
||||
return {
|
||||
isCollapsed: false,
|
||||
initialSize: SettingsStore.getValue("RoomList.panelSize") ?? undefined,
|
||||
isFocusedViaKeyboard: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,12 +84,18 @@ export class ResizerViewModel
|
||||
};
|
||||
|
||||
private onSeparatorClick = (): void => {
|
||||
// When panel is collapsed, single click should expand the panel.
|
||||
if (this.panelHandle?.isCollapsed()) {
|
||||
const lastSize = SettingsStore.getValue("RoomList.panelSize");
|
||||
this.panelHandle.resize(`${lastSize ?? 100}%`);
|
||||
}
|
||||
};
|
||||
|
||||
public onDoubleClick = (): void => {
|
||||
// When the panel is expanded, double click should collapse.
|
||||
if (!this.panelHandle?.isCollapsed()) this.panelHandle?.collapse();
|
||||
};
|
||||
|
||||
public onPointerUp = (): void => {
|
||||
this.mouseClickHandler.onPointerUp();
|
||||
};
|
||||
@@ -104,28 +107,6 @@ export class ResizerViewModel
|
||||
public onPointerDown = (): void => {
|
||||
this.mouseClickHandler.onPointerDown();
|
||||
};
|
||||
|
||||
public onFocus = (): void => {
|
||||
/**
|
||||
* The intention here is to make the separator visible when it is focused by keyboard
|
||||
* navigation i.e tabbing through the app.
|
||||
*
|
||||
* There's a good reason to take this approach instead of just relying on the focus-visible
|
||||
* selector:
|
||||
* When exactly an element gets focus-visible is determined by browser heuristics and usually
|
||||
* interacting with the mouse will not give an element focus-visible.
|
||||
* However with this separator on chrome, mouse interaction occasionally gives it focus-visible.
|
||||
* The leads to flakey separator behaviour.
|
||||
*/
|
||||
const currentNavigation = whatInput.ask();
|
||||
if (currentNavigation === "keyboard") {
|
||||
this.snapshot.merge({ isFocusedViaKeyboard: true });
|
||||
}
|
||||
};
|
||||
|
||||
public onBlur = (): void => {
|
||||
this.snapshot.merge({ isFocusedViaKeyboard: false });
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
import { waitFor } from "jest-matrix-react";
|
||||
import { type PanelImperativeHandle } from "@element-hq/web-shared-components";
|
||||
import whatInput from "what-input";
|
||||
|
||||
import { ResizerViewModel } from "../../../src/viewmodels/structures/ResizerViewModel";
|
||||
import SettingsStore from "../../../src/settings/SettingsStore";
|
||||
@@ -27,7 +26,6 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
expect(vm.getSnapshot()).toStrictEqual({
|
||||
isCollapsed: true,
|
||||
initialSize: 0,
|
||||
isFocusedViaKeyboard: false,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,7 +35,6 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
expect(vm.getSnapshot()).toStrictEqual({
|
||||
isCollapsed: false,
|
||||
initialSize: 34,
|
||||
isFocusedViaKeyboard: false,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -46,7 +43,6 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
expect(vm.getSnapshot()).toStrictEqual({
|
||||
isCollapsed: false,
|
||||
initialSize: undefined,
|
||||
isFocusedViaKeyboard: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -89,7 +85,7 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
expect(mockHandle.resize).not.toHaveBeenCalledWith("34%");
|
||||
});
|
||||
|
||||
describe("should expand panel on click()", () => {
|
||||
describe("should expand panel on double click when panel is collapsed", () => {
|
||||
it("to last non-zero width that the user set", () => {
|
||||
const vm = new ResizerViewModel();
|
||||
SettingsStore.setValue("RoomList.panelSize", null, SettingLevel.DEVICE, 34);
|
||||
@@ -98,11 +94,9 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
isCollapsed: jest.fn().mockReturnValue(true),
|
||||
} as unknown as PanelImperativeHandle;
|
||||
vm.setPanelHandle(mockHandle);
|
||||
|
||||
// Simulate click
|
||||
vm.onPointerDown();
|
||||
vm.onPointerUp();
|
||||
|
||||
expect(mockHandle.resize).toHaveBeenCalledWith("34%");
|
||||
});
|
||||
|
||||
@@ -113,22 +107,23 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
isCollapsed: jest.fn().mockReturnValue(true),
|
||||
} as unknown as PanelImperativeHandle;
|
||||
vm.setPanelHandle(mockHandle);
|
||||
|
||||
// Simulate click
|
||||
vm.onPointerDown();
|
||||
vm.onPointerUp();
|
||||
|
||||
expect(mockHandle.resize).toHaveBeenCalledWith("100%");
|
||||
});
|
||||
});
|
||||
|
||||
it("should set isFocusedViaKeyboard state correctly", () => {
|
||||
whatInput.ask = jest.fn().mockReturnValue("keyboard");
|
||||
it("should collapse panel on click when panel is expanded", () => {
|
||||
const vm = new ResizerViewModel();
|
||||
vm.onFocus();
|
||||
expect(vm.getSnapshot().isFocusedViaKeyboard).toStrictEqual(true);
|
||||
vm.onBlur();
|
||||
expect(vm.getSnapshot().isFocusedViaKeyboard).toStrictEqual(false);
|
||||
const mockHandle = {
|
||||
collapse: jest.fn(),
|
||||
isCollapsed: jest.fn().mockReturnValue(false),
|
||||
} as unknown as PanelImperativeHandle;
|
||||
vm.setPanelHandle(mockHandle);
|
||||
|
||||
vm.onDoubleClick();
|
||||
expect(mockHandle.collapse).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should resize to nearest whole number", () => {
|
||||
|
||||
Reference in New Issue
Block a user