nanobot-voice-interface/frontend/src/components/LogPanel.tsx

39 lines
1.1 KiB
TypeScript
Raw Normal View History

2026-03-06 22:51:19 -05:00
import { useEffect, useRef } from "preact/hooks";
import type { LogLine } from "../types";
interface Props {
lines: LogLine[];
}
export function LogPanel({ lines }: Props) {
const innerRef = useRef<HTMLDivElement>(null);
// Scroll to top (newest line — column-reverse layout) after each update
useEffect(() => {
const el = innerRef.current?.parentElement;
if (el) el.scrollTop = 0;
}, [lines]);
return (
<div id="log">
<div id="log-inner" ref={innerRef}>
{lines.map((line) => {
const time = line.timestamp ? new Date(line.timestamp).toLocaleTimeString() : "";
const role = line.role.trim().toLowerCase();
let text: string;
if (role === "nanobot") {
text = `[${time}] ${line.text.replace(/^(?:nanobot|napbot)\b\s*[:>-]?\s*/i, "")}`;
} else {
text = `[${time}] ${line.role}: ${line.text}`;
}
return (
<div key={line.id} class={`line ${line.role}`}>
{text}
</div>
);
})}
</div>
</div>
);
}