chore: enhance sidebar navigation and localization features

- Refactor the `SidebarMain` component to improve active link detection and enhance user experience with collapsible menus.
- Introduce `useLocalePathname` for better path management and implement functions to check active states for sidebar items.
- Update `SidebarUser` component layout for improved readability and consistency in locale display.
- Replace `UserIcon` with `User2Icon` in the `UserAvatar` component for a more modern appearance.
This commit is contained in:
javayhu 2025-03-15 17:59:12 +08:00
parent f7e5297589
commit 03f00c7d37
3 changed files with 38 additions and 15 deletions

View File

@ -7,7 +7,6 @@ import {
} from '@/components/ui/collapsible';
import {
SidebarGroup,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
@ -16,27 +15,41 @@ import {
SidebarMenuSubItem
} from '@/components/ui/sidebar';
import { getSidebarMainLinks } from '@/config';
import { LocaleLink } from '@/i18n/navigation';
import { LocaleLink, useLocalePathname } from '@/i18n/navigation';
import { createTranslator } from '@/i18n/translator';
import { MenuItem } from '@/types';
import { ChevronRight } from 'lucide-react';
import { useTranslations } from 'next-intl';
import * as React from 'react';
export function SidebarMain() {
const t = useTranslations();
const translator = createTranslator(t);
const sidebarMainLinks = getSidebarMainLinks(translator);
const pathname = useLocalePathname();
// Function to check if a path is active
const isActive = (href: string | undefined): boolean => {
if (!href) return false;
return pathname === href || pathname.startsWith(href + '/');
};
// Function to check if any sub-item in a collapsible menu is active
const hasActiveChild = (items: MenuItem[]): boolean => {
if (!items?.length) return false;
return items.some(item => isActive(item.href));
};
return (
<SidebarGroup>
{/* <SidebarGroupLabel>Platform</SidebarGroupLabel> */}
<SidebarMenu>
{sidebarMainLinks.map((item) => (
<>
<React.Fragment key={item.title}>
{item.items?.length ? (
<Collapsible
key={item.title}
asChild
defaultOpen={false}
defaultOpen={hasActiveChild(item.items)}
className="group/collapsible"
>
<SidebarMenuItem>
@ -53,7 +66,10 @@ export function SidebarMain() {
<SidebarMenuSub>
{item.items?.map((subItem) => (
<SidebarMenuSubItem key={subItem.title}>
<SidebarMenuSubButton asChild>
<SidebarMenuSubButton
asChild
isActive={isActive(subItem.href)}
>
<LocaleLink href={subItem.href || ''}>
{subItem.icon ? subItem.icon : null}
<span>{subItem.title}</span>
@ -67,16 +83,19 @@ export function SidebarMain() {
</Collapsible>
) : (
<SidebarMenuItem>
<SidebarMenuButton asChild tooltip={item.title}>
<SidebarMenuButton
asChild
tooltip={item.title}
isActive={isActive(item.href)}
>
<LocaleLink href={item.href || ''}>
{item.icon ? item.icon : null}
<span>{item.title}</span>
</LocaleLink>
</SidebarMenuButton>
</SidebarMenuItem>
)
}
</>
)}
</React.Fragment>
))}
</SidebarMenu>
</SidebarGroup>

View File

@ -175,8 +175,12 @@ export function SidebarUser() {
onClick={() => setLocale(localeOption)}
className="cursor-pointer"
>
<span className="mr-2 text-md">{LOCALE_LIST[localeOption].flag}</span>
<span className="text-sm">{LOCALE_LIST[localeOption].name}</span>
<span className="mr-2 text-md">
{LOCALE_LIST[localeOption].flag}
</span>
<span className="text-sm">
{LOCALE_LIST[localeOption].name}
</span>
</DropdownMenuItem>
))}
</DropdownMenuSubContent>

View File

@ -1,6 +1,6 @@
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import type { AvatarProps } from '@radix-ui/react-avatar';
import { UserIcon } from 'lucide-react';
import { User2Icon } from 'lucide-react';
interface UserAvatarProps extends AvatarProps {
name?: string;
@ -25,8 +25,8 @@ export function UserAvatar({ name, image, ...props }: UserAvatarProps) {
/>
<AvatarFallback>
<span className="sr-only">{name}</span>
<UserIcon className="size-4" />
{/* {getInitials(name)} */}
<User2Icon className="size-4" />
{/* {getInitials(name || '')} */}
</AvatarFallback>
</Avatar>
);