Add this component

npx zentauri-ui add log-viewer

Accessibility notes

Keyboard accessible by default with semantic markup, visible focus treatment, and tokenized states. Add descriptive labels for icon-only or decorative usage.

Dependency notes

Check Installation for shared peers. This component keeps styling in Tailwind classes and the --zui-* token contract.

Feedback

Log Viewer for displaying structured log streams

Use the log viewer to display a structured, filterable stream of log entries. Pass an array of typed entries — each with a level, timestamp, message, optional meta, and optional stack trace — and the component renders each with the correct color-coded badge, formatted timestamp, and message. An optional header bar provides per-level filter toggles, a text search input, and a copy-to-clipboard button. A summary footer shows the filtered vs. total count.

Jun 01, 10:00:00info
Application started successfully
port=3000
Jun 01, 10:00:01info
Connected to database
host=db.internal, latency=4ms
Jun 01, 10:00:02warn
Rate limit approaching threshold
current=950/1000 req/min
Jun 01, 10:00:03info
GET /api/users/8f21 — 200 OK
duration=42ms
Jun 01, 10:00:04info
GET /api/health — 200 OK
duration=8ms
Jun 01, 10:00:05error
Unhandled promise rejection
TypeError: Cannot read properties of undefined
  at Query.execute (/app/src/db/query.ts:48:12)
  at processTicksAndRejections (node:internal/process/task_queues:95:5)
Jun 01, 10:00:06debug
Retry attempt 1/3 for query #a3f8
Jun 01, 10:00:07info
Retry succeeded — query #a3f8 completed
duration=120ms
Showing 8 / Total 8

Log viewer playground

Pick a dataset, chrome appearance, and size to preview the log viewer live. Toggle the header bar with level filters, search, and the copy button, switch on a motion preset, and use Show output / Show code to copy the matching snippet.


Jun 01, 10:00:00info
Application starting…
mode=production
Jun 01, 10:00:01info
Connected to database
host=db.internal, latency=4ms
Jun 01, 10:00:02info
Listening on port 3000
host=0.0.0.0
Showing 3 / Total 3

All appearances

Every shipped chrome appearance over the same dataset. Click any card to load it into the playground above.

Log Viewer API

Generated from the package prop types and variant definitions.

LogViewer

LogViewerProps

Variants

PropTypeDefault
appearance
contrastdefaultglasssubtle
default
size
lgmdsm
md

Behavior

PropTypeDefault
defaultActiveLevelsLogLevel[] | undefinednone
enableClipboardboolean | undefinednone
enableSearchboolean | undefinednone
entries*LogEntry[]none
labelsLogViewerLabels | undefinednone
showHeaderboolean | undefinednone
showSummaryboolean | undefinednone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

LogViewerVariant

LogViewerVariantProps

Behavior

PropTypeDefault
appearance'default' | 'subtle' | 'contrast' | 'glass' | null | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone

LogViewerAnimated

LogViewerAnimatedProps

animated

Behavior

PropTypeDefault
animationLogViewerAnimation | undefinednone
appearance'default' | 'subtle' | 'contrast' | 'glass' | null | undefinednone
defaultActiveLevelsLogLevel[] | undefinednone
enableClipboardboolean | undefinednone
enableSearchboolean | undefinednone
entries*LogEntry[]none
labelsLogViewerLabels | undefinednone
refAllows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).Ref<HTMLDivElement> | undefinednone
showHeaderboolean | undefinednone
showSummaryboolean | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone
CSS variable overrides

Log Viewer CSS variables

Override these log viewer variables on :root, a theme selector, or a component wrapper.

