fix(app): align workspace chrome controls
This commit is contained in:
@@ -46,7 +46,6 @@ import { FloatingPanelPortalHost } from "@/components/ui/floating-panel-portal";
|
|||||||
import { HostChooserModal, useHostChooser } from "@/hosts/host-chooser";
|
import { HostChooserModal, useHostChooser } from "@/hosts/host-chooser";
|
||||||
import {
|
import {
|
||||||
getIsElectronRuntime,
|
getIsElectronRuntime,
|
||||||
getIsElectronRuntimeMac,
|
|
||||||
HEADER_INNER_HEIGHT,
|
HEADER_INNER_HEIGHT,
|
||||||
useIsCompactFormFactor,
|
useIsCompactFormFactor,
|
||||||
} from "@/constants/layout";
|
} from "@/constants/layout";
|
||||||
@@ -713,23 +712,17 @@ function DesktopWindowControlsSync({ enabled }: { enabled: boolean }) {
|
|||||||
const { theme } = useUnistyles();
|
const { theme } = useUnistyles();
|
||||||
const surface0 = theme.colors.surface0;
|
const surface0 = theme.colors.surface0;
|
||||||
const foreground = theme.colors.foreground;
|
const foreground = theme.colors.foreground;
|
||||||
const pathname = usePathname();
|
|
||||||
const isFocusModeEnabled = usePanelStore((state) => state.desktop.focusModeEnabled);
|
|
||||||
const liftTrafficLights =
|
|
||||||
getIsElectronRuntimeMac() &&
|
|
||||||
isFocusModeEnabled &&
|
|
||||||
parseHostWorkspaceRouteFromPathname(pathname) !== null;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!enabled || isNative) return;
|
if (!enabled || isNative) return;
|
||||||
void updateDesktopWindowControls({
|
void updateDesktopWindowControls({
|
||||||
backgroundColor: surface0,
|
backgroundColor: surface0,
|
||||||
foregroundColor: foreground,
|
foregroundColor: foreground,
|
||||||
trafficLightOffsetY: liftTrafficLights ? -5 : 0.5,
|
trafficLightOffsetY: -5,
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.warn("[DesktopWindow] Failed to update window controls overlay", error);
|
console.warn("[DesktopWindow] Failed to update window controls overlay", error);
|
||||||
});
|
});
|
||||||
}, [enabled, surface0, foreground, liftTrafficLights]);
|
}, [enabled, surface0, foreground]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { StyleSheet, withUnistyles } from "react-native-unistyles";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import type { Theme } from "@/styles/theme";
|
import type { Theme } from "@/styles/theme";
|
||||||
import { Combobox, ComboboxItem, type ComboboxProps } from "@/components/ui/combobox";
|
import { Combobox, ComboboxItem, type ComboboxProps } from "@/components/ui/combobox";
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
import { useHostRuntimeClient, useHostRuntimeIsConnected } from "@/runtime/host-runtime";
|
import { useHostRuntimeClient, useHostRuntimeIsConnected } from "@/runtime/host-runtime";
|
||||||
import { useToast } from "@/contexts/toast-context";
|
import { useToast } from "@/contexts/toast-context";
|
||||||
import { useBranchSwitcher } from "@/hooks/use-branch-switcher";
|
import { useBranchSwitcher } from "@/hooks/use-branch-switcher";
|
||||||
@@ -87,12 +88,16 @@ export function BranchSwitcher({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View ref={anchorRef} collapsable={false} style={styles.anchor}>
|
<View ref={anchorRef} collapsable={false} style={styles.anchor}>
|
||||||
|
<Tooltip delayDuration={300} enabledOnDesktop enabledOnMobile={false}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
<Pressable
|
<Pressable
|
||||||
testID={testID}
|
testID={testID}
|
||||||
onPress={handleOpen}
|
onPress={handleOpen}
|
||||||
style={triggerStyle}
|
style={triggerStyle}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel={t("branchSwitcher.currentBranch", { branchName: currentBranchName })}
|
accessibilityLabel={t("branchSwitcher.currentBranch", {
|
||||||
|
branchName: currentBranchName,
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
<ThemedGitBranch size={12} uniProps={foregroundMutedIconColorMapping} />
|
<ThemedGitBranch size={12} uniProps={foregroundMutedIconColorMapping} />
|
||||||
<Text style={styles.branchLabel} numberOfLines={1}>
|
<Text style={styles.branchLabel} numberOfLines={1}>
|
||||||
@@ -100,6 +105,11 @@ export function BranchSwitcher({
|
|||||||
</Text>
|
</Text>
|
||||||
<ThemedChevronDown size={12} uniProps={foregroundMutedIconColorMapping} />
|
<ThemedChevronDown size={12} uniProps={foregroundMutedIconColorMapping} />
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent side="bottom">
|
||||||
|
<Text style={styles.tooltipText}>{t("branchSwitcher.triggerTooltip")}</Text>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
<Combobox
|
<Combobox
|
||||||
options={branchOptions}
|
options={branchOptions}
|
||||||
value={currentBranchName}
|
value={currentBranchName}
|
||||||
@@ -145,4 +155,8 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
fontWeight: theme.fontWeight.normal,
|
fontWeight: theme.fontWeight.normal,
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
},
|
},
|
||||||
|
tooltipText: {
|
||||||
|
color: theme.colors.popoverForeground,
|
||||||
|
fontSize: theme.fontSize.xs,
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const FOOTER_HEIGHT = 75;
|
|||||||
// Shared header inner height (excluding safe area insets and border)
|
// Shared header inner height (excluding safe area insets and border)
|
||||||
// Used by both agent header (ScreenHeader) and explorer sidebar header
|
// Used by both agent header (ScreenHeader) and explorer sidebar header
|
||||||
// This ensures both headers have the same visual height
|
// This ensures both headers have the same visual height
|
||||||
export const HEADER_INNER_HEIGHT = 48;
|
export const HEADER_INNER_HEIGHT = 36;
|
||||||
export const HEADER_INNER_HEIGHT_MOBILE = 56;
|
export const HEADER_INNER_HEIGHT_MOBILE = 56;
|
||||||
export const WORKSPACE_SECONDARY_HEADER_HEIGHT = 36;
|
export const WORKSPACE_SECONDARY_HEADER_HEIGHT = 36;
|
||||||
export const HEADER_TOP_PADDING_MOBILE = 8;
|
export const HEADER_TOP_PADDING_MOBILE = 8;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { inlineUnistylesStyle } from "@/styles/unistyles-inline-style";
|
|||||||
import type { ShortcutKey } from "@/utils/format-shortcut";
|
import type { ShortcutKey } from "@/utils/format-shortcut";
|
||||||
import type { GitAction, GitActions } from "@/git/policy";
|
import type { GitAction, GitActions } from "@/git/policy";
|
||||||
import { useGitActionRunner } from "@/git/use-actions";
|
import { useGitActionRunner } from "@/git/use-actions";
|
||||||
|
import { buttonControlHeight } from "@/components/ui/control-geometry";
|
||||||
|
|
||||||
interface GitActionsSplitButtonProps {
|
interface GitActionsSplitButtonProps {
|
||||||
gitActions: GitActions;
|
gitActions: GitActions;
|
||||||
@@ -210,16 +211,16 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
},
|
},
|
||||||
splitButton: {
|
splitButton: {
|
||||||
|
height: buttonControlHeight.xs,
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "stretch",
|
alignItems: "stretch",
|
||||||
borderRadius: theme.borderRadius.md,
|
borderRadius: theme.borderRadius.lg,
|
||||||
borderWidth: theme.borderWidth[1],
|
borderWidth: theme.borderWidth[1],
|
||||||
borderColor: theme.colors.borderAccent,
|
borderColor: theme.colors.borderAccent,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
},
|
},
|
||||||
splitButtonPrimary: {
|
splitButtonPrimary: {
|
||||||
paddingHorizontal: theme.spacing[3],
|
paddingHorizontal: theme.spacing[3],
|
||||||
paddingVertical: theme.spacing[1],
|
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
},
|
},
|
||||||
@@ -249,11 +250,11 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
borderLeftColor: theme.colors.borderAccent,
|
borderLeftColor: theme.colors.borderAccent,
|
||||||
},
|
},
|
||||||
iconButton: {
|
iconButton: {
|
||||||
width: 32,
|
width: buttonControlHeight.xs,
|
||||||
height: 32,
|
height: buttonControlHeight.xs,
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
borderRadius: theme.borderRadius.md,
|
borderRadius: theme.borderRadius.lg,
|
||||||
},
|
},
|
||||||
overflowMenuButton: {
|
overflowMenuButton: {
|
||||||
marginRight: -theme.spacing[2],
|
marginRight: -theme.spacing[2],
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import { planWorkspaceOpenTargets } from "@/workspace/open-target-planner";
|
|||||||
import type { Theme } from "@/styles/theme";
|
import type { Theme } from "@/styles/theme";
|
||||||
import { ForgeBrandIcon } from "@/git/forge-icon";
|
import { ForgeBrandIcon } from "@/git/forge-icon";
|
||||||
import { getForgePresentation } from "@/git/forge";
|
import { getForgePresentation } from "@/git/forge";
|
||||||
|
import { buttonControlHeight } from "@/components/ui/control-geometry";
|
||||||
|
|
||||||
interface WorkspaceOpenInEditorButtonProps {
|
interface WorkspaceOpenInEditorButtonProps {
|
||||||
serverId: string;
|
serverId: string;
|
||||||
@@ -284,9 +285,10 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
},
|
},
|
||||||
splitButton: {
|
splitButton: {
|
||||||
|
height: buttonControlHeight.xs,
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "stretch",
|
alignItems: "stretch",
|
||||||
borderRadius: theme.borderRadius.md,
|
borderRadius: theme.borderRadius.lg,
|
||||||
borderWidth: theme.borderWidth[1],
|
borderWidth: theme.borderWidth[1],
|
||||||
borderColor: theme.colors.borderAccent,
|
borderColor: theme.colors.borderAccent,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
@@ -294,14 +296,12 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
splitButtonPrimary: {
|
splitButtonPrimary: {
|
||||||
paddingLeft: theme.spacing[3],
|
paddingLeft: theme.spacing[3],
|
||||||
paddingRight: theme.spacing[3],
|
paddingRight: theme.spacing[3],
|
||||||
paddingVertical: theme.spacing[1],
|
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
},
|
},
|
||||||
splitButtonPrimaryIconOnly: {
|
splitButtonPrimaryIconOnly: {
|
||||||
paddingLeft: theme.spacing[2],
|
paddingLeft: theme.spacing[2],
|
||||||
paddingRight: theme.spacing[2],
|
paddingRight: theme.spacing[2],
|
||||||
paddingVertical: theme.spacing[1],
|
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import { useQueryClient } from "@tanstack/react-query";
|
|||||||
import { useRouter, type Href } from "expo-router";
|
import { useRouter, type Href } from "expo-router";
|
||||||
import * as Clipboard from "expo-clipboard";
|
import * as Clipboard from "expo-clipboard";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { DiffStat } from "@/components/diff-stat";
|
|
||||||
import {
|
import {
|
||||||
ChevronDown,
|
ChevronDown,
|
||||||
Copy,
|
Copy,
|
||||||
@@ -37,12 +36,12 @@ import type { Theme } from "@/styles/theme";
|
|||||||
import invariant from "tiny-invariant";
|
import invariant from "tiny-invariant";
|
||||||
import { SidebarMenuToggle } from "@/components/headers/menu-header";
|
import { SidebarMenuToggle } from "@/components/headers/menu-header";
|
||||||
import { HeaderToggleButton } from "@/components/headers/header-toggle-button";
|
import { HeaderToggleButton } from "@/components/headers/header-toggle-button";
|
||||||
|
import { buttonControlHeight } from "@/components/ui/control-geometry";
|
||||||
import { ScreenHeader } from "@/components/headers/screen-header";
|
import { ScreenHeader } from "@/components/headers/screen-header";
|
||||||
import { ScreenTitle } from "@/components/headers/screen-title";
|
import { ScreenTitle } from "@/components/headers/screen-title";
|
||||||
import { HostBadge } from "@/hosts/host-badge";
|
import { HostBadge } from "@/hosts/host-badge";
|
||||||
import { useHostBadges } from "@/hosts/use-host-badges";
|
import { useHostBadges } from "@/hosts/use-host-badges";
|
||||||
import { Combobox, type ComboboxOption } from "@/components/ui/combobox";
|
import { Combobox, type ComboboxOption } from "@/components/ui/combobox";
|
||||||
import { Shortcut } from "@/components/ui/shortcut";
|
|
||||||
import type { ShortcutKey } from "@/utils/format-shortcut";
|
import type { ShortcutKey } from "@/utils/format-shortcut";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@@ -52,7 +51,6 @@ import {
|
|||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
|
||||||
import {
|
import {
|
||||||
FloatingPanelPortalHost,
|
FloatingPanelPortalHost,
|
||||||
FloatingPanelPortalHostNameProvider,
|
FloatingPanelPortalHostNameProvider,
|
||||||
@@ -61,7 +59,6 @@ import { ExplorerSidebar } from "@/components/explorer-sidebar";
|
|||||||
import { SplitContainer } from "@/components/split-container";
|
import { SplitContainer } from "@/components/split-container";
|
||||||
import { RetainedPanel } from "@/components/retained-panel";
|
import { RetainedPanel } from "@/components/retained-panel";
|
||||||
import { WindowChromeRegion } from "@/utils/desktop-window";
|
import { WindowChromeRegion } from "@/utils/desktop-window";
|
||||||
import { SourceControlPanelIcon } from "@/components/icons/source-control-panel-icon";
|
|
||||||
import { WorkspaceActions } from "@/git/workspace-actions";
|
import { WorkspaceActions } from "@/git/workspace-actions";
|
||||||
import { WorkspaceOpenInEditorButton } from "@/screens/workspace/workspace-open-in-editor-button";
|
import { WorkspaceOpenInEditorButton } from "@/screens/workspace/workspace-open-in-editor-button";
|
||||||
import { WorkspaceScriptsButton } from "@/screens/workspace/workspace-scripts-button";
|
import { WorkspaceScriptsButton } from "@/screens/workspace/workspace-scripts-button";
|
||||||
@@ -175,7 +172,7 @@ import {
|
|||||||
useModifiedPanelTabIds,
|
useModifiedPanelTabIds,
|
||||||
} from "@/panels/panel-instance-attributes";
|
} from "@/panels/panel-instance-attributes";
|
||||||
import { findAdjacentPane } from "@/utils/split-navigation";
|
import { findAdjacentPane } from "@/utils/split-navigation";
|
||||||
import { useIsCompactFormFactor, supportsDesktopPaneSplits } from "@/constants/layout";
|
import { supportsDesktopPaneSplits, useIsCompactFormFactor } from "@/constants/layout";
|
||||||
import { getIsElectron, isNative, isWeb } from "@/constants/platform";
|
import { getIsElectron, isNative, isWeb } from "@/constants/platform";
|
||||||
import type { SurfaceBackdrop } from "@/styles/surface-backdrop";
|
import type { SurfaceBackdrop } from "@/styles/surface-backdrop";
|
||||||
import {
|
import {
|
||||||
@@ -252,7 +249,6 @@ const ThemedGlobe = withUnistyles(Globe);
|
|||||||
const ThemedImport = withUnistyles(ImportIcon);
|
const ThemedImport = withUnistyles(ImportIcon);
|
||||||
const ThemedSettings = withUnistyles(Settings);
|
const ThemedSettings = withUnistyles(Settings);
|
||||||
const ThemedPanelRight = withUnistyles(PanelRight);
|
const ThemedPanelRight = withUnistyles(PanelRight);
|
||||||
const ThemedSourceControlPanelIcon = withUnistyles(SourceControlPanelIcon);
|
|
||||||
|
|
||||||
interface DynamicProviderIconProps {
|
interface DynamicProviderIconProps {
|
||||||
iconKey: string;
|
iconKey: string;
|
||||||
@@ -273,8 +269,6 @@ const extraMutedColorMapping = (theme: Theme) => ({
|
|||||||
color: theme.colors.foregroundExtraMuted,
|
color: theme.colors.foregroundExtraMuted,
|
||||||
});
|
});
|
||||||
|
|
||||||
const sourceControlPanelStrokeWidth15 = { strokeWidth: 1.5 };
|
|
||||||
|
|
||||||
const MENU_NEW_AGENT_ICON = <ThemedSquarePen size={16} uniProps={mutedColorMapping} />;
|
const MENU_NEW_AGENT_ICON = <ThemedSquarePen size={16} uniProps={mutedColorMapping} />;
|
||||||
const MENU_NEW_TERMINAL_ICON = <ThemedSquareTerminal size={16} uniProps={mutedColorMapping} />;
|
const MENU_NEW_TERMINAL_ICON = <ThemedSquareTerminal size={16} uniProps={mutedColorMapping} />;
|
||||||
const MENU_NEW_BROWSER_ICON = <ThemedGlobe size={16} uniProps={mutedColorMapping} />;
|
const MENU_NEW_BROWSER_ICON = <ThemedGlobe size={16} uniProps={mutedColorMapping} />;
|
||||||
@@ -2022,15 +2016,6 @@ function WorkspaceScreenContent({
|
|||||||
isDesktopExplorerOpen,
|
isDesktopExplorerOpen,
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasDiffStat = useMemo(() => Boolean(workspaceDescriptor?.diffStat), [workspaceDescriptor]);
|
|
||||||
const explorerToggleStyle = useCallback(
|
|
||||||
({ hovered, pressed }: { hovered?: boolean; pressed?: boolean }) => [
|
|
||||||
styles.sourceControlButton,
|
|
||||||
hasDiffStat && styles.sourceControlButtonWithStats,
|
|
||||||
(Boolean(hovered) || Boolean(pressed) || isExplorerOpen) && styles.sourceControlButtonHovered,
|
|
||||||
],
|
|
||||||
[hasDiffStat, isExplorerOpen],
|
|
||||||
);
|
|
||||||
const explorerToggleAccessibilityState = useMemo(
|
const explorerToggleAccessibilityState = useMemo(
|
||||||
() => ({ expanded: isExplorerOpen }),
|
() => ({ expanded: isExplorerOpen }),
|
||||||
[isExplorerOpen],
|
[isExplorerOpen],
|
||||||
@@ -3612,70 +3597,24 @@ function WorkspaceScreenContent({
|
|||||||
{!isMobile && workspaceDirectory ? (
|
{!isMobile && workspaceDirectory ? (
|
||||||
<>
|
<>
|
||||||
<WorkspaceActions serverId={normalizedServerId} cwd={workspaceDirectory} />
|
<WorkspaceActions serverId={normalizedServerId} cwd={workspaceDirectory} />
|
||||||
{isGitCheckout ? (
|
|
||||||
<Tooltip delayDuration={0} enabledOnDesktop enabledOnMobile={false}>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<Pressable
|
|
||||||
testID="workspace-explorer-toggle"
|
|
||||||
onPress={handleToggleExplorer}
|
|
||||||
accessibilityRole="button"
|
|
||||||
accessibilityLabel={explorerToggleLabel}
|
|
||||||
accessibilityState={explorerToggleAccessibilityState}
|
|
||||||
style={explorerToggleStyle}
|
|
||||||
>
|
|
||||||
{({ hovered, pressed }) => {
|
|
||||||
const active = hovered || pressed;
|
|
||||||
const colorMapping = active ? foregroundColorMapping : extraMutedColorMapping;
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ThemedSourceControlPanelIcon size={16} uniProps={colorMapping} />
|
|
||||||
{workspaceDescriptor?.diffStat ? (
|
|
||||||
<DiffStat
|
|
||||||
additions={workspaceDescriptor.diffStat.additions}
|
|
||||||
deletions={workspaceDescriptor.diffStat.deletions}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Pressable>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent
|
|
||||||
testID="workspace-explorer-toggle-tooltip"
|
|
||||||
side="left"
|
|
||||||
align="center"
|
|
||||||
offset={8}
|
|
||||||
>
|
|
||||||
<View style={styles.explorerTooltipRow}>
|
|
||||||
<Text style={styles.explorerTooltipText}>
|
|
||||||
{t("workspace.tabs.explorer.toggle")}
|
|
||||||
</Text>
|
|
||||||
<Shortcut keys={EXPLORER_TOGGLE_KEYS} style={styles.explorerTooltipShortcut} />
|
|
||||||
</View>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
{!isMobile && !isGitCheckout ? (
|
|
||||||
<HeaderToggleButton
|
<HeaderToggleButton
|
||||||
testID="workspace-explorer-toggle"
|
testID="workspace-explorer-toggle"
|
||||||
onPress={handleToggleExplorer}
|
onPress={handleToggleExplorer}
|
||||||
tooltipLabel={t("workspace.tabs.explorer.toggle")}
|
tooltipLabel={t("workspace.tabs.explorer.toggle")}
|
||||||
tooltipKeys={EXPLORER_TOGGLE_KEYS}
|
tooltipKeys={EXPLORER_TOGGLE_KEYS}
|
||||||
tooltipSide="left"
|
tooltipSide="left"
|
||||||
style={[styles.compactHeaderActionButton, styles.explorerPanelButton]}
|
style={styles.compactHeaderActionButton}
|
||||||
accessible
|
accessible
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel={explorerToggleLabel}
|
accessibilityLabel={explorerToggleLabel}
|
||||||
accessibilityState={explorerToggleAccessibilityState}
|
accessibilityState={explorerToggleAccessibilityState}
|
||||||
>
|
>
|
||||||
{({ hovered, pressed }) => {
|
{({ hovered }) => {
|
||||||
const colorMapping =
|
const colorMapping = hovered ? foregroundColorMapping : extraMutedColorMapping;
|
||||||
hovered || pressed ? foregroundColorMapping : extraMutedColorMapping;
|
|
||||||
return <ThemedPanelRight size={16} uniProps={colorMapping} />;
|
return <ThemedPanelRight size={16} uniProps={colorMapping} />;
|
||||||
}}
|
}}
|
||||||
</HeaderToggleButton>
|
</HeaderToggleButton>
|
||||||
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
{isMobile ? (
|
{isMobile ? (
|
||||||
<HeaderToggleButton
|
<HeaderToggleButton
|
||||||
@@ -3691,17 +3630,9 @@ function WorkspaceScreenContent({
|
|||||||
accessibilityState={explorerToggleAccessibilityState}
|
accessibilityState={explorerToggleAccessibilityState}
|
||||||
>
|
>
|
||||||
{({ hovered }) => {
|
{({ hovered }) => {
|
||||||
const colorMapping =
|
const colorMapping = hovered ? foregroundColorMapping : mutedColorMapping;
|
||||||
isExplorerOpen || hovered ? foregroundColorMapping : mutedColorMapping;
|
// Matches the ghost scripts Play icon in the same header (16 / 1.5).
|
||||||
return isGitCheckout ? (
|
return <ThemedPanelRight size={16} strokeWidth={1.5} uniProps={colorMapping} />;
|
||||||
<ThemedSourceControlPanelIcon
|
|
||||||
size={20}
|
|
||||||
uniProps={colorMapping}
|
|
||||||
{...sourceControlPanelStrokeWidth15}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ThemedPanelRight size={20} uniProps={colorMapping} />
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
</HeaderToggleButton>
|
</HeaderToggleButton>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -3718,12 +3649,9 @@ function WorkspaceScreenContent({
|
|||||||
handleScriptTerminalStarted,
|
handleScriptTerminalStarted,
|
||||||
handleViewScriptTerminal,
|
handleViewScriptTerminal,
|
||||||
handleOpenUrlInBrowserTab,
|
handleOpenUrlInBrowserTab,
|
||||||
isGitCheckout,
|
|
||||||
handleToggleExplorer,
|
handleToggleExplorer,
|
||||||
isExplorerOpen,
|
|
||||||
explorerToggleLabel,
|
explorerToggleLabel,
|
||||||
explorerToggleAccessibilityState,
|
explorerToggleAccessibilityState,
|
||||||
explorerToggleStyle,
|
|
||||||
t,
|
t,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -4087,18 +4015,19 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
borderRadius: theme.borderRadius.lg,
|
borderRadius: theme.borderRadius.lg,
|
||||||
},
|
},
|
||||||
compactHeaderActionButton: {
|
compactHeaderActionButton: {
|
||||||
width: theme.spacing[8],
|
width: {
|
||||||
height: theme.spacing[8],
|
xs: theme.spacing[8],
|
||||||
|
md: buttonControlHeight.xs,
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
xs: theme.spacing[8],
|
||||||
|
md: buttonControlHeight.xs,
|
||||||
|
},
|
||||||
padding: 0,
|
padding: 0,
|
||||||
borderRadius: theme.borderRadius.lg,
|
borderRadius: theme.borderRadius.lg,
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
},
|
},
|
||||||
explorerPanelButton: {
|
|
||||||
// The 32px trigger and 16px panel glyph leave 8px more trailing space than
|
|
||||||
// the 22px split-pane trigger and its 14px glyph in the row below.
|
|
||||||
marginRight: -theme.spacing[2],
|
|
||||||
},
|
|
||||||
compactHeaderMenuCluster: {
|
compactHeaderMenuCluster: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
@@ -4107,26 +4036,6 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
md: theme.spacing[2],
|
md: theme.spacing[2],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sourceControlButton: {
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
gap: theme.spacing[2],
|
|
||||||
paddingHorizontal: theme.spacing[1],
|
|
||||||
paddingVertical: theme.spacing[1],
|
|
||||||
minHeight: Math.ceil(theme.fontSize.sm * 1.5) + theme.spacing[1] * 2,
|
|
||||||
minWidth: Math.ceil(theme.fontSize.sm * 1.5) + theme.spacing[1] * 2,
|
|
||||||
borderRadius: theme.borderRadius.md,
|
|
||||||
// Match the painted right edge of the trailing split-pane glyph below. The
|
|
||||||
// two header rows intentionally use different control sizes and padding.
|
|
||||||
marginRight: -7,
|
|
||||||
},
|
|
||||||
sourceControlButtonWithStats: {
|
|
||||||
paddingHorizontal: theme.spacing[3],
|
|
||||||
},
|
|
||||||
sourceControlButtonHovered: {
|
|
||||||
backgroundColor: theme.colors.surface2,
|
|
||||||
},
|
|
||||||
newTabActions: {
|
newTabActions: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
@@ -4155,16 +4064,6 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
gap: theme.spacing[2],
|
gap: theme.spacing[2],
|
||||||
},
|
},
|
||||||
newTabTooltipShortcut: {},
|
newTabTooltipShortcut: {},
|
||||||
explorerTooltipRow: {
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: theme.spacing[2],
|
|
||||||
},
|
|
||||||
explorerTooltipText: {
|
|
||||||
fontSize: theme.fontSize.sm,
|
|
||||||
color: theme.colors.popoverForeground,
|
|
||||||
},
|
|
||||||
explorerTooltipShortcut: {},
|
|
||||||
mobileTabsRow: {
|
mobileTabsRow: {
|
||||||
backgroundColor: theme.colors.surface0,
|
backgroundColor: theme.colors.surface0,
|
||||||
borderBottomWidth: theme.borderWidth[1],
|
borderBottomWidth: theme.borderWidth[1],
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import {
|
|||||||
} from "@/utils/workspace-script-links";
|
} from "@/utils/workspace-script-links";
|
||||||
import type { Theme } from "@/styles/theme";
|
import type { Theme } from "@/styles/theme";
|
||||||
import { useWorkspaceServiceRoutePreferencesStore } from "@/workspace-service-routes/store";
|
import { useWorkspaceServiceRoutePreferencesStore } from "@/workspace-service-routes/store";
|
||||||
|
import { buttonControlHeight } from "@/components/ui/control-geometry";
|
||||||
|
|
||||||
type RowActionIcon = "copy" | "open" | "restart" | "start" | "stop" | "terminal";
|
type RowActionIcon = "copy" | "open" | "restart" | "start" | "stop" | "terminal";
|
||||||
|
|
||||||
@@ -742,9 +743,10 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
},
|
},
|
||||||
splitButton: {
|
splitButton: {
|
||||||
|
height: buttonControlHeight.xs,
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "stretch",
|
alignItems: "stretch",
|
||||||
borderRadius: theme.borderRadius.md,
|
borderRadius: theme.borderRadius.lg,
|
||||||
borderWidth: theme.borderWidth[1],
|
borderWidth: theme.borderWidth[1],
|
||||||
borderColor: theme.colors.borderAccent,
|
borderColor: theme.colors.borderAccent,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
@@ -766,7 +768,6 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
},
|
},
|
||||||
splitButtonPrimary: {
|
splitButtonPrimary: {
|
||||||
paddingHorizontal: theme.spacing[3],
|
paddingHorizontal: theme.spacing[3],
|
||||||
paddingVertical: theme.spacing[1],
|
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
},
|
},
|
||||||
splitButtonPrimaryHovered: {
|
splitButtonPrimaryHovered: {
|
||||||
|
|||||||
Reference in New Issue
Block a user