new-personal-site/components/lib/elements/HeaderNavLinkComponent.tsx
Benjamin Toby a0a0ab8ee4 Updates
2025-07-20 10:35:54 +01:00

142 lines
5.6 KiB
TypeScript

import React, { DetailedHTMLProps, HTMLAttributes, ReactNode } from "react";
import { twMerge } from "tailwind-merge";
import Row from "../layout/Row";
import HeaderLink from "./HeaderLink";
import { ChevronDown } from "lucide-react";
import Dropdown from "./Dropdown";
import { TwuiHeaderLink } from "./HeaderNav";
import Card from "./Card";
import Stack from "../layout/Stack";
import Button from "../layout/Button";
/**
* # Header Nav Main Link Component
* @className twui-header-nav-link-component
* @className twui-header-nav-link-icon
* @className twui-header-nav-link-dropdown
*/
export default function HeaderNavLinkComponent({
link,
dropdown,
}: {
link: TwuiHeaderLink;
dropdown?: ReactNode;
}) {
const isDropdown = dropdown || link.dropdown || link.children?.[0];
const mainLinkComponent = (
<Row className="gap-0 grow">
<HeaderLink link={link} strict={link.strict} />
{isDropdown && (
<ChevronDown
className={twMerge(
"hidden xl:flex xl:-ml-1",
"twui-header-nav-link-icon"
)}
size={20}
/>
)}
</Row>
);
const [showMobileDropdown, setShowMobileDropdown] = React.useState(false);
return (
<div
className={twMerge(
"relative w-full xl:w-auto [&_a.active]:font-bold",
"twui-header-nav-link-component"
)}
>
{isDropdown ? (
<React.Fragment>
<Stack className="flex xl:hidden w-full">
<Row className="w-full justify-between">
{mainLinkComponent}
<Button
variant="ghost"
onClick={() =>
setShowMobileDropdown(!showMobileDropdown)
}
title="Header Links Dropdown Button"
>
<ChevronDown
className={twMerge(
"twui-header-nav-link-icon !text-link dark:!text-white"
)}
size={20}
/>
</Button>
</Row>
{showMobileDropdown && (
<Stack className="w-full">
{dropdown ? (
dropdown
) : link.children?.[0] ? (
<Card
className={twMerge(
"w-full p-0",
"twui-header-nav-link-dropdown"
)}
>
<Stack className="w-full items-stretch gap-0 py-2">
{link.children.map(
(_ch, _index) => {
return (
<HeaderLink
link={_ch}
key={_index}
className="px-6 py-4"
/>
);
}
)}
</Stack>
</Card>
) : link.dropdown ? (
link.dropdown
) : null}
</Stack>
)}
</Stack>
<Dropdown
target={mainLinkComponent}
position="bottom-right"
hoverOpen
className="hidden xl:flex"
>
{dropdown ? (
dropdown
) : link.children?.[0] ? (
<Card
className={twMerge(
"min-w-[200px] mt-2 p-0",
"twui-header-nav-link-dropdown"
)}
>
<Stack className="w-full items-stretch gap-0 py-2">
{link.children.map((_ch, _index) => {
return (
<HeaderLink
link={_ch}
key={_index}
className="px-6 py-4"
/>
);
})}
</Stack>
</Card>
) : link.dropdown ? (
link.dropdown
) : null}
</Dropdown>
</React.Fragment>
) : (
mainLinkComponent
)}
</div>
);
}