diff --git a/studio/frontend/src/components/app-sidebar.tsx b/studio/frontend/src/components/app-sidebar.tsx index 85404b8887..5bb7434d3e 100644 --- a/studio/frontend/src/components/app-sidebar.tsx +++ b/studio/frontend/src/components/app-sidebar.tsx @@ -825,12 +825,16 @@ export function AppSidebar() { }, }, }; - const pinnedNavIds = sidebarNav - .filter((item) => item.pinned) - .map((item) => item.id); - const overflowNavIds = sidebarNav + const unpinnedNavIds = sidebarNav .filter((item) => !item.pinned) .map((item) => item.id); + // A flyout wrapping a single row costs a click and earns nothing, so More only + // appears once it would hold two or more; a lone unpinned row renders inline, + // in its saved order position. + const overflowNavIds = unpinnedNavIds.length > 1 ? unpinnedNavIds : []; + const inlineNavIds = sidebarNav + .filter((item) => item.pinned || overflowNavIds.length === 0) + .map((item) => item.id); const showSidebarBrand = !usesCustomTitlebar; const showCompactMacBrand = showSidebarBrand && usesNativeMacTitlebar; @@ -1612,7 +1616,7 @@ export function AppSidebar() { {/* Rows come from the saved pin order (Settings -> Appearance -> Sidebar navigation). Pinned ids render here in order; the rest fall into the More flyout below, so nothing is unreachable. */} - {pinnedNavIds.map((id) => { + {inlineNavIds.map((id) => { const row = navRows[id]; return ( - item.id)} @@ -138,9 +137,10 @@ export function SidebarNavCustomizer() { ))} - {/* Only meaningful once something is unpinned -- with everything pinned the - sidebar has no More row at all. */} - {unpinnedCount > 0 && ( + {/* Only meaningful at two or more: with everything pinned there is no More + row, and a lone unpinned row renders inline rather than hiding behind + a menu built for one item. */} + {unpinnedCount > 1 && ( <>
= /** * Sidebar NAVIGATION rows the user can pin and reorder (distinct from the - * profile-menu entries above). New Chat and Search stay fixed at the top: they - * are actions, not destinations. Array order is render order; an unpinned row - * moves into the "More" flyout rather than disappearing, so no page becomes - * unreachable. + * profile-menu entries above). New chat stays fixed at the top: it is an action, + * not a destination. Array order is render order; an unpinned row moves into the + * "More" flyout rather than disappearing, so no page becomes unreachable -- + * except when it is the only unpinned row, which renders inline instead. */ export const SIDEBAR_NAV_ITEM_IDS = [ "projects", diff --git a/studio/frontend/src/i18n/locales/en.ts b/studio/frontend/src/i18n/locales/en.ts index 00f84248d5..56e4f3c632 100644 --- a/studio/frontend/src/i18n/locales/en.ts +++ b/studio/frontend/src/i18n/locales/en.ts @@ -519,7 +519,7 @@ export const en = { sidebarNav: { title: "Sidebar navigation", description: - "Pin and reorder the sidebar tabs. Anything unpinned moves into the More menu instead of being hidden. New chat and Search stay fixed.", + "Pin and reorder the sidebar tabs. Anything unpinned moves into the More menu instead of being hidden, unless it is the only one left. New chat stays fixed.", dragToReorder: "Drag to reorder", pinToSidebar: "Pin {name} to the sidebar", moreHolds: "More ({count})", diff --git a/studio/frontend/src/i18n/locales/zh-CN.ts b/studio/frontend/src/i18n/locales/zh-CN.ts index 859a3e435d..416b0b87f0 100644 --- a/studio/frontend/src/i18n/locales/zh-CN.ts +++ b/studio/frontend/src/i18n/locales/zh-CN.ts @@ -373,7 +373,7 @@ export const zhCN = { sidebarNav: { title: "侧边栏导航", description: - "固定并重新排序侧边栏标签。取消固定的项目会移入“更多”菜单而不是被隐藏。新聊天和搜索保持固定。", + "固定并重新排序侧边栏标签。取消固定的项目会移入“更多”菜单而不是被隐藏;若仅剩一项,则直接显示。新聊天保持固定。", dragToReorder: "拖动以重新排序", pinToSidebar: "将{name}固定到侧边栏", moreHolds: "更多({count})",