Prefer specific active navigation links
This commit is contained in:
@ -19,15 +19,19 @@ function matchesPath(currentPath: string, href: string) {
|
||||
return currentPath === href || currentPath.startsWith(`${href}/`);
|
||||
}
|
||||
|
||||
function findActiveHref(currentPath: string, items: Array<{ href: string }>) {
|
||||
return items
|
||||
.filter((item) => matchesPath(currentPath, item.href))
|
||||
.sort((a, b) => b.href.length - a.href.length)[0]?.href;
|
||||
}
|
||||
|
||||
export function MobileNav({ pathname, userRole }: MobileNavProps) {
|
||||
const { dict } = useLocale();
|
||||
const navigation = useMemo(() => getNavigationForRole(userRole as AppRole), [userRole]);
|
||||
const buildOpenGroups = () => {
|
||||
const grouped = navigation.filter(isNavGroup);
|
||||
return grouped.reduce<Record<string, boolean>>((acc, item) => {
|
||||
const isGroupActive = item.children.some(
|
||||
(child) => matchesPath(pathname, child.href)
|
||||
);
|
||||
const isGroupActive = Boolean(findActiveHref(pathname, item.children));
|
||||
acc[item.key] = isGroupActive;
|
||||
return acc;
|
||||
}, {});
|
||||
@ -39,9 +43,7 @@ export function MobileNav({ pathname, userRole }: MobileNavProps) {
|
||||
setOpenGroups((current) => {
|
||||
const next = { ...current };
|
||||
navigation.filter(isNavGroup).forEach((item) => {
|
||||
const isGroupActive = item.children.some(
|
||||
(child) => matchesPath(pathname, child.href)
|
||||
);
|
||||
const isGroupActive = Boolean(findActiveHref(pathname, item.children));
|
||||
if (isGroupActive) {
|
||||
next[item.key] = true;
|
||||
}
|
||||
@ -55,9 +57,8 @@ export function MobileNav({ pathname, userRole }: MobileNavProps) {
|
||||
<div className="space-y-2 pb-1">
|
||||
{navigation.map((item) => {
|
||||
if (isNavGroup(item)) {
|
||||
const isGroupActive = item.children.some(
|
||||
(child) => matchesPath(pathname, child.href)
|
||||
);
|
||||
const activeChildHref = findActiveHref(pathname, item.children);
|
||||
const isGroupActive = Boolean(activeChildHref);
|
||||
const isOpen = openGroups[item.key] ?? isGroupActive;
|
||||
return (
|
||||
<div key={item.key} className="rounded border border-line/70 bg-slate-50">
|
||||
@ -83,8 +84,7 @@ export function MobileNav({ pathname, userRole }: MobileNavProps) {
|
||||
{isOpen ? (
|
||||
<div className="grid gap-2 border-t border-line/70 bg-white p-2">
|
||||
{item.children.map((child) => {
|
||||
const isActive =
|
||||
matchesPath(pathname, child.href);
|
||||
const isActive = activeChildHref === child.href;
|
||||
return (
|
||||
<Link
|
||||
key={child.href}
|
||||
|
||||
@ -20,15 +20,19 @@ function matchesPath(currentPath: string, href: string) {
|
||||
return currentPath === href || currentPath.startsWith(`${href}/`);
|
||||
}
|
||||
|
||||
function findActiveHref(currentPath: string, items: Array<{ href: string }>) {
|
||||
return items
|
||||
.filter((item) => matchesPath(currentPath, item.href))
|
||||
.sort((a, b) => b.href.length - a.href.length)[0]?.href;
|
||||
}
|
||||
|
||||
export function Sidebar({ pathname, user }: SidebarProps) {
|
||||
const { dict } = useLocale();
|
||||
const navigation = useMemo(() => getNavigationForRole(user.role as never), [user.role]);
|
||||
const buildOpenGroups = () => {
|
||||
const grouped = navigation.filter(isNavGroup);
|
||||
return grouped.reduce<Record<string, boolean>>((acc, item) => {
|
||||
const isGroupActive = item.children.some(
|
||||
(child) => matchesPath(pathname, child.href)
|
||||
);
|
||||
const isGroupActive = Boolean(findActiveHref(pathname, item.children));
|
||||
acc[item.key] = isGroupActive;
|
||||
return acc;
|
||||
}, {});
|
||||
@ -40,9 +44,7 @@ export function Sidebar({ pathname, user }: SidebarProps) {
|
||||
setOpenGroups((current) => {
|
||||
const next = { ...current };
|
||||
navigation.filter(isNavGroup).forEach((item) => {
|
||||
const isGroupActive = item.children.some(
|
||||
(child) => matchesPath(pathname, child.href)
|
||||
);
|
||||
const isGroupActive = Boolean(findActiveHref(pathname, item.children));
|
||||
if (isGroupActive) {
|
||||
next[item.key] = true;
|
||||
}
|
||||
@ -70,9 +72,8 @@ export function Sidebar({ pathname, user }: SidebarProps) {
|
||||
<nav className="space-y-1 pr-1">
|
||||
{navigation.map((item) => {
|
||||
if (isNavGroup(item)) {
|
||||
const isGroupActive = item.children.some(
|
||||
(child) => matchesPath(pathname, child.href)
|
||||
);
|
||||
const activeChildHref = findActiveHref(pathname, item.children);
|
||||
const isGroupActive = Boolean(activeChildHref);
|
||||
const isOpen = openGroups[item.key] ?? isGroupActive;
|
||||
|
||||
return (
|
||||
@ -108,8 +109,7 @@ export function Sidebar({ pathname, user }: SidebarProps) {
|
||||
{isOpen ? (
|
||||
<div className="mt-1 space-y-1 pl-3">
|
||||
{item.children.map((child) => {
|
||||
const isActive =
|
||||
matchesPath(pathname, child.href);
|
||||
const isActive = activeChildHref === child.href;
|
||||
|
||||
return (
|
||||
<Link
|
||||
|
||||
Reference in New Issue
Block a user