Scrollable log feed component that renders a list of `LogEntry` items with severity indicators, timestamps, and optional tool icons — with loading and empty states. ## Key Components | Export | Type | Description | |---|---|---| | `LogsList` | `React.ForwardRefExoticComponent` | Main scrollable log list container | | `LogCard` | `React.FC` (internal) | Individual log entry row with click/keyboard support | | `formatTimestamp` | `function` (internal) | UTC-safe timestamp formatter preventing React hydration mismatch (#418) | **`LogsList` Props** (`LogsListProps`): | Prop | Default | Description | |---|---|---| | `logs` | — | Array of `LogEntry` items to render | | `maxHeight` | `'400px'` | Container max height; use `'100%'` for full-height mode | | `showConnector` | `true` | Draws a vertical line connecting sequential log entries | | `onLogClick` | — | Callback fired with the clicked `LogEntry` | | `loading` | `false` | Shows a loading placeholder when `true` | | `emptyMessage` | `'No logs to display'` | Message shown when `logs` is empty | | `className` | — | Additional CSS classes for the outer container | ## Usage Example ```typescript import { LogsList } from '@openframe-oss-lib/components' import type { LogEntry } from '@openframe-oss-lib/types' const logs: LogEntry[] = [ { id: '1', title: 'Backup job completed', severity: 'info', timestamp: new Date(), toolType: 'backup', }, { id: '2', title: 'Disk usage above 90%', severity: 'warning', timestamp: '2025-01-15T08:30:00Z', }, ] export default function AuditPanel() { return ( console.log('Selected:', log.id)} /> ) } ``` > **Hydration note:** `formatTimestamp` uses UTC getters (`getUTCFullYear`, etc.) to ensure timestamps are identical between SSR and client rendering, preventing React hydration error #418. **Source:** [`logs-list.tsx`](https://github.com/flamingo-stack/openframe-oss-lib/blob/main/logs-list.tsx)