Skip to content

Commit 157b50c

Browse files
lefarcenclaude
andauthored
fix(web): fix Mac sidebar toggle position and platform detection (#1002)
- Mac toggle button now fixed at traffic light position in both expanded and collapsed states - Remove toggle from header on Mac (stays in fixed position) - Add navigator.userAgent fallback for platform detection when VITE_DESKTOP_PLATFORM env is not available (dev mode) - Inject VITE_DESKTOP_PLATFORM into web dev server env Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2b66ad4 commit 157b50c

3 files changed

Lines changed: 42 additions & 24 deletions

File tree

apps/web/src/layouts/workspace-layout.tsx

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -680,17 +680,12 @@ function WorkspaceLayoutInner() {
680680
/>
681681
)}
682682

683-
{/* Collapsed sidebar toggle (desktop client only) */}
684-
{!isWindowsDesktopClient && collapsed && (
683+
{/* Mac sidebar toggle — fixed next to traffic lights, always visible */}
684+
{isMacDesktopClient && (
685685
<button
686686
type="button"
687687
onClick={() => setCollapsed(!collapsed)}
688-
className={cn(
689-
"fixed h-8 w-8 rounded-lg text-text-tertiary hover:text-text-primary hover:bg-surface-2 transition-colors hidden md:flex items-center justify-center z-50",
690-
isMacDesktopClient
691-
? "top-[10px] left-[76px]"
692-
: "top-[16px] left-[24px]",
693-
)}
688+
className="fixed top-[10px] left-[76px] h-8 w-8 rounded-lg text-text-tertiary hover:text-text-primary hover:bg-surface-2 transition-colors hidden md:flex items-center justify-center z-50"
694689
style={{ WebkitAppRegion: "no-drag" } as React.CSSProperties}
695690
title={
696691
collapsed ? t("layout.expandSidebar") : t("layout.collapseSidebar")
@@ -703,6 +698,18 @@ function WorkspaceLayoutInner() {
703698
)}
704699
</button>
705700
)}
701+
{/* Non-mac, non-windows collapsed toggle */}
702+
{!isMacDesktopClient && !isWindowsDesktopClient && collapsed && (
703+
<button
704+
type="button"
705+
onClick={() => setCollapsed(!collapsed)}
706+
className="fixed top-[16px] left-[24px] h-8 w-8 rounded-lg text-text-tertiary hover:text-text-primary hover:bg-surface-2 transition-colors hidden md:flex items-center justify-center z-50"
707+
style={{ WebkitAppRegion: "no-drag" } as React.CSSProperties}
708+
title={t("layout.expandSidebar")}
709+
>
710+
<PanelLeftOpen size={16} />
711+
</button>
712+
)}
706713

707714
{isWindowsDesktopClient && (
708715
<div className="fixed px-2 z-50">
@@ -735,18 +742,14 @@ function WorkspaceLayoutInner() {
735742
}
736743
>
737744
{/* Traffic light clearance (desktop client) */}
738-
{!isWindowsDesktopClient && (
739-
<div
740-
className={cn("shrink-0", isMacDesktopClient ? "h-10" : "h-14")}
741-
/>
742-
)}
745+
{!isWindowsDesktopClient && <div className={cn("shrink-0", "h-14")} />}
743746

744747
{/* Header / Brand */}
745748
{!isWindowsDesktopClient && (
746749
<div
747750
className={cn(
748751
"flex items-center justify-between px-3 pb-2 shrink-0",
749-
isMacDesktopClient && "h-12 pl-4 pr-3 pt-0 pb-1",
752+
isMacDesktopClient && "px-4 pb-1",
750753
!isDesktopClient && "border-b border-border py-3 px-4 gap-2.5",
751754
)}
752755
style={{ WebkitAppRegion: "no-drag" } as React.CSSProperties}
@@ -768,14 +771,16 @@ function WorkspaceLayoutInner() {
768771
{t("layout.update.badge")}
769772
</button>
770773
)}
771-
<button
772-
type="button"
773-
onClick={() => setCollapsed(true)}
774-
className="p-1.5 rounded-lg transition-colors text-text-muted hover:text-text-primary hover:bg-surface-3 shrink-0"
775-
title={t("layout.collapseSidebar")}
776-
>
777-
<PanelLeftClose size={14} />
778-
</button>
774+
{!isMacDesktopClient && (
775+
<button
776+
type="button"
777+
onClick={() => setCollapsed(true)}
778+
className="p-1.5 rounded-lg transition-colors text-text-muted hover:text-text-primary hover:bg-surface-3 shrink-0"
779+
title={t("layout.collapseSidebar")}
780+
>
781+
<PanelLeftClose size={14} />
782+
</button>
783+
)}
779784
</div>
780785
</>
781786
) : (

apps/web/src/lib/desktop-platform.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
export function getDesktopPlatform(): string | null {
2-
const value = import.meta.env.VITE_DESKTOP_PLATFORM;
3-
return typeof value === "string" && value.trim().length > 0 ? value : null;
2+
// Prefer the build-time env injected by desktop packaging / dev scripts.
3+
const envValue = import.meta.env.VITE_DESKTOP_PLATFORM;
4+
if (typeof envValue === "string" && envValue.trim().length > 0) {
5+
return envValue;
6+
}
7+
// Fallback: detect at runtime via navigator so dev-mode webviews
8+
// (where Vite may not receive the env) still get the correct platform.
9+
if (typeof navigator !== "undefined") {
10+
const ua = navigator.userAgent.toLowerCase();
11+
if (ua.includes("win")) return "win32";
12+
if (ua.includes("mac")) return "darwin";
13+
if (ua.includes("linux")) return "linux";
14+
}
15+
return null;
416
}
517

618
export function isWindowsDesktopPlatform(): boolean {

scripts/dev/src/shared/dev-runtime-config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ export function createWebInjectedEnv(): NodeJS.ProcessEnv {
215215
WEB_HOST: "127.0.0.1",
216216
WEB_PORT: String(config.webPort),
217217
WEB_API_ORIGIN: config.controllerUrl,
218+
VITE_DESKTOP_PLATFORM: process.platform,
218219
};
219220
}
220221

0 commit comments

Comments
 (0)