feat(ui): add collapsible persistent sidebar

This commit is contained in:
Logan.Li committed 2026-08-06 17:56:55 +08:00
1 parent 9ce71795b8
commit 101d2164b4
13 files changed
+153 -29

No files matched your search

+25 -3
View File
@@ -8,6 +8,7 @@
*/
import type { ReactNode } from 'react'
import { PanelLeft } from 'lucide-react'
import Sidebar from '../components/layout/Sidebar'
import TabBar from '../components/layout/TabBar'
import TabContent from '../components/layout/TabContent'
@@ -20,6 +21,7 @@ export interface AppShellProps {
isMobile: boolean
sidebarCollapsed: boolean
mobileSidebarOpen: boolean
onToggleSidebar: () => void
onToggleMobileSidebar: () => void
onCloseMobileSidebar: () => void
onNewSession: () => void
@@ -63,11 +65,26 @@ function MobileMenuButton({ onClick }: { onClick: () => void }) {
)
}
function ExpandSidebarButton({ onClick }: { onClick: () => void }) {
return (
<button
type="button"
onClick={onClick}
className="titlebar-no-drag flex h-10 w-10 flex-shrink-0 items-center justify-center border-r border-dark-700/40 text-txt-muted transition-colors hover:bg-dark-700/60 hover:text-content-primary"
title="展开侧栏 (Ctrl/Cmd+B)"
aria-label="展开侧栏"
>
<PanelLeft className="h-4 w-4" />
</button>
)
}
export default function AppShell({
activeTabId,
isMobile,
sidebarCollapsed,
mobileSidebarOpen,
onToggleSidebar,
onToggleMobileSidebar,
onCloseMobileSidebar,
onNewSession,
@@ -91,6 +108,8 @@ export default function AppShell({
if (isMobile) onCloseMobileSidebar()
}
const desktopSidebarHidden = !isMobile && sidebarCollapsed
return (
<div className="flex h-screen flex-col overflow-hidden bg-dark-900 text-content-primary">
<TitleBar />
@@ -105,24 +124,27 @@ export default function AppShell({
)}
<aside
className={`titlebar-no-drag h-full flex-shrink-0 transition-all duration-300 ease-in-out ${
className={`titlebar-no-drag h-full flex-shrink-0 transition-[width,transform] duration-200 ease-in-out ${
isMobile
? `fixed inset-y-0 left-0 top-10 z-50 ${mobileSidebarOpen ? 'translate-x-0' : '-translate-x-full'}`
: sidebarCollapsed
? 'w-0 overflow-hidden'
: desktopSidebarHidden
? 'w-0 overflow-hidden border-0'
: ''
} `}
aria-hidden={desktopSidebarHidden}
>
<Sidebar
onNewSession={handleSidebarNewSession}
onQuickConnect={handleSidebarQuickConnect}
onEditSession={handleSidebarEditSession}
onCollapse={isMobile ? undefined : onToggleSidebar}
/>
</aside>
<main className="flex min-w-0 flex-1 flex-col bg-dark-800">
<div className="flex items-stretch">
{isMobile && <MobileMenuButton onClick={onToggleMobileSidebar} />}
{desktopSidebarHidden && <ExpandSidebarButton onClick={onToggleSidebar} />}
<div className="min-w-0 flex-1">
<TabBar onOpenLauncher={onOpenLauncher} />
</div>