diff --git a/src/app/logs/page.tsx b/src/app/logs/page.tsx index 1d2ab12..f2d0a36 100644 --- a/src/app/logs/page.tsx +++ b/src/app/logs/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { DashboardLayout } from "@/components/dashboard/DashboardLayout"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; @@ -14,6 +14,10 @@ import { AnsiText } from "@/components/ansi/Ansi"; export default function LogsPage() { const [isPaused, setIsPaused] = useState(false); + const containerRef = useRef(null); + const bottomRef = useRef(null); + const shouldAutoScroll = useRef(true); + const [filter, setFilter] = useState<"all" | "info" | "warn" | "error">( "all", ); @@ -28,6 +32,25 @@ export default function LogsPage() { filter === "all" ? true : log.level === filter, ); + const handleScroll = () => { + const el = containerRef.current; + if (!el) return; + + const threshold = 20; // px from bottom + const isAtBottom = + el.scrollHeight - el.scrollTop - el.clientHeight < threshold; + + shouldAutoScroll.current = isAtBottom; + }; + + useEffect(() => { + if (!shouldAutoScroll.current || isPaused) return; + + bottomRef.current?.scrollIntoView({ + behavior: "smooth", + }); + }, [filteredLogs, isPaused]); + const handleExport = () => { // Convert data to JSON string const json = JSON.stringify(filteredLogs, null, 2); @@ -156,7 +179,11 @@ export default function LogsPage() { - +
{filteredLogs.map((log, index) => (
*/} + + {/* Scroll anchor */} +
))}