Files
PacketStation/frontend/src/components/TopBar.tsx
T

65 lines
1.9 KiB
TypeScript
Raw Normal View History

import { useEffect, useState, type ReactNode } from "react";
import { Link } from "react-router";
import logo from "../assets/logo.png";
import { setMotion, useMotion } from "../lib/motion";
/** The Motion on / Motion off switch (the old motionBtn), with a short toast on toggle. */
export function MotionButton() {
const on = useMotion();
const [toast, setToast] = useState<string | null>(null);
useEffect(() => {
if (!toast) return;
const t = window.setTimeout(() => setToast(null), 2500);
return () => window.clearTimeout(t);
}, [toast]);
return (
<>
<button
className="btn sm ghost mbtn"
type="button"
aria-pressed={on}
title={on ? "Turn animations off" : "Turn animations on"}
onClick={() => {
setMotion(!on);
setToast(on ? "Motion off" : "Motion on");
}}
>
<span className="mdot" aria-hidden="true" />
{on ? "Motion on" : "Motion off"}
</button>
{toast ? (
<div className="toast" role="status" data-testid="motion-toast">
{toast}
</div>
) : null}
</>
);
}
interface TopBarProps {
/** The role switcher, drawn between the brand and the spacer. */
nav?: ReactNode;
/** Right-hand side: the signed-in user, the role chip, Account and Sign out. */
children?: ReactNode;
}
/** Sticky shop header. Same markup classes as the old page's header.top. */
export function TopBar({ nav, children }: TopBarProps) {
return (
<header className="top">
<div className="top-in">
<Link className="brand" to="/" aria-label="Packet Station home">
<img alt="PESCO" src={logo} width={119} height={34} />
<div className="nm">
Packet <span>Station</span>
</div>
</Link>
{nav}
<MotionButton />
<div className="sp" />
{children ? <div className="who">{children}</div> : null}
</div>
</header>
);
}