feat: improve admin panel design (#14464)

This commit is contained in:
DarkSky
2026-02-17 17:40:29 +08:00
committed by GitHub
parent 850e646ab9
commit 8f833388eb
86 changed files with 2633 additions and 1431 deletions

View File

@@ -5,10 +5,9 @@ import {
import { Separator } from '@affine/admin/components/ui/separator';
import { TooltipProvider } from '@affine/admin/components/ui/tooltip';
import { cn } from '@affine/admin/utils';
import { cssVarV2 } from '@toeverything/theme/v2';
import { AlignJustifyIcon } from 'lucide-react';
import type { PropsWithChildren, ReactNode, RefObject } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type { ImperativePanelHandle } from 'react-resizable-panels';
import { useLocation } from 'react-router-dom';
@@ -23,7 +22,6 @@ import {
} from '../components/ui/sheet';
import { Logo } from './accounts/components/logo';
import { useMediaQuery } from './common';
import { NavContext } from './nav/context';
import { Nav } from './nav/nav';
import {
PanelContext,
@@ -43,10 +41,6 @@ export function Layout({ children }: PropsWithChildren) {
const leftPanelRef = useRef<ImperativePanelHandle>(null);
const location = useLocation();
const [activeTab, setActiveTab] = useState('');
const [activeSubTab, setActiveSubTab] = useState('server');
const [currentModule, setCurrentModule] = useState('server');
const handleLeftExpand = useCallback(() => {
if (leftPanelRef.current?.getSize() === 0) {
leftPanelRef.current?.resize(30);
@@ -127,60 +121,66 @@ export function Layout({ children }: PropsWithChildren) {
handleSetRightPanelContent(null);
closeRightPanel();
}, [location.pathname, closeRightPanel, handleSetRightPanelContent]);
const panelContextValue = useMemo(
() => ({
leftPanel: {
isOpen: leftOpen,
panelContent: leftPanelContent,
setPanelContent: setLeftPanelContent,
togglePanel: toggleLeftPanel,
openPanel: openLeftPanel,
closePanel: closeLeftPanel,
},
rightPanel: {
isOpen: rightOpen,
panelContent: rightPanelContent,
setPanelContent: handleSetRightPanelContent,
togglePanel: toggleRightPanel,
openPanel: openRightPanel,
closePanel: closeRightPanel,
hasDirtyChanges: rightPanelHasDirtyChanges,
setHasDirtyChanges: setRightPanelHasDirtyChanges,
},
}),
[
closeLeftPanel,
closeRightPanel,
handleSetRightPanelContent,
leftOpen,
leftPanelContent,
openLeftPanel,
openRightPanel,
rightOpen,
rightPanelContent,
rightPanelHasDirtyChanges,
setLeftPanelContent,
setRightPanelHasDirtyChanges,
toggleLeftPanel,
toggleRightPanel,
]
);
return (
<PanelContext.Provider
value={{
leftPanel: {
isOpen: leftOpen,
panelContent: leftPanelContent,
setPanelContent: setLeftPanelContent,
togglePanel: toggleLeftPanel,
openPanel: openLeftPanel,
closePanel: closeLeftPanel,
},
rightPanel: {
isOpen: rightOpen,
panelContent: rightPanelContent,
setPanelContent: handleSetRightPanelContent,
togglePanel: toggleRightPanel,
openPanel: openRightPanel,
closePanel: closeRightPanel,
hasDirtyChanges: rightPanelHasDirtyChanges,
setHasDirtyChanges: setRightPanelHasDirtyChanges,
},
}}
>
<NavContext.Provider
value={{
activeTab,
activeSubTab,
currentModule,
setActiveTab,
setActiveSubTab,
setCurrentModule,
}}
>
<TooltipProvider delayDuration={0}>
<div className="flex h-screen w-full overflow-hidden">
<ResizablePanelGroup direction="horizontal">
<LeftPanel
panelRef={leftPanelRef as RefObject<ImperativePanelHandle>}
onExpand={handleLeftExpand}
onCollapse={handleLeftCollapse}
/>
<ResizablePanel id="1" order={1} minSize={50} defaultSize={50}>
{children}
</ResizablePanel>
<RightPanel
panelRef={rightPanelRef as RefObject<ImperativePanelHandle>}
onExpand={handleRightExpand}
onCollapse={handleRightCollapse}
/>
</ResizablePanelGroup>
</div>
</TooltipProvider>
</NavContext.Provider>
<PanelContext.Provider value={panelContextValue}>
<TooltipProvider delayDuration={0}>
<div className="flex h-dvh w-full overflow-hidden">
<ResizablePanelGroup direction="horizontal">
<LeftPanel
panelRef={leftPanelRef as RefObject<ImperativePanelHandle>}
onExpand={handleLeftExpand}
onCollapse={handleLeftCollapse}
/>
<ResizablePanel id="1" order={1} minSize={50} defaultSize={50}>
{children}
</ResizablePanel>
<RightPanel
panelRef={rightPanelRef as RefObject<ImperativePanelHandle>}
onExpand={handleRightExpand}
onCollapse={handleRightCollapse}
/>
</ResizablePanelGroup>
</div>
</TooltipProvider>
</PanelContext.Provider>
);
}
@@ -197,7 +197,11 @@ export const LeftPanel = ({
return (
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" className="fixed top-5 left-6 p-0 h-5 w-5">
<Button
variant="ghost"
className="fixed left-4 top-4 z-20 h-8 w-8 rounded-lg border border-border bg-background/95 p-0 shadow-1 backdrop-blur"
size="icon"
>
<AlignJustifyIcon size={20} />
</Button>
</SheetTrigger>
@@ -207,11 +211,15 @@ export const LeftPanel = ({
Admin panel for managing accounts, AI, config, and settings
</SheetDescription>
</SheetHeader>
<SheetContent side="left" className="p-0" withoutCloseButton>
<SheetContent
side="left"
className="w-64 border-r border-border/60 bg-sidebar-bg p-0"
withoutCloseButton
>
<div className="flex flex-col w-full h-full">
<div
className={cn(
'flex h-[52px] items-center gap-2 px-4 text-base font-medium'
'flex h-14 items-center gap-2 border-b border-border px-4 text-base font-semibold text-sidebar-foreground'
)}
>
<Logo />
@@ -239,21 +247,13 @@ export const LeftPanel = ({
onCollapse={onCollapse}
className={cn(
isCollapsed ? 'min-w-[57px] max-w-[57px]' : 'min-w-56 max-w-56',
'border-r h-dvh'
'h-dvh overflow-visible border-r border-border/60 bg-sidebar-bg'
)}
style={{ overflow: 'visible' }}
>
<div
className="flex flex-col max-w-56 h-full "
style={{
backgroundColor: cssVarV2(
'selfhost/layer/background/sidebarBg/sidebarBg'
),
}}
>
<div className="flex h-full max-w-56 flex-col">
<div
className={cn(
'flex h-[56px] items-center px-4 text-base font-medium',
'flex h-14 items-center px-4 text-base font-semibold text-sidebar-foreground',
isCollapsed && 'justify-center px-2'
)}
>
@@ -299,7 +299,11 @@ export const RightPanel = ({
For displaying additional information
</SheetDescription>
</SheetHeader>
<SheetContent side="right" className="p-0" withoutCloseButton>
<SheetContent
side="right"
className="border-l border-border/60 bg-background p-0"
withoutCloseButton
>
<div className="h-full overflow-y-auto">{panelContent}</div>
</SheetContent>
</Sheet>
@@ -317,7 +321,7 @@ export const RightPanel = ({
collapsedSize={0}
onExpand={onExpand}
onCollapse={onCollapse}
className="border-l max-w-96"
className="max-w-96 border-l border-border/60 bg-background"
>
<div className="h-full overflow-y-auto">{panelContent}</div>
</ResizablePanel>