From 521aafe993be56060baec7d9e3e0b5b8d26049fa Mon Sep 17 00:00:00 2001 From: michaelhan Date: Sat, 25 Jul 2026 01:36:06 -0700 Subject: [PATCH] Sidebar settings: hide a lone unpinned tab, match New chat icon, rename Profile menu - With exactly one tab unpinned, both More and that tab are dropped, so nothing is drawn for it (previously it rendered inline). The page stays reachable by URL. - The customizer's New chat preview uses PencilEdit02Icon, the icon the real row renders; Edit03Icon was a different glyph. - "Sidebar menu" is now "Profile menu", described as the shortcuts behind your name at the bottom of the sidebar, so it no longer reads as a second name for the navigation section above it. --- studio/backend/routes/settings.py | 4 ++-- studio/frontend/src/components/app-sidebar.tsx | 6 +++--- .../components/sidebar-nav-customizer.tsx | 18 +++++++++--------- .../settings/stores/appearance-custom-store.ts | 4 ++-- studio/frontend/src/i18n/locales/en.ts | 6 +++--- studio/frontend/src/i18n/locales/zh-CN.ts | 6 +++--- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/studio/backend/routes/settings.py b/studio/backend/routes/settings.py index 73fbb2dbed..796b0f5ac4 100644 --- a/studio/backend/routes/settings.py +++ b/studio/backend/routes/settings.py @@ -735,8 +735,8 @@ SIDEBAR_MENU_ITEM_DEFAULTS = { } # Navigable sidebar rows the user can pin/reorder; the boolean is each id's -# default pin state, matching the shipped layout. An unpinned row moves into the -# "More" flyout client-side, so it stays reachable. +# default pin state, matching the shipped layout. Unpinned rows collect in the +# "More" flyout client-side; a single unpinned row is hidden there instead. SIDEBAR_NAV_ITEM_DEFAULTS = { "projects": True, "hub": True, diff --git a/studio/frontend/src/components/app-sidebar.tsx b/studio/frontend/src/components/app-sidebar.tsx index 5bb7434d3e..449b138af3 100644 --- a/studio/frontend/src/components/app-sidebar.tsx +++ b/studio/frontend/src/components/app-sidebar.tsx @@ -829,11 +829,11 @@ export function AppSidebar() { .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. + // appears once it would hold two or more. With exactly one row unpinned, both + // the menu and that row are dropped -- the page stays reachable by URL. const overflowNavIds = unpinnedNavIds.length > 1 ? unpinnedNavIds : []; const inlineNavIds = sidebarNav - .filter((item) => item.pinned || overflowNavIds.length === 0) + .filter((item) => item.pinned) .map((item) => item.id); const showSidebarBrand = !usesCustomTitlebar; diff --git a/studio/frontend/src/features/settings/components/sidebar-nav-customizer.tsx b/studio/frontend/src/features/settings/components/sidebar-nav-customizer.tsx index fb23dca4ae..e0bf096871 100644 --- a/studio/frontend/src/features/settings/components/sidebar-nav-customizer.tsx +++ b/studio/frontend/src/features/settings/components/sidebar-nav-customizer.tsx @@ -6,11 +6,11 @@ import { DashboardCircleIcon, DownloadSquare01Icon, DragDropVerticalIcon, - Edit03Icon, FlimSlateIcon, Folder01Icon, Image03Icon, MoreHorizontalIcon, + PencilEdit02Icon, } from "@hugeicons/core-free-icons"; import { HugeiconsIcon } from "@hugeicons/react"; import { Reorder, useDragControls } from "motion/react"; @@ -107,11 +107,11 @@ function MovableRow({ item }: { item: SidebarNavItemPref }) { } /** - * Pin and reorder the sidebar navigation rows. A row with its switch off moves - * into the "More" flyout instead of disappearing, so every page stays reachable - * -- unless it is the only unpinned row, which stays inline (a menu holding one - * item earns nothing). New chat renders as a static row: it is an action pinned - * to the top, not a destination. + * Pin and reorder the sidebar navigation rows. Rows with their switch off collect + * in the "More" flyout. A single unpinned row is hidden outright instead: More + * would be a menu of one, so neither it nor the row is drawn (the page stays + * reachable by URL). New chat renders as a static row: it is an action pinned to + * the top, not a destination. */ export function SidebarNavCustomizer() { const t = useT(); @@ -120,7 +120,7 @@ export function SidebarNavCustomizer() { const unpinnedCount = sidebarNav.filter((item) => !item.pinned).length; return (
- + item.id)} @@ -138,8 +138,8 @@ export function SidebarNavCustomizer() { ))} {/* 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. */} + row, and a single unpinned row is hidden rather than sitting behind a + menu built for one item. */} {unpinnedCount > 1 && ( <>
diff --git a/studio/frontend/src/features/settings/stores/appearance-custom-store.ts b/studio/frontend/src/features/settings/stores/appearance-custom-store.ts index 1efcaea2ba..758f33902f 100644 --- a/studio/frontend/src/features/settings/stores/appearance-custom-store.ts +++ b/studio/frontend/src/features/settings/stores/appearance-custom-store.ts @@ -86,8 +86,8 @@ export const SIDEBAR_MENU_DEFAULT_VISIBLE: Record = * Sidebar NAVIGATION rows the user can pin and reorder (distinct from the * 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. + * "More" flyout. A single unpinned row is hidden outright rather than getting a + * flyout of one; the page stays reachable by URL. */ 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 56e4f3c632..041dafc419 100644 --- a/studio/frontend/src/i18n/locales/en.ts +++ b/studio/frontend/src/i18n/locales/en.ts @@ -519,15 +519,15 @@ 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, unless it is the only one left. New chat stays fixed.", + "Pin and reorder the sidebar tabs. Unpinned tabs collect in the More menu; a single unpinned tab is hidden instead of getting a menu of one. New chat stays fixed.", dragToReorder: "Drag to reorder", pinToSidebar: "Pin {name} to the sidebar", moreHolds: "More ({count})", }, sidebarMenu: { - title: "Sidebar menu", + title: "Profile menu", description: - "Show, hide, and reorder items in the sidebar profile menu. Settings, Help, Log out, and Shutdown stay fixed.", + "Choose which shortcuts appear when you click your name at the bottom of the sidebar, and in what order. Settings, Help, Log out, and Shutdown always appear.", darkModeToggle: "Dark mode toggle", dragToReorder: "Drag to reorder", }, diff --git a/studio/frontend/src/i18n/locales/zh-CN.ts b/studio/frontend/src/i18n/locales/zh-CN.ts index 416b0b87f0..ad579e2c86 100644 --- a/studio/frontend/src/i18n/locales/zh-CN.ts +++ b/studio/frontend/src/i18n/locales/zh-CN.ts @@ -373,15 +373,15 @@ export const zhCN = { sidebarNav: { title: "侧边栏导航", description: - "固定并重新排序侧边栏标签。取消固定的项目会移入“更多”菜单而不是被隐藏;若仅剩一项,则直接显示。新聊天保持固定。", + "固定并重新排序侧边栏标签。取消固定的标签会收进“更多”菜单;若只有一个取消固定,则直接隐藏,而不是为它单独建一个菜单。新聊天保持固定。", dragToReorder: "拖动以重新排序", pinToSidebar: "将{name}固定到侧边栏", moreHolds: "更多({count})", }, sidebarMenu: { - title: "侧边栏菜单", + title: "个人菜单", description: - "显示、隐藏和重新排序侧边栏个人菜单中的项目。设置、帮助、退出登录和关闭保持固定。", + "选择点击侧边栏底部你的名字时显示哪些快捷项及其顺序。设置、帮助、退出登录和关闭始终显示。", darkModeToggle: "深色模式切换", dragToReorder: "拖动以重新排序", },