+
+ {/* PR title row: truncates with a hover tooltip only when the
+ visible text is cut off. */}
+ {showPrTitleRow && (
+
+
+
+
+ {prTitle}
+
+
+
+ {prTitle}
+
+
+
+ )}
{/* Content */}
- {view.type === "remote" ? (
+ {effectiveView.type === "remote" ? (
= ({
/>
) : (
= ({
);
};
+
+// ---------------------------------------------------------------
+// Git view switcher: dropdown for the active PR/Branch/Working view.
+// ---------------------------------------------------------------
+
+interface GitViewSwitcherProps {
+ items: ReadonlyArray
;
+ activeItem?: ViewItem;
+ /**
+ * Whether a remote (PR or Branch) item exists in `items`. Controls
+ * whether local entries are visually nested (indented) under it.
+ */
+ hasRemoteItem: boolean;
+ onSelect: (item: ViewItem) => void;
+}
+
+const GitViewSwitcher: FC = ({
+ items,
+ activeItem,
+ hasRemoteItem,
+ onSelect,
+}) => {
+ if (!activeItem) {
+ return (
+
+
+ No changes
+
+ );
+ }
+
+ const isSingleItem = items.length <= 1;
+
+ const triggerContent = (
+ <>
+
+
+ {activeItem.icon}
+
+ {activeItem.stateLabel}
+
+
+ {activeItem.triggerIdentifier}
+ {!isSingleItem && (
+
+ )}
+
+ >
+ );
+
+ if (isSingleItem) {
+ return (
+
+ {triggerContent}
+
+ );
+ }
+
+ return (
+
+
+
+
+
+ {items.map((item) => {
+ const isActive = item.id === activeItem.id;
+ return (
+ onSelect(item)}
+ className={cn(
+ "flex items-center gap-2 rounded-sm px-2 py-1.5 text-xs",
+ // Nest local entries under the remote/PR entry
+ // when one exists. Without a parent above them,
+ // nesting reads as an orphan indent.
+ item.kind === "local" && hasRemoteItem
+ ? "ml-4 mt-0.5"
+ : "w-full",
+ isActive && "bg-surface-secondary text-content-primary",
+ )}
+ >
+
+ {item.icon}
+
+
+ {item.itemPrimary}
+
+ {item.itemSecondary && (
+
+ {item.itemSecondary}
+
+ )}
+
+ );
+ })}
+
+
+ );
+};
+
// ---------------------------------------------------------------
// Remote view (branch/PR diff)
// ---------------------------------------------------------------
@@ -470,7 +689,7 @@ const RepoHeader: FC<{
- {repo.branch?.trim() || repoTabLabel(repoRoot)}
+ {repo.branch?.trim() || repoLabel(repoRoot)}
{repoRoot}
@@ -494,7 +713,33 @@ const RepoHeader: FC<{
};
// ---------------------------------------------------------------
-// PR state icon (compact, for the tab bar)
+// PR state helpers
+// ---------------------------------------------------------------
+
+/** Human-readable state label for the view-switcher trigger. */
+function prStateLabel(state: string | undefined, draft: boolean | undefined) {
+ if (state === "merged") return "Merged";
+ if (state === "closed") return "Closed";
+ if (draft) return "Draft";
+ return "Open";
+}
+
+/** Tailwind classes for the state pill on the view-switcher trigger. */
+function prStateClasses(state: string | undefined, draft: boolean | undefined) {
+ if (state === "merged") {
+ return "text-git-merged-bright";
+ }
+ if (state === "closed") {
+ return "text-git-deleted-bright";
+ }
+ if (draft) {
+ return "text-content-secondary";
+ }
+ return "text-git-added-bright";
+}
+
+// ---------------------------------------------------------------
+// PR state icon (compact, for the view switcher)
// ---------------------------------------------------------------
export const PrStateIcon: FC<{
@@ -502,24 +747,15 @@ export const PrStateIcon: FC<{
draft?: boolean;
className?: string;
}> = ({ state, draft, className }) => {
+ const colorClass = prStateClasses(state, draft);
if (state === "merged") {
- return ;
+ return ;
}
if (state === "closed") {
- return (
-
- );
+ return ;
}
if (draft) {
- return (
-
- );
+ return ;
}
- return (
-
- );
+ return ;
};