fix(admin): nav bar incorrectly active state (#7870)

This commit is contained in:
JimmFly
2024-09-05 09:35:22 +00:00
parent d5ecf503c2
commit 5c67f98e90
4 changed files with 78 additions and 73 deletions

View File

@@ -91,7 +91,12 @@ export const router = _createBrowserRouter(
},
{
path: 'settings',
lazy: () => import('./modules/settings'),
children: [
{
path: '*',
lazy: () => import('./modules/settings'),
},
],
},
],
},

View File

@@ -21,7 +21,7 @@ const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Header className="flex w-full">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(

View File

@@ -5,9 +5,7 @@ import {
AccordionTrigger,
} from '@affine/admin/components/ui/accordion';
import { useCallback } from 'react';
import { Link } from 'react-router-dom';
import { useNav } from './context';
import { NavLink, useLocation } from 'react-router-dom';
export const CollapsibleItem = ({
items,
@@ -18,7 +16,9 @@ export const CollapsibleItem = ({
items: string[];
changeModule?: (module: string) => void;
}) => {
const { activeSubTab, setActiveSubTab } = useNav();
const location = useLocation();
const activeSubTab = location.hash.slice(1);
const handleClick = useCallback(
(id: string) => {
const targetElement = document.getElementById(id);
@@ -29,36 +29,45 @@ export const CollapsibleItem = ({
});
}
changeModule?.(title);
setActiveSubTab(id);
},
[changeModule, setActiveSubTab, title]
[changeModule, title]
);
return (
<Accordion type="multiple" className="w-full ">
<AccordionItem value="item-1" className="border-b-0">
<Link to={`/admin/settings#${title}`}>
<NavLink
to={`/admin/settings/${title}`}
className={({ isActive }) => {
return isActive
? 'w-full bg-zinc-100 inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50'
: '';
}}
>
<AccordionTrigger
onClick={() => handleClick(title)}
className={`py-2 px-3 rounded ${activeSubTab === title ? 'bg-zinc-100' : ''}`}
className={`py-2 px-3 rounded`}
>
{title}
</AccordionTrigger>
</Link>
<AccordionContent className=" flex flex-col gap-2">
</NavLink>
<AccordionContent className=" flex flex-col gap-2 py-1">
{items.map((item, index) => (
<Link
<NavLink
key={index}
to={`/admin/settings#${item}`}
className="px-3 overflow-hidden"
to={`/admin/settings/${title}#${item}`}
className={({ isActive }) => {
return isActive && activeSubTab === item
? `transition-all overflow-hidden w-full bg-zinc-100 inline-flex items-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50`
: '';
}}
>
<AccordionContent
onClick={() => handleClick(item)}
className={`py-1 px-2 rounded text-ellipsis whitespace-nowrap overflow-hidden ${activeSubTab === item ? 'bg-zinc-100' : ''}`}
className={`py-1 px-2 rounded text-ellipsis whitespace-nowrap overflow-hidden`}
>
{item}
</AccordionContent>
</Link>
</NavLink>
))}
</AccordionContent>
</AccordionItem>

View File

@@ -8,54 +8,38 @@ import { buttonVariants } from '@affine/admin/components/ui/button';
import { cn } from '@affine/admin/utils';
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
import { ClipboardListIcon, SettingsIcon, UsersIcon } from 'lucide-react';
import { useEffect } from 'react';
import { Link } from 'react-router-dom';
import { NavLink } from 'react-router-dom';
import { useGetServerRuntimeConfig } from '../settings/use-get-server-runtime-config';
import { CollapsibleItem } from './collapsible-item';
import { useNav } from './context';
import { UserDropdown } from './user-dropdown';
const TabsMap: { [key: string]: string } = {
accounts: 'Accounts',
ai: 'AI',
config: 'Config',
settings: 'Settings',
};
export function Nav() {
const { moduleList } = useGetServerRuntimeConfig();
const { activeTab, setActiveTab, setCurrentModule } = useNav();
useEffect(() => {
const path = window.location.pathname;
for (const key in TabsMap) {
if (path.includes(key)) {
setActiveTab(TabsMap[key]);
return;
}
}
}, [setActiveTab]);
const { setCurrentModule } = useNav();
return (
<div className="flex flex-col gap-4 py-2 justify-between flex-grow overflow-hidden">
<nav className="flex flex-col gap-1 px-2 flex-grow overflow-hidden">
<Link
<NavLink
to={'/admin/accounts'}
className={cn(
buttonVariants({
variant: activeTab === 'Accounts' ? 'default' : 'ghost',
size: 'sm',
}),
activeTab === 'Accounts' &&
'dark:bg-muted dark:text-white dark:hover:bg-muted dark:hover:text-white',
'justify-start',
'flex-none'
)}
className={({ isActive }) =>
cn(
buttonVariants({
variant: isActive ? 'default' : 'ghost',
size: 'sm',
}),
isActive &&
'dark:bg-muted dark:text-white dark:hover:bg-muted dark:hover:text-white',
'justify-start',
'flex-none'
)
}
>
<UsersIcon className="mr-2 h-4 w-4" />
Accounts
</Link>
</NavLink>
{/* <Link
to={'/admin/ai'}
className={cn(
@@ -72,48 +56,55 @@ export function Nav() {
<CpuIcon className="mr-2 h-4 w-4" />
AI
</Link> */}
<Link
<NavLink
to={'/admin/config'}
className={cn(
buttonVariants({
variant: activeTab === 'Config' ? 'default' : 'ghost',
size: 'sm',
}),
activeTab === 'Config' &&
'dark:bg-muted dark:text-white dark:hover:bg-muted dark:hover:text-white',
'justify-start',
'flex-none'
)}
className={({ isActive }) =>
cn(
buttonVariants({
variant: isActive ? 'default' : 'ghost',
size: 'sm',
}),
isActive &&
'dark:bg-muted dark:text-white dark:hover:bg-muted dark:hover:text-white',
'justify-start',
'flex-none'
)
}
>
<ClipboardListIcon className="mr-2 h-4 w-4" />
Config
</Link>
</NavLink>
<Accordion type="multiple" className="w-full h-full overflow-hidden">
<AccordionItem
value="item-1"
className="border-b-0 h-full flex flex-col gap-1"
className="border-b-0 h-full flex flex-col gap-1 w-full"
>
<Link to={'/admin/settings'}>
<AccordionTrigger
className={cn(
<NavLink
to={'/admin/settings'}
className={({ isActive }) =>
cn(
buttonVariants({
variant: activeTab === 'Settings' ? 'default' : 'ghost',
variant: isActive ? 'default' : 'ghost',
size: 'sm',
}),
activeTab === 'Settings' &&
isActive &&
'dark:bg-muted dark:text-white dark:hover:bg-muted dark:hover:text-white',
'justify-between',
'hover:no-underline'
)}
'justify-start',
'flex-none',
'w-full'
)
}
>
<AccordionTrigger
className={'flex items-center justify-between w-full'}
>
<div className="flex items-center">
<SettingsIcon className="mr-2 h-4 w-4" />
<span>Settings</span>
</div>
</AccordionTrigger>
</Link>
</NavLink>
<AccordionContent className="h-full overflow-hidden w-full">
<ScrollAreaPrimitive.Root