refactor: client side navigation (#135)

This commit is contained in:
Manuel
2024-02-19 18:04:01 +01:00
committed by GitHub
parent 6a02afbfe2
commit a4fc6f6444
2 changed files with 94 additions and 47 deletions

View File

@@ -0,0 +1,70 @@
"use client";
import type { ReactNode } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { NavLink } from "@homarr/ui";
export const CommonNavLink = (props: ClientNavigationLink) =>
"href" in props ? (
<NavLinkHref {...props} />
) : (
<NavLinkWithItems {...props} />
);
const NavLinkHref = (props: NavigationLinkHref) => {
const pathname = usePathname();
return props.external ? (
<NavLink
component="a"
label={props.label}
leftSection={props.icon}
href={props.href}
style={{
borderRadius: 5,
}}
target="_blank"
/>
) : (
<NavLink
component={Link}
label={props.label}
leftSection={props.icon}
href={props.href}
active={pathname === props.href}
style={{
borderRadius: 5,
}}
/>
);
};
const NavLinkWithItems = (props: NavigationLinkWithItems) => (
<NavLink
style={{
borderRadius: 5,
}}
label={props.label}
leftSection={props.icon}
>
{props.items.map((item) => (
<NavLinkHref key={item.label} {...item} />
))}
</NavLink>
);
interface CommonNavigationLinkProps {
label: string;
icon: ReactNode;
}
interface NavigationLinkHref extends CommonNavigationLinkProps {
href: string;
external?: boolean;
}
interface NavigationLinkWithItems extends CommonNavigationLinkProps {
items: NavigationLinkHref[];
}
export type ClientNavigationLink = NavigationLinkHref | NavigationLinkWithItems;

View File

@@ -1,12 +1,8 @@
import Link from "next/link";
import {
AppShellNavbar,
AppShellSection,
NavLink,
ScrollArea,
} from "@homarr/ui";
import type { TablerIconsProps } from "@homarr/ui";
import { AppShellNavbar, AppShellSection, ScrollArea } from "@homarr/ui";
import type { ClientNavigationLink } from "./navigation-link";
import { CommonNavLink } from "./navigation-link";
interface MainNavigationProps {
headerSection?: JSX.Element;
@@ -28,51 +24,31 @@ export const MainNavigation = ({
mb={footerSection ? "md" : undefined}
component={ScrollArea}
>
{links.map((link) => (
<CommonNavLink key={link.label} {...link} />
))}
{links.map((link, index) => {
const { icon: TablerIcon, ...props } = link;
const Icon = <TablerIcon size={20} stroke={1.5} />;
let clientLink: ClientNavigationLink;
if ("items" in props) {
clientLink = {
...props,
items: props.items.map((item) => {
return {
...item,
icon: <item.icon size={20} stroke={1.5} />,
};
}),
} as ClientNavigationLink;
} else {
clientLink = props as ClientNavigationLink;
}
return <CommonNavLink key={index} {...clientLink} icon={Icon} />;
})}
</AppShellSection>
{footerSection && <AppShellSection>{footerSection}</AppShellSection>}
</AppShellNavbar>
);
};
const CommonNavLink = (props: NavigationLink) =>
"href" in props ? (
<NavLinkHref {...props} />
) : (
<NavLinkWithItems {...props} />
);
const NavLinkHref = (props: NavigationLinkHref) =>
props.external ? (
<NavLink
component="a"
label={props.label}
leftSection={<props.icon size={20} stroke={1.5} />}
href={props.href}
target="_blank"
/>
) : (
<NavLink
component={Link}
label={props.label}
leftSection={<props.icon size={20} stroke={1.5} />}
href={props.href}
/>
);
const NavLinkWithItems = (props: NavigationLinkWithItems) => (
<NavLink
label={props.label}
leftSection={<props.icon size={20} stroke={1.5} />}
>
{props.items.map((item) => (
<NavLinkHref key={item.label} {...item} />
))}
</NavLink>
);
interface CommonNavigationLinkProps {
label: string;
icon: (props: TablerIconsProps) => JSX.Element;
@@ -85,4 +61,5 @@ interface NavigationLinkHref extends CommonNavigationLinkProps {
interface NavigationLinkWithItems extends CommonNavigationLinkProps {
items: NavigationLinkHref[];
}
export type NavigationLink = NavigationLinkHref | NavigationLinkWithItems;