Files
ThothII/frontend/src/shell/ArchiveNavigation.tsx
T

40 lines
2.1 KiB
TypeScript

import { useEffect, useLayoutEffect, useRef, useState, type ReactNode } from "react";
import { Button } from "../components/ui/button";
import { Dialog, DialogContent, DialogDescription, DialogTitle, DialogTrigger } from "../components/ui/dialog";
/** Measure the embedded application, which can be narrower than the viewport. */
export function ArchiveNavigation({ surface, forceDrawer = false, children }: { surface: string; forceDrawer?: boolean; children: ReactNode }) {
const marker = useRef<HTMLSpanElement>(null);
const [narrow, setNarrow] = useState(false);
const [open, setOpen] = useState(false);
useLayoutEffect(() => {
const shell = marker.current?.closest<HTMLElement>(".thot-app-shell");
if (!shell) return;
const update = () => {
const width = shell.getBoundingClientRect().width || window.innerWidth;
const collapsed = forceDrawer || width < (surface === "core" ? 768 : 1000);
setNarrow(collapsed);
shell.dataset.administrationNarrow = String(collapsed);
};
update();
const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(update) : null;
observer?.observe(shell);
window.addEventListener("resize", update);
return () => { observer?.disconnect(); window.removeEventListener("resize", update); delete shell.dataset.administrationNarrow; };
}, [surface, forceDrawer]);
useEffect(() => { setOpen(false); }, [surface, narrow]);
const anchor = <span ref={marker} hidden />;
if (!narrow) return <>{anchor}{children}</>;
return <>{anchor}<Dialog open={open} onOpenChange={setOpen}>
<div className="thot-administration-mobile-nav">
<span className="font-heading font-semibold">ThothII</span>
<DialogTrigger render={<Button variant="outline" size="sm" />}>Navigation</DialogTrigger>
</div>
<DialogContent className="flex max-h-[calc(100dvh-2rem)] flex-col">
<DialogTitle>Navigation</DialogTitle>
<DialogDescription className="sr-only">Choose an administration page or a session.</DialogDescription>
<div className="min-h-0 overflow-y-auto [&>aside]:w-full">{children}</div>
</DialogContent>
</Dialog></>;
}