/** * ClaudeLogsPanel * * Shared rendering surface for Claude logs — used both in the compact sidebar * section and the fullscreen dialog. Renders the toolbar (search, filter, * pending button), the rich log viewer, and empty/error states. */ import React from 'react'; import { Button } from '@renderer/components/ui/button'; import { cn } from '@renderer/lib/utils'; import { Search, X } from 'lucide-react'; import { ClaudeLogsFilterPopover } from './ClaudeLogsFilterPopover'; import { CliLogsRichView } from './CliLogsRichView'; import type { ClaudeLogsController } from './useClaudeLogsController'; // ============================================================================= // Props // ============================================================================= interface ClaudeLogsPanelProps { ctrl: ClaudeLogsController; /** Maximum height class for the log viewer (e.g. "max-h-[213px]" for compact). */ viewerClassName?: string; /** Extra className for the panel wrapper. */ className?: string; } // ============================================================================= // Component // ============================================================================= export const ClaudeLogsPanel = ({ ctrl, viewerClassName, className, }: ClaudeLogsPanelProps): React.JSX.Element => { const { data, loading, loadingMore, error, pendingNewCount, isAlive, filteredText, showMoreVisible, searchQuery, setSearchQuery, filter, setFilter, filterOpen, setFilterOpen, viewerState, onViewerStateChange, applyPending, loadOlderLogs, containerRefCallback, handleScroll, } = ctrl; return (
{error}
: null} {!error && filteredText.trim().length > 0 ? ({loading ? 'Loading…' : 'No logs captured.'}
) : null} {!error && data.lines.length > 0 && filteredText.trim().length === 0 ? (No matching logs.
) : null}