diff --git a/src/types/host-sidebar-preferences.ts b/src/types/host-sidebar-preferences.ts
index 3013559b2..3b455c5dd 100644
--- a/src/types/host-sidebar-preferences.ts
+++ b/src/types/host-sidebar-preferences.ts
@@ -49,6 +49,8 @@ export interface HostSidebarDisplayPreferences {
statusColorScheme: StatusColorScheme;
/** When true, a host row needs a double click to launch its session. */
openOnDoubleClick: boolean;
+ /** When false, nested folders hide the parent-path breadcrumb before their name. */
+ showFolderPaths: boolean;
}
export interface HostSidebarPreferences {
@@ -130,6 +132,7 @@ export function defaultHostSidebarPreferences(): HostSidebarPreferences {
trayTrigger: "always",
statusColorScheme: "accent",
openOnDoubleClick: false,
+ showFolderPaths: true,
},
};
}
@@ -203,6 +206,10 @@ export function sanitizeHostSidebarPreferences(
typeof displayObj.openOnDoubleClick === "boolean"
? displayObj.openOnDoubleClick
: defaults.display.openOnDoubleClick,
+ showFolderPaths:
+ typeof displayObj.showFolderPaths === "boolean"
+ ? displayObj.showFolderPaths
+ : defaults.display.showFolderPaths,
};
return {
diff --git a/src/ui/locales/en.json b/src/ui/locales/en.json
index dbb09e03f..5acff02c5 100644
--- a/src/ui/locales/en.json
+++ b/src/ui/locales/en.json
@@ -1404,6 +1404,8 @@
"actionsClick": "Click to expand/collapse",
"openOnDoubleClick": "Open on double click",
"openOnDoubleClickDesc": "Require a double click to open a host session instead of a single click",
+ "showFolderPaths": "Show folder paths",
+ "showFolderPathsDesc": "Show the parent folder path above nested subfolder names. Subfolders stay indented either way.",
"deletedHost": "Deleted {{name}}",
"copiedToClipboard": "Copied to clipboard",
"terminalUrlCopied": "Terminal URL copied",
diff --git a/src/ui/sidebar/CustomizeSidebarPanel.tsx b/src/ui/sidebar/CustomizeSidebarPanel.tsx
index 56bad5c59..a1c5c8961 100644
--- a/src/ui/sidebar/CustomizeSidebarPanel.tsx
+++ b/src/ui/sidebar/CustomizeSidebarPanel.tsx
@@ -97,6 +97,20 @@ export function CustomizeSidebarPanel({
}
/>
+
+
+ update((prev) => ({
+ ...prev,
+ display: { ...prev.display, showFolderPaths: v },
+ }))
+ }
+ />
+
diff --git a/src/ui/sidebar/HostsPanel.tsx b/src/ui/sidebar/HostsPanel.tsx
index 5508d5dfe..5c49685f6 100644
--- a/src/ui/sidebar/HostsPanel.tsx
+++ b/src/ui/sidebar/HostsPanel.tsx
@@ -1076,6 +1076,7 @@ export function HostsPanel({
trayTrigger={sidebarPrefs.display.trayTrigger}
showTags={sidebarPrefs.display.showTags}
openOnDoubleClick={sidebarPrefs.display.openOnDoubleClick}
+ showFolderPaths={sidebarPrefs.display.showFolderPaths}
/>
)}
diff --git a/src/ui/sidebar/tree/FolderItem/FolderItem.tsx b/src/ui/sidebar/tree/FolderItem/FolderItem.tsx
index 55d55701c..1b52f010c 100644
--- a/src/ui/sidebar/tree/FolderItem/FolderItem.tsx
+++ b/src/ui/sidebar/tree/FolderItem/FolderItem.tsx
@@ -68,6 +68,7 @@ export function FolderItem({
trayTrigger = "hover",
showTags = true,
openOnDoubleClick = false,
+ showFolderPaths = true,
arrangeMode = false,
isDragging = false,
onReorderDrop,
@@ -115,6 +116,8 @@ export function FolderItem({
trayTrigger?: HostTrayTrigger;
showTags?: boolean;
openOnDoubleClick?: boolean;
+ /** When false, nested folders hide the parent-path breadcrumb before their name. */
+ showFolderPaths?: boolean;
/** When true (rearranging unlocked), the header can be dragged and its
* top/bottom edges become reorder drop zones. The middle still accepts
* hosts dropped into the folder. */
@@ -152,7 +155,8 @@ export function FolderItem({
// Nested folders show their parent path as a muted breadcrumb so depth stays
// legible even when a folder is reached via search auto-expand rather than
// by manually opening every ancestor.
- const pathSegments = isGroup ? [] : folderPath.split(" / ");
+ const pathSegments =
+ isGroup || !showFolderPaths ? [] : folderPath.split(" / ");
const breadcrumb =
pathSegments.length > 1 ? pathSegments.slice(0, -1).join(" / ") : null;
const folderHosts = collectAllHosts(folder.children);
@@ -337,6 +341,7 @@ export function FolderItem({
trayTrigger={trayTrigger}
showTags={showTags}
openOnDoubleClick={openOnDoubleClick}
+ showFolderPaths={showFolderPaths}
arrangeMode={arrangeMode}
onReorderDrop={onReorderDrop}
onFolderDragStart={onFolderDragStart}
diff --git a/src/ui/sidebar/tree/SidebarTree.tsx b/src/ui/sidebar/tree/SidebarTree.tsx
index b8c5cc5a8..59931a4ab 100644
--- a/src/ui/sidebar/tree/SidebarTree.tsx
+++ b/src/ui/sidebar/tree/SidebarTree.tsx
@@ -87,6 +87,7 @@ export function SidebarTree({
trayTrigger = "hover",
showTags = true,
openOnDoubleClick = false,
+ showFolderPaths = true,
}: {
children: (Host | HostFolder)[];
onOpenTab: (
@@ -108,6 +109,8 @@ export function SidebarTree({
trayTrigger?: HostTrayTrigger;
showTags?: boolean;
openOnDoubleClick?: boolean;
+ /** When false, nested folders hide the parent-path breadcrumb before their name. */
+ showFolderPaths?: boolean;
}) {
const { t } = useTranslation();
// Knobs with no other owner come straight from the interface preset; the
@@ -996,6 +999,7 @@ export function SidebarTree({
trayTrigger={trayTrigger}
showTags={showTags}
openOnDoubleClick={openOnDoubleClick}
+ showFolderPaths={showFolderPaths}
arrangeMode={arrangeMode}
isDragging={
draggedReorderKey === `folder:${item.path ?? item.name}`
diff --git a/src/ui/tests/types/host-sidebar-preferences.test.ts b/src/ui/tests/types/host-sidebar-preferences.test.ts
index 6e457ae44..ca468e9fc 100644
--- a/src/ui/tests/types/host-sidebar-preferences.test.ts
+++ b/src/ui/tests/types/host-sidebar-preferences.test.ts
@@ -26,6 +26,7 @@ describe("defaultHostSidebarPreferences", () => {
trayTrigger: "always",
statusColorScheme: "accent",
openOnDoubleClick: false,
+ showFolderPaths: true,
},
});
});
@@ -63,6 +64,7 @@ describe("sanitizeHostSidebarPreferences", () => {
trayTrigger: "click",
statusColorScheme: "status",
openOnDoubleClick: true,
+ showFolderPaths: false,
},
};
expect(sanitizeHostSidebarPreferences(valid)).toEqual(valid);
@@ -78,6 +80,16 @@ describe("sanitizeHostSidebarPreferences", () => {
).toBe(false);
});
+ it("defaults showFolderPaths to true when missing or not a boolean", () => {
+ expect(
+ sanitizeHostSidebarPreferences({ display: {} }).display.showFolderPaths,
+ ).toBe(true);
+ expect(
+ sanitizeHostSidebarPreferences({ display: { showFolderPaths: "no" } })
+ .display.showFolderPaths,
+ ).toBe(true);
+ });
+
it("falls back to defaults for invalid enum values", () => {
const result = sanitizeHostSidebarPreferences({
sort: { key: "not-a-real-key", pinnedFirst: "yes" },