diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa9122cb..0d7aa76c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,11 @@
## [Unreleased]
+### Added
+- Added feature to close editor tab on middle click ([support#758]).
+
+[support#758]: https://github.com/pybricks/support/issues/758
+
## [2.0.0-beta.8] - 2022-10-25
### Fixed
diff --git a/src/editor/Editor.test.tsx b/src/editor/Editor.test.tsx
index 4cef6a18..7a939776 100644
--- a/src/editor/Editor.test.tsx
+++ b/src/editor/Editor.test.tsx
@@ -81,6 +81,22 @@ describe('Editor', () => {
expect(dispatch).toHaveBeenCalledWith(editorCloseFile(testFile.uuid));
});
+
+ it('should dispatch close action when tab is middle clicked', async () => {
+ jest.mocked(useFileStorageMetadata).mockReturnValue([testFile]);
+ jest.mocked(useFileStoragePath).mockReturnValue(testFile.path);
+
+ const [user, editor, dispatch] = testRender(, {
+ editor: { openFileUuids: [testFile.uuid] },
+ });
+
+ await user.pointer({
+ keys: '[MouseMiddle]',
+ target: editor.getByRole('tab', { name: 'test.file' }),
+ });
+
+ expect(dispatch).toHaveBeenCalledWith(editorCloseFile(testFile.uuid));
+ });
});
describe('context menu', () => {
diff --git a/src/editor/Editor.tsx b/src/editor/Editor.tsx
index 5f6348ce..1d39a1de 100644
--- a/src/editor/Editor.tsx
+++ b/src/editor/Editor.tsx
@@ -265,6 +265,18 @@ const EditorTabs: React.VoidFunctionComponent = ({ onChange })
[dispatch],
);
+ // close tab when middle-clicked
+ const handleMouseDown = useCallback(
+ (e: React.MouseEvent, uuid: UUID) => {
+ if (e.button === 1) {
+ dispatch(editorCloseFile(uuid));
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ },
+ [dispatch],
+ );
+
const tabsRef = useRef(null);
// HACK: call private Tabs method to fix selection indicator animation when
@@ -287,6 +299,7 @@ const EditorTabs: React.VoidFunctionComponent = ({ onChange })
key={uuid}
id={uuid}
onKeyDown={(e) => handleKeyDown(e, uuid)}
+ onMouseDown={(e) => handleMouseDown(e, uuid)}
>