Files
cyclone/src/components/Layout.tsx
T

39 lines
1.3 KiB
TypeScript

import { Outlet } from "react-router-dom";
import { useIsFetching } from "@tanstack/react-query";
import { Sidebar } from "./Sidebar";
export function Layout() {
// useIsFetching() returns the number of in-flight queries and is 0 on
// first load (queries that have not yet fired are not counted). We use it
// to drive a 1px hairline scan element at the very top of the layout.
const isFetching = useIsFetching();
const showScan = isFetching > 0;
return (
<div className="relative min-h-screen z-10">
{/*
Scan element — always in the DOM (no layout shift), 1px tall, full
width. pointer-events-none so it never blocks clicks. The inner
bar uses the `scan` keyframe from tailwind.config to slide a 1/3-
width electric-blue bar across the hairline.
*/}
<div
className="fixed top-0 left-0 right-0 z-50 h-px overflow-hidden pointer-events-none transition-opacity duration-200"
style={{ opacity: showScan ? 1 : 0 }}
aria-hidden
>
<div
className="h-full w-1/3 bg-accent animate-scan"
style={{ boxShadow: "0 0 8px hsl(var(--accent) / 0.5)" }}
/>
</div>
<Sidebar />
<main className="md:pl-60">
<div className="mx-auto max-w-[1400px] px-8 py-10">
<Outlet />
</div>
</main>
</div>
);
}