feat(app): polish workspace tabs and changes
Size tabs from rendered labels and switch to horizontal overflow once minimum click targets are reached, keeping the add-tab action adjacent until it must remain fixed. Make Changes an always-expanded document with an optional desktop navigation tree, keep Git actions in their platform-owned headers, remove pinned and inline split shortcuts, and place review tabs beside Changes.
This commit is contained in:
@@ -94,7 +94,7 @@ export function BranchSwitcher({
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={t("branchSwitcher.currentBranch", { branchName: currentBranchName })}
|
||||
>
|
||||
<ThemedGitBranch size={14} uniProps={foregroundMutedIconColorMapping} />
|
||||
<ThemedGitBranch size={12} uniProps={foregroundMutedIconColorMapping} />
|
||||
<Text style={styles.branchLabel} numberOfLines={1}>
|
||||
{currentBranchName}
|
||||
</Text>
|
||||
@@ -132,8 +132,7 @@ const styles = StyleSheet.create((theme) => ({
|
||||
gap: theme.spacing[1],
|
||||
minWidth: 0,
|
||||
paddingVertical: theme.spacing[1],
|
||||
paddingHorizontal: theme.spacing[2],
|
||||
marginLeft: -theme.spacing[2],
|
||||
paddingHorizontal: theme.spacing[1],
|
||||
borderRadius: theme.borderRadius.md,
|
||||
flexShrink: 1,
|
||||
},
|
||||
@@ -141,9 +140,9 @@ const styles = StyleSheet.create((theme) => ({
|
||||
backgroundColor: theme.colors.surface1,
|
||||
},
|
||||
branchLabel: {
|
||||
fontSize: theme.fontSize.sm,
|
||||
color: theme.colors.foreground,
|
||||
fontWeight: theme.fontWeight.medium,
|
||||
fontSize: theme.fontSize.xs,
|
||||
color: theme.colors.foregroundMuted,
|
||||
fontWeight: theme.fontWeight.normal,
|
||||
flexShrink: 1,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -18,7 +18,7 @@ import { usePanelStore, selectIsFileExplorerOpen, type ExplorerTab } from "@/sto
|
||||
import { useCloseFileExplorerGesture } from "@/mobile-panels/gestures";
|
||||
import { MobilePanelOverlay } from "@/mobile-panels/presentation";
|
||||
import { HEADER_INNER_HEIGHT } from "@/constants/layout";
|
||||
import { GitDiffPane } from "@/git/diff-pane";
|
||||
import { ChangesSurface } from "@/git/diff-pane";
|
||||
import { FileExplorerPane } from "./file-explorer-pane";
|
||||
import { useKeyboardShiftStyle } from "@/hooks/use-keyboard-shift-style";
|
||||
import { useHasOwnedWindowChromeObstruction, WindowChromeSafeArea } from "@/utils/desktop-window";
|
||||
@@ -433,7 +433,7 @@ function ChangedFilesPane({
|
||||
>) {
|
||||
const { addFile, canAddToChat } = useAddFileToChat({ serverId, workspaceId });
|
||||
return (
|
||||
<GitDiffPane
|
||||
<ChangesSurface
|
||||
host="explorer"
|
||||
serverId={serverId}
|
||||
workspaceId={workspaceId}
|
||||
|
||||
@@ -1007,7 +1007,7 @@ function SplitPaneView({
|
||||
buildPaneContentModel,
|
||||
onFocusPane,
|
||||
onSplitPane: _onSplitPane,
|
||||
onSplitPaneEmpty,
|
||||
onSplitPaneEmpty: _onSplitPaneEmpty,
|
||||
onReorderTabsInPane,
|
||||
renderPaneEmptyState,
|
||||
activeDragTabId,
|
||||
@@ -1114,15 +1114,6 @@ function SplitPaneView({
|
||||
},
|
||||
[onReorderTabsInPane, paneId],
|
||||
);
|
||||
const handleSplitRight = useCallback(
|
||||
() => onSplitPaneEmpty({ targetPaneId: paneId, position: "right" }),
|
||||
[onSplitPaneEmpty, paneId],
|
||||
);
|
||||
const handleSplitDown = useCallback(
|
||||
() => onSplitPaneEmpty({ targetPaneId: paneId, position: "bottom" }),
|
||||
[onSplitPaneEmpty, paneId],
|
||||
);
|
||||
|
||||
return (
|
||||
<RenderProfile id={`SplitPaneView:${pane.id}`}>
|
||||
<View ref={paneRef} collapsable={false} style={styles.pane}>
|
||||
@@ -1151,8 +1142,6 @@ function SplitPaneView({
|
||||
onCreateBrowserTab={onCreateBrowserTab}
|
||||
showCreateBrowserTab={showCreateBrowserTab}
|
||||
onReorderTabs={handleReorderTabs}
|
||||
onSplitRight={handleSplitRight}
|
||||
onSplitDown={handleSplitDown}
|
||||
externalDndContext
|
||||
activeDragTabId={activeDragTabId}
|
||||
tabDropPreviewIndex={
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { ReactElement } from "react";
|
||||
import { SquareTerminal } from "lucide-react-native";
|
||||
import { withUnistyles } from "react-native-unistyles";
|
||||
import { getProviderIcon } from "@/components/provider-icons";
|
||||
import type { Theme } from "@/styles/theme";
|
||||
|
||||
const mutedColorMapping = (theme: Theme) => ({ color: theme.colors.foregroundMuted });
|
||||
|
||||
const ThemedSquareTerminal = withUnistyles(SquareTerminal);
|
||||
|
||||
function ProviderProfileIcon({
|
||||
iconKey,
|
||||
size,
|
||||
color = "",
|
||||
}: {
|
||||
iconKey: string;
|
||||
size: number;
|
||||
color?: string;
|
||||
}) {
|
||||
const Icon = getProviderIcon(iconKey);
|
||||
return <Icon size={size} color={color} />;
|
||||
}
|
||||
|
||||
const ThemedProviderProfileIcon = withUnistyles(ProviderProfileIcon);
|
||||
|
||||
export function TerminalProfileIcon({ iconKey }: { iconKey: string | undefined }): ReactElement {
|
||||
if (!iconKey) {
|
||||
return <ThemedSquareTerminal size={14} uniProps={mutedColorMapping} />;
|
||||
}
|
||||
return <ThemedProviderProfileIcon iconKey={iconKey} size={14} uniProps={mutedColorMapping} />;
|
||||
}
|
||||
Reference in New Issue
Block a user