68 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-log-viewer-border: #0000001a;
  --zui-log-viewer-bg: oklch(98.4% 0.003 247.858);
  --zui-log-viewer-fg: oklch(20.8% 0.042 265.755);
  --zui-log-viewer-subtle-bg: oklch(92.9% 0.013 255.508);
  --zui-log-viewer-contrast-bg: #ffffff;
  --zui-log-viewer-glass-bg: #ffffffcc;
  --zui-log-viewer-glass-border: #ffffff66;
  --zui-log-viewer-header-bg: oklch(96.8% 0.007 247.896);
  --zui-log-viewer-filter-fg: oklch(44.6% 0.043 257.281);
  --zui-log-viewer-filter-hover-bg: #0000000d;
  --zui-log-viewer-filter-active-bg: #0000000d;
  --zui-log-viewer-search-border: #0000001a;
  --zui-log-viewer-search-bg: oklch(98.4% 0.003 247.858);
  --zui-log-viewer-search-fg: oklch(20.8% 0.042 265.755);
  --zui-log-viewer-search-placeholder: #94a3b8;
  --zui-log-viewer-action-fg: oklch(44.6% 0.043 257.281);
  --zui-log-viewer-action-hover-bg: #0000000d;
  --zui-log-viewer-timestamp-fg: #94a3b8;
  --zui-log-viewer-message-fg: oklch(20.8% 0.042 265.755);
  --zui-log-viewer-meta-fg: #94a3b8;
  --zui-log-viewer-empty-fg: #94a3b8;
  --zui-log-viewer-summary-fg: #94a3b8;
  --zui-log-viewer-error-bg: #fee2e2;
  --zui-log-viewer-error-fg: #b91c1c;
  --zui-log-viewer-warn-bg: #fef9c3;
  --zui-log-viewer-warn-fg: #a16207;
  --zui-log-viewer-info-bg: #dbeafe;
  --zui-log-viewer-info-fg: #1d4ed8;
  --zui-log-viewer-debug-bg: #e2e8f0;
  --zui-log-viewer-debug-fg: #475569;
  --zui-log-viewer-verbose-bg: #f3e8ff;
  --zui-log-viewer-verbose-fg: #7c3aed;
  --zui-log-viewer-silly-bg: #fce7f3;
  --zui-log-viewer-silly-fg: #be185d;
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-log-viewer-border-dark: #ffffff1a;
  --zui-log-viewer-bg-dark: oklch(12.9% 0.042 264.695);
}

Composition and API

Pass log entries through the entries prop as an array of { level, timestamp, message, meta?, stack? } objects, where level is error, warn, info, debug, or verbose. Each level renders with its own color-coded badge background and foreground. The showHeader prop toggles the filter bar; within it, enableClipboard toggles the copy button and enableSearch toggles the text search input. showSummary toggles the footer count. appearance switches between default, subtle, contrast, and glass chrome, and size controls the font scale. The separate animated entry adds fade and stagger reveal presets for the body.

Accessibility

The filter buttons, copy control, and search input are real interactive elements. The timestamp and level badge are presentational text with no interactive role. Every element carries data-slot attributes for styling and testing, and each entry exposes a data-level attribute reflecting its severity. Color pairs meet contrast on their surfaces; the animated entry's motion is short and easing-based, so pair it with prefers-reduced-motion handling in your app where needed.

Next.js integration notes

The static LogViewer entry ships no framer-motion and is safe in any Server or Client Component tree (it is a Client Component because the filter/search/copy controls manage local state). The animated LogViewerAnimated entry imports framer-motion, which is an optional peer dependency. Both render deterministically from the same entries, so server and client output match and there is no hydration mismatch.

FAQ

How do I distinguish log levels visually?

Each entry carries a level badge rendered with its own color palette: error is red, warn is yellow, info is blue, debug is slate, and verbose is purple. All colors are driven by --zui-log-viewer-* CSS variables you can override.

Can I filter to show only certain levels?

Yes. The header bar renders a toggle button for each level. Click a button to hide that level from the list; at least one level must remain active. You can also set defaultActiveLevels to control the initial filter set.

Do I need framer-motion?

Only for the animated entry. The default import from @zentauri-ui/zentauri-components/ui/log-viewer is framer-motion-free. Import LogViewerAnimated from the /animated subpath when you want the fade or stagger reveal, and install framer-motion as a peer dependency.

How do I theme the log level colors?

Override the --zui-log-viewer-* CSS variables (bg, fg, border, header, filter colors, search colors, per-level badge colors, and more) on :root, a theme selector, or a wrapper. Each variable ships a light fallback and a paired -dark variant for dark mode.