From 65149798ef83c08d92dfc29d389f3ab672c2d902 Mon Sep 17 00:00:00 2001 From: keehar <54379749+spoisseroux@users.noreply.github.com> Date: Wed, 15 Jul 2026 04:52:43 -0400 Subject: [PATCH] Give the collapsed space panel separator clearance from the macOS traffic lights (#34243) * Space the collapsed space panel separator away from the macOS traffic lights On macOS the frameless window draws the traffic light buttons over the top of the space panel. The cluster is inset 9px and is roughly 52px wide, so it ends about 61px from the window edge. The collapsed space panel is 68px wide, which left its right-hand separator crowding the green button. Widen the collapsed panel to 76px on macOS so the separator gets about 15px of clearance, in line with the compound 4x spacing step. The rule is added to the styling already injected for the macOS title bar, so it only affects the desktop app on macOS and is removed in full screen along with the rest. Fixes https://github.com/element-hq/element-web/issues/32012 Notes: Fix the collapsed space panel separator sitting too close to the macOS traffic light buttons. * Use contributor copyright header on the new test file --- apps/desktop/src/macos-titlebar.test.ts | 70 +++++++++++++++++++++++++ apps/desktop/src/macos-titlebar.ts | 9 ++++ 2 files changed, 79 insertions(+) create mode 100644 apps/desktop/src/macos-titlebar.test.ts diff --git a/apps/desktop/src/macos-titlebar.test.ts b/apps/desktop/src/macos-titlebar.test.ts new file mode 100644 index 0000000000..7ff00572a6 --- /dev/null +++ b/apps/desktop/src/macos-titlebar.test.ts @@ -0,0 +1,70 @@ +/* +Copyright 2026 Spencer Poisseroux + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import { expect, describe, it, beforeEach, afterEach, vi } from "vitest"; +import type { BrowserWindow } from "electron"; + +import { setupMacosTitleBar } from "./macos-titlebar.js"; + +function createFakeWindow(): { + window: BrowserWindow; + emitDidFinishLoad: () => void; + insertCSS: ReturnType; +} { + const listeners: Record void> = {}; + const insertCSS = vi.fn().mockResolvedValue("css-key"); + const window = { + isFullScreen: vi.fn().mockReturnValue(false), + on: vi.fn(), + webContents: { + insertCSS, + removeInsertedCSS: vi.fn(), + on: vi.fn((event: string, listener: () => void) => { + listeners[event] = listener; + }), + }, + } as unknown as BrowserWindow; + + return { + window, + insertCSS, + emitDidFinishLoad: () => listeners["did-finish-load"]?.(), + }; +} + +describe("setupMacosTitleBar", () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + describe("on macOS", () => { + beforeEach(() => { + vi.spyOn(process, "platform", "get").mockReturnValue("darwin"); + }); + + it("widens the collapsed space panel so the separator clears the traffic lights", async () => { + const { window, insertCSS, emitDidFinishLoad } = createFakeWindow(); + setupMacosTitleBar(window); + emitDidFinishLoad(); + // insertCSS is async; wait for the microtask queue to flush + await Promise.resolve(); + + expect(insertCSS).toHaveBeenCalledTimes(1); + const css = insertCSS.mock.calls[0][0] as string; + expect(css).toContain(".mx_SpacePanel.collapsed"); + expect(css).toContain("width: 76px !important;"); + }); + }); + + it("does nothing on non-macOS platforms", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + const { window, insertCSS, emitDidFinishLoad } = createFakeWindow(); + setupMacosTitleBar(window); + emitDidFinishLoad(); + expect(insertCSS).not.toHaveBeenCalled(); + }); +}); diff --git a/apps/desktop/src/macos-titlebar.ts b/apps/desktop/src/macos-titlebar.ts index 917ae75a62..717a853c91 100644 --- a/apps/desktop/src/macos-titlebar.ts +++ b/apps/desktop/src/macos-titlebar.ts @@ -32,6 +32,15 @@ export function setupMacosTitleBar(window: BrowserWindow): void { /* 19px original top value, 32px margin-top above, 12px original margin-top value */ top: calc(19px + 32px - 12px) !important; } + /* Widen the collapsed space panel so its right-hand separator clears the + traffic light buttons. The buttons are inset 9px (see trafficLightPosition + in electron-main) and the three-button cluster is ~52px wide, ending ~61px + from the window edge; against the default 68px rail the separator crowds the + green button. 76px restores ~15px of clearance, matching the compound 4x + spacing step. */ + .mx_SpacePanel.collapsed { + width: 76px !important; + } /* Prevent the media lightbox sender info from clipping into the traffic light buttons */ .mx_ImageView_info_wrapper { margin-top: 32px;