refactor(nav): unify navigation links with Button asChild pattern
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
import { Bell, CreditCard, Settings, ShieldCheck } from "lucide-react"
|
import { Bell, CreditCard, Settings, ShieldCheck } from "lucide-react"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
@@ -23,19 +24,17 @@ export function AccountSidebar() {
|
|||||||
const Icon = link.icon
|
const Icon = link.icon
|
||||||
const isActive = pathname === link.href
|
const isActive = pathname === link.href
|
||||||
return (
|
return (
|
||||||
<Link
|
<Button
|
||||||
key={link.href}
|
key={link.href}
|
||||||
href={link.href}
|
variant={isActive ? "secondary" : "ghost"}
|
||||||
className={cn(
|
className={cn("w-full justify-start", !isActive && "text-muted-foreground")}
|
||||||
"flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors",
|
asChild
|
||||||
isActive
|
|
||||||
? "bg-accent text-accent-foreground"
|
|
||||||
: "text-muted-foreground hover:text-foreground hover:bg-accent/50",
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
|
<Link href={link.href}>
|
||||||
<Icon className="h-4 w-4" />
|
<Icon className="h-4 w-4" />
|
||||||
{link.label}
|
{link.label}
|
||||||
</Link>
|
</Link>
|
||||||
|
</Button>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { useAuthStore } from "@/store/auth"
|
import { useAuthStore } from "@/store/auth"
|
||||||
|
|
||||||
@@ -49,19 +50,17 @@ export function DashboardSidebar() {
|
|||||||
const Icon = link.icon
|
const Icon = link.icon
|
||||||
const isActive = pathname === link.href
|
const isActive = pathname === link.href
|
||||||
return (
|
return (
|
||||||
<Link
|
<Button
|
||||||
key={link.href}
|
key={link.href}
|
||||||
href={link.href}
|
variant={isActive ? "secondary" : "ghost"}
|
||||||
className={cn(
|
className={cn("w-full justify-start", !isActive && "text-muted-foreground")}
|
||||||
"flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors",
|
asChild
|
||||||
isActive
|
|
||||||
? "bg-accent text-accent-foreground"
|
|
||||||
: "text-muted-foreground hover:text-foreground hover:bg-accent/50",
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
|
<Link href={link.href}>
|
||||||
<Icon className="h-4 w-4" />
|
<Icon className="h-4 w-4" />
|
||||||
{link.label}
|
{link.label}
|
||||||
</Link>
|
</Link>
|
||||||
|
</Button>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ export function Header() {
|
|||||||
{isAuthenticated && (
|
{isAuthenticated && (
|
||||||
<div className="border-t pt-4">
|
<div className="border-t pt-4">
|
||||||
<p className="px-3 text-xs text-muted-foreground mb-2">切换身份</p>
|
<p className="px-3 text-xs text-muted-foreground mb-2">切换身份</p>
|
||||||
<div className="flex gap-1 px-3">
|
<div className="flex gap-2 px-3">
|
||||||
{availableRoles.map(([role, label]) => (
|
{availableRoles.map(([role, label]) => (
|
||||||
<Button
|
<Button
|
||||||
key={role}
|
key={role}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import type * as React from "react"
|
|||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-200 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium transition-all duration-200 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
@@ -21,10 +21,10 @@ const buttonVariants = cva(
|
|||||||
size: {
|
size: {
|
||||||
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
||||||
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
||||||
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
sm: "h-8 gap-1.5 px-3 has-[>svg]:px-2.5",
|
||||||
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
lg: "h-10 px-6 has-[>svg]:px-4",
|
||||||
icon: "size-9",
|
icon: "size-9",
|
||||||
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
"icon-xs": "size-6 rounded-sm [&_svg:not([class*='size-'])]:size-3",
|
||||||
"icon-sm": "size-8",
|
"icon-sm": "size-8",
|
||||||
"icon-lg": "size-10",
|
"icon-lg": "size-10",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user