quickshell-web/src/components/navigation/sidebars/nav/index.tsx

93 lines
2.2 KiB
TypeScript

import {
createSignal,
createEffect,
onMount,
onCleanup,
type Component,
} from "solid-js";
import { LoadingSpinner, MenuToX, XToMenu } from "@icons";
import { Tree } from "./Tree";
import type { NavProps } from "../types";
const NavComponent: Component<NavProps> = props => {
const [open, setOpen] = createSignal<boolean>(false);
const { tree, mobile, routes } = props;
let navRef: HTMLDivElement;
if (!tree) {
return <LoadingSpinner />;
}
function toggle(e: MouseEvent) {
e.preventDefault();
setOpen(!open());
}
if (!mobile) {
return (
<Tree
currentRoute={tree.currentRoute}
currentModule={tree.currentModule || null}
currentClass={tree.currentClass || null}
items={routes}
/>
);
}
const handleClickOutside = (event: MouseEvent) => {
const isLink = "href" in (event.target || {});
const isInBody = document.body.contains(event.target as Node);
if (
isLink ||
!isInBody ||
(isInBody && !navRef.contains(event.target as Node))
) {
setOpen(false);
}
};
onMount(() => {
onCleanup(() => {
window.removeEventListener("click", handleClickOutside);
});
});
createEffect(() => {
if (open()) {
window.addEventListener("click", handleClickOutside);
document.body.classList.add("overflow-nav");
document.body.classList.add("dim-content-nav");
} else {
window.removeEventListener("click", handleClickOutside);
document.body.classList.remove("overflow-nav");
document.body.classList.remove("dim-content-nav");
}
});
return (
<div
class="nav-toggle"
ref={navRef!}
>
<div onclick={e => toggle(e)}>
<MenuToX class={`nav-icon ${open() ? "active" : ""}`} />
<XToMenu class={`nav-icon ${!open() ? "active" : ""}`} />
</div>
<div
id={open() ? "#qs_search" : ""}
class={`nav-items ${open() ? "shown" : ""}`}
>
<Tree
currentRoute={tree.currentRoute}
currentModule={tree.currentModule}
currentClass={tree.currentClass}
items={routes}
/>
</div>
</div>
);
};
export default NavComponent;