From 4622b0c7efc323eb4708feb9134a3be0936d40df Mon Sep 17 00:00:00 2001 From: Jacob Fu <141651335+FuJacob@users.noreply.github.com> Date: Mon, 8 Jun 2026 23:55:59 -0700 Subject: [PATCH 1/2] fix(ui): make the macOS 26 menu bar popup fill opaque so its shadow hugs a solid panel On macOS 26 Liquid Glass, containerBackground(_, for: .window) is composited through a translucent glass backdrop (CABackdropLayer), so the opaque Color passed by #566 was still rendered see-through. The non-opaque popover window let the desktop bleed through and the native shadow detached from the content on light backgrounds, reopening #492 as #646. Draw the fill as ordinary content instead: an opaque window-colored rounded rectangle matching the native 16pt continuous corner, behind the menu. It renders as a real opaque layer the system shadow can hug. Verified on macOS 26 via layer inspection (a full-size opaque corner-16 layer now backs the window) and by capturing the popover in light and dark mode. Fixes #646 --- Cotabby/UI/MenuBarView.swift | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Cotabby/UI/MenuBarView.swift b/Cotabby/UI/MenuBarView.swift index b2a0c3a..4194174 100644 --- a/Cotabby/UI/MenuBarView.swift +++ b/Cotabby/UI/MenuBarView.swift @@ -467,11 +467,22 @@ private struct MenuBarWindowBackgroundModifier: ViewModifier { @ViewBuilder func body(content: Content) -> some View { if #available(macOS 26.0, *) { - // macOS 26 Liquid Glass renders the `.windowBackground` *material* as translucent - // glass, so the app/desktop behind the popup bleeds through and the native chrome and - // shadow detach from the content, worst on light backgrounds (issue #492). Fill with - // an opaque window *color* instead so the popup reads as one solid rounded panel. - content.containerBackground(Color(nsColor: .windowBackgroundColor), for: .window) + // macOS 26 Liquid Glass composites `containerBackground(_, for: .window)` through a + // translucent glass backdrop (a `CABackdropLayer`), so passing it an opaque `Color` + // does NOT produce an opaque fill: the desktop still bleeds through the glass and the + // native window shadow detaches from the see-through panel on light backgrounds. That + // is why #492 (translucent material) recurred as #646 even after #566 swapped the + // material for an opaque color, which the system still re-routed through the backdrop. + // + // Draw the fill as ordinary content instead. A plain `.background` renders as a normal + // opaque layer rather than the glass backdrop, and we clip it to the native popover + // shape (measured 16pt continuous corner) so it covers the whole non-opaque window up + // to the rounded edge. The popup then reads as one solid rounded panel that the system + // shadow can hug, with no desktop bleed-through. + content.background { + RoundedRectangle(cornerRadius: 16, style: .continuous) + .fill(Color(nsColor: .windowBackgroundColor)) + } } else if #available(macOS 15.0, *) { // MenuBarExtra's `.window` style already gives us native rounded window chrome. Place // the fill at the hosting window instead of this view's local bounds so it reaches the From cd545d793ea090d2cf096522cf4498dcacd74194 Mon Sep 17 00:00:00 2001 From: Jacob Fu <141651335+FuJacob@users.noreply.github.com> Date: Tue, 9 Jun 2026 00:16:05 -0700 Subject: [PATCH 2/2] refactor(ui): name the macOS 26 popover corner radius constant Addresses Greptile feedback: extract the measured 16pt radius into macOS26PopoverCornerRadius so the coupling to the system popover shape is documented and future OS changes are a one-line update. --- Cotabby/UI/MenuBarView.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Cotabby/UI/MenuBarView.swift b/Cotabby/UI/MenuBarView.swift index 4194174..e3739d5 100644 --- a/Cotabby/UI/MenuBarView.swift +++ b/Cotabby/UI/MenuBarView.swift @@ -464,6 +464,13 @@ struct MenuBarView: View { /// `MenuBarExtra`. Keeping this as a dedicated modifier gives the UI a narrow boundary for one /// platform-specific presentation rule without mixing availability checks into the main view body. private struct MenuBarWindowBackgroundModifier: ViewModifier { + /// Corner radius of the macOS 26 popover window, measured against the system chrome. The opaque + /// fill is clipped to this so it reaches the rounded edge of the non-opaque window. It is an + /// intentional coupling to a system measurement: if a future macOS changes the popover shape, + /// this is the single value to update (too small leaves a transparent sliver that re-detaches + /// the shadow; too large is harmlessly clipped by the window mask). + private static let macOS26PopoverCornerRadius: CGFloat = 16 + @ViewBuilder func body(content: Content) -> some View { if #available(macOS 26.0, *) { @@ -476,11 +483,11 @@ private struct MenuBarWindowBackgroundModifier: ViewModifier { // // Draw the fill as ordinary content instead. A plain `.background` renders as a normal // opaque layer rather than the glass backdrop, and we clip it to the native popover - // shape (measured 16pt continuous corner) so it covers the whole non-opaque window up + // shape (see `macOS26PopoverCornerRadius`) so it covers the whole non-opaque window up // to the rounded edge. The popup then reads as one solid rounded panel that the system // shadow can hug, with no desktop bleed-through. content.background { - RoundedRectangle(cornerRadius: 16, style: .continuous) + RoundedRectangle(cornerRadius: Self.macOS26PopoverCornerRadius, style: .continuous) .fill(Color(nsColor: .windowBackgroundColor)) } } else if #available(macOS 15.0, *) {