Keep desktop sidebar controls stable across panel changes (#2078)

* fix(app): stabilize desktop sidebar controls

Keep the left-window-controls toggle mounted across sidebar state changes so its position and tooltip state remain stable. Preserve browser placement and show an explicit Explorer close control only where native right-side controls do not provide one.

* fix(app): suppress inactive sidebar chrome
This commit is contained in:
Mohamed Boudra
2026-07-15 15:30:57 +08:00
committed by GitHub
parent 9c40cb7637
commit 77f6069ec1
10 changed files with 326 additions and 33 deletions
+26 -5
View File
@@ -32,7 +32,7 @@ import { SidebarDisplayPreferencesMenu } from "@/components/sidebar/sidebar-disp
import { SidebarHelpMenu } from "@/components/sidebar/sidebar-help-menu";
import { Shortcut } from "@/components/ui/shortcut";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { useIsCompactFormFactor } from "@/constants/layout";
import { HEADER_INNER_HEIGHT, useIsCompactFormFactor } from "@/constants/layout";
import { isWeb } from "@/constants/platform";
import { useOpenProjectPicker } from "@/hooks/use-open-project-picker";
import { useShortcutKeys } from "@/hooks/use-shortcut-keys";
@@ -52,7 +52,7 @@ import { useHosts } from "@/runtime/host-runtime";
import { useActiveWorkspaceSelection } from "@/stores/navigation-active-workspace-store";
import { useWorkspace } from "@/stores/session-store-hooks";
import { selectIsAgentListOpen, usePanelStore } from "@/stores/panel-store";
import { WindowChromeSafeArea } from "@/utils/desktop-window";
import { useOwnsWindowChromeCorner, WindowChromeSafeArea } from "@/utils/desktop-window";
import { useCloseAgentListGesture } from "@/mobile-panels/gestures";
import { MobilePanelOverlay } from "@/mobile-panels/presentation";
import {
@@ -706,6 +706,7 @@ function DesktopSidebar({
handleViewMore,
handleViewSchedules,
}: DesktopSidebarProps) {
const ownsTopLeft = useOwnsWindowChromeCorner("top-left");
const pathname = usePathname();
const hasActiveHostFilter = useSidebarViewStore((state) => state.hostFilters.length > 0);
const isSessionsActive = pathname.includes("/sessions");
@@ -759,6 +760,10 @@ function DesktopSidebar({
() => [styles.desktopSidebarBorder, { flex: 1, paddingTop: insetsTop }],
[insetsTop],
);
const sidebarHeaderGroupStyle = useMemo(
() => [styles.sidebarHeaderGroup, ownsTopLeft && styles.sidebarHeaderGroupBelowChrome],
[ownsTopLeft],
);
const resizeHandleStyle = useMemo(
() => [styles.resizeHandle, isWeb && ({ cursor: "col-resize" } as object)],
[],
@@ -772,9 +777,14 @@ function DesktopSidebar({
<Animated.View style={desktopSidebarStyle}>
<View style={desktopSidebarBorderStyle}>
<View style={styles.sidebarDragArea}>
<TitlebarDragRegion />
<WindowChromeSafeArea placement="below" />
<View style={styles.sidebarHeaderGroup}>
{ownsTopLeft ? (
<View style={styles.desktopChromeRow}>
<TitlebarDragRegion />
</View>
) : (
<TitlebarDragRegion />
)}
<View style={sidebarHeaderGroupStyle}>
<SidebarNewWorkspaceHeaderRow
label={labels.newWorkspace}
testID="sidebar-global-new-workspace"
@@ -920,6 +930,9 @@ const styles = StyleSheet.create((theme) => ({
borderBottomWidth: 1,
borderBottomColor: theme.colors.border,
},
sidebarHeaderGroupBelowChrome: {
paddingTop: 0,
},
workspacesSectionHeader: {
flexDirection: "row",
alignItems: "center",
@@ -991,6 +1004,14 @@ const styles = StyleSheet.create((theme) => ({
sidebarDragArea: {
position: "relative",
},
desktopChromeRow: {
position: "relative",
height: HEADER_INNER_HEIGHT,
flexDirection: "row",
alignItems: "center",
borderBottomWidth: theme.borderWidth[1],
borderBottomColor: "transparent",
},
sidebarFooter: {
flexDirection: "row",
alignItems: "center",