Ports catalog.ts's tree renderer to components under src/components/sidebar/, following docs/SIDEBAR.md: two-line cards behind a 5px activity rail, adaptive meta line (duration, detail, program, diff stat), collapsible folders, j/k walk, inline rename and a right-click menu. The nav walk reads a pure model (model.ts) rather than the DOM, so the rule that an expanded folder header is skipped and a collapsed one is not is testable without a render. Rail motion needs @keyframes, so it stays in sidebar.css rather than the Tailwind config. Closes #244
17 lines
581 B
TypeScript
17 lines
581 B
TypeScript
import { useEffect, useState } from "react";
|
|
|
|
/** A clock that ticks at least every `intervalMs` while the page is visible.
|
|
* docs/SIDEBAR.md asks for a re-render at least every 30s so the duration's
|
|
* cutover points land within one tick. */
|
|
export function useNow(intervalMs = 30_000): number {
|
|
const [now, setNow] = useState(() => Date.now());
|
|
useEffect(() => {
|
|
const id = setInterval(() => {
|
|
if (document.visibilityState !== "visible") return;
|
|
setNow(Date.now());
|
|
}, intervalMs);
|
|
return () => clearInterval(id);
|
|
}, [intervalMs]);
|
|
return now;
|
|
}
|