11import { ArrowPathIcon } from "@heroicons/react/20/solid" ;
22import { Link } from "@remix-run/react" ;
33import { formatDurationNanoseconds } from "@trigger.dev/core/v3" ;
4- import { type ReactNode , useEffect , useRef } from "react" ;
4+ import { type ReactNode , useEffect , useRef , useState } from "react" ;
55import { cn } from "~/utils/cn" ;
66import { Button } from "~/components/primitives/Buttons" ;
77import { useEnvironment } from "~/hooks/useEnvironment" ;
@@ -107,7 +107,7 @@ function highlightText(text: string, searchTerm: string | undefined): ReactNode
107107 return (
108108 < >
109109 { text . slice ( 0 , index ) }
110- < mark className = "rounded bg-yellow-500/30 px-0.5 " >
110+ < mark className = "rounded px-0.5 bg-yellow-400 text-black font-medium " >
111111 { text . slice ( index , index + searchTerm . length ) }
112112 </ mark >
113113 { text . slice ( index + searchTerm . length ) }
@@ -132,6 +132,21 @@ export function LogsTable({
132132 const project = useProject ( ) ;
133133 const environment = useEnvironment ( ) ;
134134 const loadMoreRef = useRef < HTMLDivElement > ( null ) ;
135+ const [ showLoadMoreSpinner , setShowLoadMoreSpinner ] = useState ( false ) ;
136+
137+ // Show load more spinner only after 0.5 seconds of loading time
138+ useEffect ( ( ) => {
139+ if ( ! isLoadingMore ) {
140+ setShowLoadMoreSpinner ( false ) ;
141+ return ;
142+ }
143+
144+ const timer = setTimeout ( ( ) => {
145+ setShowLoadMoreSpinner ( true ) ;
146+ } , 500 ) ;
147+
148+ return ( ) => clearTimeout ( timer ) ;
149+ } , [ isLoadingMore ] ) ;
135150
136151 // Intersection observer for infinite scroll
137152 useEffect ( ( ) => {
@@ -159,17 +174,17 @@ export function LogsTable({
159174 } , [ hasMore , isLoadingMore , onLoadMore ] ) ;
160175
161176 return (
162- < div className = "relative h-full overflow-y- auto scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600" >
163- < Table variant = "compact/mono" >
164- < TableHeader >
177+ < div className = "relative h-full overflow-auto scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600" >
178+ < Table variant = "compact/mono" containerClassName = "overflow-visible" >
179+ < TableHeader className = "sticky top-0 z-10" >
165180 < TableRow >
166- < TableHeaderCell > Time</ TableHeaderCell >
167- < TableHeaderCell > Run</ TableHeaderCell >
168- < TableHeaderCell > Task</ TableHeaderCell >
169- < TableHeaderCell > Level</ TableHeaderCell >
170- < TableHeaderCell > Status</ TableHeaderCell >
171- < TableHeaderCell > Duration</ TableHeaderCell >
172- < TableHeaderCell className = "w-full" > Message</ TableHeaderCell >
181+ < TableHeaderCell className = "w-48 whitespace-nowrap" > Time</ TableHeaderCell >
182+ < TableHeaderCell className = "w-24 whitespace-nowrap" > Run</ TableHeaderCell >
183+ < TableHeaderCell className = "w-32 whitespace-nowrap" > Task</ TableHeaderCell >
184+ < TableHeaderCell className = "whitespace-nowrap" > Level</ TableHeaderCell >
185+ < TableHeaderCell className = "whitespace-nowrap" > Status</ TableHeaderCell >
186+ < TableHeaderCell className = "whitespace-nowrap" > Duration</ TableHeaderCell >
187+ < TableHeaderCell className = "w-full min-w-0 " > Message</ TableHeaderCell >
173188 </ TableRow >
174189 </ TableHeader >
175190 < TableBody >
@@ -258,18 +273,13 @@ export function LogsTable({
258273 { /* Infinite scroll trigger */ }
259274 { hasMore && logs . length > 0 && (
260275 < div ref = { loadMoreRef } className = "flex items-center justify-center py-4" >
261- { isLoadingMore && (
276+ { showLoadMoreSpinner && (
262277 < div className = "flex items-center gap-2" >
263278 < Spinner /> < span className = "text-text-dimmed" > Loading more…</ span >
264279 </ div >
265280 ) }
266281 </ div >
267282 ) }
268- { isLoading && (
269- < div className = "absolute inset-0 flex items-center justify-center gap-2 bg-charcoal-900/90" >
270- < Spinner /> < span className = "text-text-dimmed" > Loading…</ span >
271- </ div >
272- ) }
273283 </ div >
274284 ) ;
275285}
0 commit comments