From 656c9b155f6407d9a64c0a4d308f7ef351a2be64 Mon Sep 17 00:00:00 2001 From: matt Date: Thu, 12 Feb 2026 14:54:23 +0900 Subject: [PATCH] feat(ui): integrate Electron mode detection for conditional UI rendering - Added `isElectronMode` function to determine if the app is running in Electron or a browser. - Updated `SidebarHeader`, `TabBar`, and `TabbedLayout` components to conditionally render UI elements based on the Electron mode. - Adjusted styles and settings gear icon visibility to enhance user experience in browser mode. This commit improves the application's adaptability by ensuring that Electron-specific features are only available when appropriate. --- src/renderer/api/index.ts | 6 ++++ .../components/layout/SidebarHeader.tsx | 7 ++-- src/renderer/components/layout/TabBar.tsx | 34 +++++++++++-------- .../components/layout/TabbedLayout.tsx | 3 +- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/renderer/api/index.ts b/src/renderer/api/index.ts index fb2ba881..1d59170e 100644 --- a/src/renderer/api/index.ts +++ b/src/renderer/api/index.ts @@ -39,6 +39,12 @@ function getImpl(): ElectronAPI { * In browser: delegates to `HttpAPIClient` (created on first use). * In tests: delegates to whatever mock is installed on `window.electronAPI`. */ +/** + * Whether the app is running inside Electron (true) or in a browser via HTTP server (false). + * Use this to hide Electron-only UI (settings, traffic lights, etc.) in browser mode. + */ +export const isElectronMode = (): boolean => !!window.electronAPI; + export const api: ElectronAPI = new Proxy({} as ElectronAPI, { get(_target, prop, receiver) { const impl = getImpl(); diff --git a/src/renderer/components/layout/SidebarHeader.tsx b/src/renderer/components/layout/SidebarHeader.tsx index cae456ef..4ad2bcfd 100644 --- a/src/renderer/components/layout/SidebarHeader.tsx +++ b/src/renderer/components/layout/SidebarHeader.tsx @@ -13,6 +13,7 @@ import { useEffect, useRef, useState } from 'react'; +import { isElectronMode } from '@renderer/api'; import { HEADER_ROW1_HEIGHT, HEADER_ROW2_HEIGHT } from '@renderer/constants/layout'; import { useStore } from '@renderer/store'; import { truncateMiddle } from '@renderer/utils/stringUtils'; @@ -330,8 +331,10 @@ export const SidebarHeader = (): React.JSX.Element => { style={ { height: `${HEADER_ROW1_HEIGHT}px`, - paddingLeft: 'var(--macos-traffic-light-padding-left, 72px)', - WebkitAppRegion: 'drag', + paddingLeft: isElectronMode() + ? 'var(--macos-traffic-light-padding-left, 72px)' + : '16px', + WebkitAppRegion: isElectronMode() ? 'drag' : undefined, } as React.CSSProperties } > diff --git a/src/renderer/components/layout/TabBar.tsx b/src/renderer/components/layout/TabBar.tsx index fae7e16c..9cf37c90 100644 --- a/src/renderer/components/layout/TabBar.tsx +++ b/src/renderer/components/layout/TabBar.tsx @@ -11,6 +11,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useDroppable } from '@dnd-kit/core'; import { horizontalListSortingStrategy, SortableContext } from '@dnd-kit/sortable'; +import { isElectronMode } from '@renderer/api'; import { HEADER_ROW1_HEIGHT } from '@renderer/constants/layout'; import { useStore } from '@renderer/store'; import { Bell, PanelLeft, Plus, RefreshCw, Search, Settings } from 'lucide-react'; @@ -250,7 +251,8 @@ export const TabBar = ({ paneId }: TabBarProps): React.JSX.Element => { sidebarCollapsed && isLeftmostPane ? 'var(--macos-traffic-light-padding-left, 72px)' : '8px', - WebkitAppRegion: sidebarCollapsed && isLeftmostPane ? 'drag' : undefined, + WebkitAppRegion: + isElectronMode() && sidebarCollapsed && isLeftmostPane ? 'drag' : undefined, backgroundColor: 'var(--color-surface)', borderBottom: '1px solid var(--color-border)', opacity: isFocused || paneCount === 1 ? 1 : 0.7, @@ -382,20 +384,22 @@ export const TabBar = ({ paneId }: TabBarProps): React.JSX.Element => { )} - {/* Settings gear icon */} - + {/* Settings gear icon (Electron only - browser can't access native settings) */} + {isElectronMode() && ( + + )} {/* Context menu */} diff --git a/src/renderer/components/layout/TabbedLayout.tsx b/src/renderer/components/layout/TabbedLayout.tsx index a7373dff..235389bd 100644 --- a/src/renderer/components/layout/TabbedLayout.tsx +++ b/src/renderer/components/layout/TabbedLayout.tsx @@ -6,6 +6,7 @@ * - Main content: PaneContainer with one or more panes, each with TabBar + content */ +import { isElectronMode } from '@renderer/api'; import { getTrafficLightPaddingForZoom } from '@renderer/constants/layout'; import { useKeyboardShortcuts } from '@renderer/hooks/useKeyboardShortcuts'; import { useZoomFactor } from '@renderer/hooks/useZoomFactor'; @@ -64,7 +65,7 @@ export const TabbedLayout = (): React.JSX.Element => { // Enable keyboard shortcuts useKeyboardShortcuts(); const zoomFactor = useZoomFactor(); - const trafficLightPadding = getTrafficLightPaddingForZoom(zoomFactor); + const trafficLightPadding = isElectronMode() ? getTrafficLightPaddingForZoom(zoomFactor) : 0; return (