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.
This commit is contained in:
matt 2026-02-12 14:54:23 +09:00
parent 7fa2f96ed4
commit 656c9b155f
4 changed files with 32 additions and 18 deletions

View file

@ -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();

View file

@ -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
}
>

View file

@ -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 => {
)}
</button>
{/* Settings gear icon */}
<button
onClick={openSettingsTab}
onMouseEnter={() => setSettingsHover(true)}
onMouseLeave={() => setSettingsHover(false)}
className="rounded-md p-2 transition-colors"
style={{
color: settingsHover ? 'var(--color-text)' : 'var(--color-text-muted)',
backgroundColor: settingsHover ? 'var(--color-surface-raised)' : 'transparent',
}}
title="Settings"
>
<Settings className="size-4" />
</button>
{/* Settings gear icon (Electron only - browser can't access native settings) */}
{isElectronMode() && (
<button
onClick={openSettingsTab}
onMouseEnter={() => setSettingsHover(true)}
onMouseLeave={() => setSettingsHover(false)}
className="rounded-md p-2 transition-colors"
style={{
color: settingsHover ? 'var(--color-text)' : 'var(--color-text-muted)',
backgroundColor: settingsHover ? 'var(--color-surface-raised)' : 'transparent',
}}
title="Settings"
>
<Settings className="size-4" />
</button>
)}
</div>
{/* Context menu */}

View file

@ -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 (
<div