Log view: monospace lines with a timestamp gutter and per-line severity. No Fluxon equivalent. Pure presentational server render; no JS hook.
<.log_view id="run-trace" label="Trace">
<.log_line at="12:04:03" channel="bash" severity={:neutral}>ls -la src</.log_line>
<.log_line at="12:04:05" channel="bash" severity={:error} meta="412ms">
No such file or directory
<:detail>{@stack}</:detail>
</.log_line>
</.log_view>Why this is not an editor, and not a <pre>
Command output keeps arriving in read-only code EDITORS across this
portfolio, and it reads wrong every time: an editor offers a caret, a
selection model and a gutter that implies you may type, for content nobody
can edit. A bare <pre> has the opposite problem — no timestamps, no
severity, and it pushes the page sideways the moment one line is long.
This component takes the third position. Lines are data: each carries an
optional preformatted at, a channel (the tool, stream or subsystem that
produced it), a severity, and trailing meta such as a duration. Severity
bands the line with a colored left edge AND is announced to assistive tech,
so it is never color-only.
Containment is the load-bearing rule
The scroll lives on the log view, never on the page: the root is the
overflow: auto box, so a 400-character line scrolls INSIDE the component
and the document body never scrolls horizontally. wrap flips individual
lines to soft-wrapping when reading beats fidelity. Set a height on the root
(or let a flex parent give it one) and the header stays pinned while the
lines scroll under it.
--lui-log-view-gutter-w tunes the timestamp column.
Summary
Functions
Attributes
at(:string) - Preformatted timestamp for the gutter; the component does not format time. Defaults tonil.channel(:string) - What produced the line — a tool name, stream, or subsystem. Defaults tonil.severity(:atom) - Line severity. Bands the line and is announced to assistive tech. Defaults to:neutral. Must be one of:neutral,:info,:success,:warning, or:error.meta(:string) - Trailing detail, typically a duration. Defaults tonil.selected(:boolean) - Marks this line as the current selection. Defaults tofalse.open(:boolean) - When:detailis present, start expanded. Defaults tofalse.class(:any) - Extra classes merged onto the line root. Defaults tonil.- Global attributes are accepted. Arbitrary HTML/
phx-*attributes passed through.
Slots
inner_block(required) - The line body.detail- Collapsible body revealed under a native disclosure. When present, the line is a summary.
Attributes
id(:string) - DOM id for the root element. Defaults tonil.label(:string) - Optional heading pinned above the lines while they scroll. Defaults tonil.wrap(:boolean) - Soft-wrap long lines instead of scrolling them horizontally. Inherited by lines unless overridden. Defaults tofalse.class(:any) - Extra classes merged onto the root element. Defaults tonil.- Global attributes are accepted. Arbitrary HTML/
phx-*attributes passed through.
Slots
actions- Controls rendered at the right of the header (filters, toggles).inner_block(required) - One or morelog_line/1children.