1
0
Fork 0

refactor(sidebar): use next/link for client-side navigation

This commit is contained in:
Jason Fraley 2026-08-02 02:04:12 -04:00
parent 01f4820f2e
commit 6cce6116b8
4 changed files with 30 additions and 10 deletions

View file

@ -1,5 +1,6 @@
"use client" "use client"
import Link from "next/link"
import { ChevronRight, type LucideIcon } from "lucide-react" import { ChevronRight, type LucideIcon } from "lucide-react"
import { import {
@ -44,10 +45,10 @@ export function NavCore({
<Collapsible key={item.title} asChild defaultOpen={item.isActive}> <Collapsible key={item.title} asChild defaultOpen={item.isActive}>
<SidebarMenuItem> <SidebarMenuItem>
<SidebarMenuButton asChild tooltip={item.title}> <SidebarMenuButton asChild tooltip={item.title}>
<a href={item.url}> <Link href={item.url}>
<item.icon /> <item.icon />
<span>{item.title}</span> <span>{item.title}</span>
</a> </Link>
</SidebarMenuButton> </SidebarMenuButton>
{item.items?.length ? ( {item.items?.length ? (
<> <>
@ -62,10 +63,10 @@ export function NavCore({
{item.items?.map((subItem) => ( {item.items?.map((subItem) => (
<SidebarMenuSubItem key={subItem.title}> <SidebarMenuSubItem key={subItem.title}>
<SidebarMenuSubButton asChild> <SidebarMenuSubButton asChild>
<a href={subItem.url}> <Link href={subItem.url}>
{subItem.icon ? <subItem.icon /> : null} {subItem.icon ? <subItem.icon /> : null}
<span>{subItem.title}</span> <span>{subItem.title}</span>
</a> </Link>
</SidebarMenuSubButton> </SidebarMenuSubButton>
</SidebarMenuSubItem> </SidebarMenuSubItem>
))} ))}

View file

@ -1,5 +1,6 @@
"use client" "use client"
import Link from "next/link"
import { import {
Folder, Folder,
MoreHorizontal, MoreHorizontal,
@ -43,10 +44,10 @@ export function NavProjects({
{projects.map((item) => ( {projects.map((item) => (
<SidebarMenuItem key={item.name}> <SidebarMenuItem key={item.name}>
<SidebarMenuButton asChild> <SidebarMenuButton asChild>
<a href={item.url}> <Link href={item.url}>
<item.icon /> <item.icon />
<span>{item.name}</span> <span>{item.name}</span>
</a> </Link>
</SidebarMenuButton> </SidebarMenuButton>
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>

View file

@ -1,4 +1,5 @@
import * as React from "react" import * as React from "react"
import Link from "next/link"
import { type LucideIcon } from "lucide-react" import { type LucideIcon } from "lucide-react"
import { import {
@ -26,10 +27,10 @@ export function NavSecondary({
{items.map((item) => ( {items.map((item) => (
<SidebarMenuItem key={item.title}> <SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild size="sm"> <SidebarMenuButton asChild size="sm">
<a href={item.url}> <Link href={item.url}>
<item.icon /> <item.icon />
<span>{item.title}</span> <span>{item.title}</span>
</a> </Link>
</SidebarMenuButton> </SidebarMenuButton>
</SidebarMenuItem> </SidebarMenuItem>
))} ))}

View file

@ -2,6 +2,8 @@
import { BadgeCheck, Bell, ChevronsUpDown, CreditCard, FileTextIcon, LogOut, Sparkles } from "lucide-react"; import { BadgeCheck, Bell, ChevronsUpDown, CreditCard, FileTextIcon, LogOut, Sparkles } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { import {
@ -30,6 +32,21 @@ export function NavUser({
}; };
}) { }) {
const { isMobile } = useSidebar(); const { isMobile } = useSidebar();
const router = useRouter();
const [loggingOut, setLoggingOut] = useState(false);
const handleLogout = async () => {
setLoggingOut(true);
try {
await fetch("/api/users/logout", { method: "POST" });
} catch {
// ignore network errors; redirect anyway
} finally {
setLoggingOut(false);
}
router.push("/");
router.refresh();
};
return ( return (
<SidebarMenu> <SidebarMenu>
@ -92,9 +109,9 @@ export function NavUser({
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuGroup> </DropdownMenuGroup>
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<DropdownMenuItem> <DropdownMenuItem onSelect={() => handleLogout()}>
<LogOut /> <LogOut />
Log out {loggingOut ? "Logging out..." : "Log out"}
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>