Fix bottom/top nav: highlight only the most specific matching link (e.g. /bookings/new no longer also lights up Бронирования)
This commit is contained in:
1 parent
b6c604feaf
commit
4f206c2ddc
3 files changed
+19
-6
No files matched your search
@@ -4,7 +4,7 @@ import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { MoreHorizontal, X } from "lucide-react";
|
||||
import { links, PRIMARY_COUNT } from "./nav-data";
|
||||
import { links, PRIMARY_COUNT, isLinkActive } from "./nav-data";
|
||||
|
||||
export function MobileNav({ isAdmin }: { isAdmin: boolean }) {
|
||||
const pathname = usePathname();
|
||||
@@ -13,10 +13,10 @@ export function MobileNav({ isAdmin }: { isAdmin: boolean }) {
|
||||
const visibleLinks = links.filter((link) => !link.adminOnly || isAdmin);
|
||||
const primary = visibleLinks.slice(0, PRIMARY_COUNT);
|
||||
const overflow = visibleLinks.slice(PRIMARY_COUNT);
|
||||
const overflowActive = overflow.some((l) => pathname.startsWith(l.href));
|
||||
const overflowActive = overflow.some((l) => isLinkActive(l, pathname, visibleLinks));
|
||||
|
||||
function isActive(link: (typeof links)[number]) {
|
||||
return link.exact ? pathname === link.href : pathname.startsWith(link.href);
|
||||
return isLinkActive(link, pathname, visibleLinks);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -23,3 +23,15 @@ export const links: NavLink[] = [
|
||||
];
|
||||
|
||||
export const PRIMARY_COUNT = 4;
|
||||
|
||||
/**
|
||||
* Highlights only the most specific match — e.g. on "/bookings/new", both it
|
||||
* (exact) and "/bookings" (prefix) technically match; without this, both
|
||||
* would light up at once. Picks the matching link with the longest href.
|
||||
*/
|
||||
export function isLinkActive(link: NavLink, pathname: string, allLinks: NavLink[]): boolean {
|
||||
const matches = allLinks.filter((l) => (l.exact ? pathname === l.href : pathname.startsWith(l.href)));
|
||||
if (matches.length === 0) return false;
|
||||
const best = matches.reduce((a, b) => (b.href.length > a.href.length ? b : a));
|
||||
return best.href === link.href;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { links } from "./nav-data";
|
||||
import { links, isLinkActive } from "./nav-data";
|
||||
|
||||
export function NavLinks({ isAdmin }: { isAdmin: boolean }) {
|
||||
const pathname = usePathname();
|
||||
@@ -10,8 +10,9 @@ export function NavLinks({ isAdmin }: { isAdmin: boolean }) {
|
||||
|
||||
return (
|
||||
<nav className="flex items-center gap-1">
|
||||
{visibleLinks.map(({ href, label, icon: Icon, exact }) => {
|
||||
const active = exact ? pathname === href : pathname.startsWith(href);
|
||||
{visibleLinks.map((link) => {
|
||||
const { href, label, icon: Icon } = link;
|
||||
const active = isLinkActive(link, pathname, visibleLinks);
|
||||
return (
|
||||
<Link
|
||||
key={href}
|
||||
|
||||
Reference in new issue
Block a user