From 617c3c7e70221c1e49d0652729e6b62dacaef62e Mon Sep 17 00:00:00 2001 From: sikongyue <3155157671@qq.com> Date: Thu, 20 Aug 2026 00:50:17 +0800 Subject: [PATCH] =?UTF-8?q?feat(web):=20=E5=B7=A5=E4=BD=9C=E5=8C=BA?= =?UTF-8?q?=E5=B8=83=E5=B1=80=20-=20=E4=BE=A7=E6=A0=8F=E5=88=86=E7=BB=84?= =?UTF-8?q?=E5=AF=BC=E8=88=AA=E6=94=AF=E6=8C=81=E6=8A=98=E5=8F=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 NavGroup 组件:有标题的分组(工作台管理)可点击折叠/展开,Chevron 旋转指示,grid-rows 平滑动画;激活项所在分组自动展开\n- 折叠按钮借鉴 SelectItem 交互:紧凑 28px 高度、hover/focus-visible 浅背景反馈、标签文字与图标随 hover 加深(36% -> 55% / 35% -> 70%)\n- 无标题主分组(核心导航入口)保持常驻;分组标签 padding 移交折叠按钮,样式单一来源 --- .../layout/workspace-sidebar-nav.tsx | 79 +++++++++++++++---- web/src/styles/globals.css | 33 +++++++- 2 files changed, 95 insertions(+), 17 deletions(-) diff --git a/web/src/components/layout/workspace-sidebar-nav.tsx b/web/src/components/layout/workspace-sidebar-nav.tsx index e81a4e9dd..e5c45c1de 100644 --- a/web/src/components/layout/workspace-sidebar-nav.tsx +++ b/web/src/components/layout/workspace-sidebar-nav.tsx @@ -266,6 +266,62 @@ function NavItem({ item, activeId, onSelect, onOpenSearch, onLogout, level = 0 } ); } +function NavGroup({ group, activeId, onNavigate, onOpenSearch, onLogout }: { + group: WorkspaceNavGroup; + activeId: string; + onNavigate: () => void; + onOpenSearch: () => void; + onLogout: () => void; +}) { + const [isOpen, setIsOpen] = useState(true); + const hasActive = group.items.some((item) => item.id === activeId || (item.id === "settings" && activeId.startsWith("settings:"))); + + // 激活项所在分组自动展开,保证当前位置可见。 + useEffect(() => { + if (hasActive) setIsOpen(true); + }, [hasActive]); + + const content = ( +
+ {group.items.map((item) => ( + + ))} +
+ ); + + // 无标题分组(核心导航入口)常驻展示,不做折叠。 + if (!group.heading) { + return
{content}
; + } + + return ( +
+ +
+
{content}
+
+
+ ); +} + export function WorkspaceSidebarNav({ onNavigate, onOpenSearch }: { onNavigate: () => void; onOpenSearch: () => void }) { const { pathname } = useLocation(); const [searchParams] = useSearchParams(); @@ -325,21 +381,14 @@ export function WorkspaceSidebarNav({ onNavigate, onOpenSearch }: { onNavigate: )} > {groups.map((group, index) => ( -
- {group.heading ? {group.heading} : null} -
- {group.items.map((item) => ( - void handleLogout()} - /> - ))} -
-
+ void handleLogout()} + /> ))} diff --git a/web/src/styles/globals.css b/web/src/styles/globals.css index a2d26fc38..cec08d8e9 100644 --- a/web/src/styles/globals.css +++ b/web/src/styles/globals.css @@ -941,15 +941,44 @@ pointer-events: none; } - /* 分组标题:小号大写标签,弱化但可读 */ + /* 分组标题:小号大写标签,弱化但可读;有标题的分组支持折叠,padding/间距由折叠按钮接管 */ .app-workspace-nav-group-label { display: block; - padding: 0 10px 6px; font-size: var(--fs-label); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: color-mix(in srgb, var(--foreground) 36%, transparent); + transition: color var(--motion-instant) ease-out; + } + + .app-workspace-nav-group-toggle { + display: flex; + width: 100%; + min-height: 28px; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 0 8px; + border-radius: var(--r-sm); + text-align: left; + color: inherit; + transition: background-color var(--motion-instant) ease-out; + } + + .app-workspace-nav-group-toggle:hover, + .app-workspace-nav-group-toggle:focus-visible { + background: var(--surface-hover); + } + + .app-workspace-nav-group-toggle:hover .app-workspace-nav-group-label, + .app-workspace-nav-group-toggle:focus-visible .app-workspace-nav-group-label { + color: color-mix(in srgb, var(--foreground) 55%, transparent); + } + + .app-workspace-nav-group-toggle:hover svg, + .app-workspace-nav-group-toggle:focus-visible svg { + color: color-mix(in srgb, var(--foreground) 70%, transparent); } /* 工作区切换器下拉浮层 */