Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

EventStream

Live activity feed with follow mode — newest events pin to the bottom of a scrollable stream, and scrolling up releases the pin.

Import

EventStream is a registry composite — you own the source after installing:

npx ploxum add event-stream
import { EventStream, type EventStreamItem } from "@/components/event-stream";

Depends on @roger-emerson/ploxum-primitives (Card, StatusPip, Badge, Switch, EmptyState) and @roger-emerson/ploxum-icons (Radio, for the default empty state).

Usage

const events: EventStreamItem[] = [
  {
    id: "evt-01",
    severity: "ok",
    title: "Gate A throughput nominal",
    detail: "1,204 scans in last 5 min",
    source: "Ingress",
    timestamp: "19:42:07",
  },
  {
    id: "evt-02",
    severity: "live",
    title: "Broadcast feed 2 went live",
    source: "Media",
    timestamp: "19:43:12",
  },
  {
    id: "evt-03",
    severity: "warning",
    title: "Mezz 202 density trending up",
    detail: "78% of threshold",
    source: "Crowd",
    timestamp: "19:44:01",
  },
  {
    id: "evt-04",
    severity: "critical",
    title: "Floor 103 capacity threshold reached",
    source: "Crowd",
    timestamp: "19:45:30",
  },
];
 
<EventStream
  events={events}
  maxHeight={360}
  onSelect={(id) => openAlertDetail(id)}
/>;

Follow defaults to on: the scroller stays pinned to the newest event as items append. Scrolling more than 24px off the bottom turns follow off (reported via onFollowChange); hovering pauses the auto-scroll without changing state. Pass follow to run it controlled.

Props

EventStream

PropTypeDefaultDescription
eventsEventStreamItem[]Events to render, oldest first. Newest renders at the bottom.
followbooleantruePin the stream to the newest event. Controlled when provided.
onFollowChange(follow: boolean) => voidFires when the user scrolls out of (or toggles back into) follow mode.
maxHeightnumber320Scroller height cap in px.
fillbooleanfalseFill the parent's bounded height and scroll internally instead of capping at maxHeight.
glowOnArrivalbooleanfalsePulse a brief amber glow on each newly-arrived row; fades ~2s. Critical rows and reduced-motion never glow.
onSelect(id: string) => voidRow click handler.
emptyStateReactNodebuilt-in EmptyStateSlot rendered when there are no events.
classNamestringExtra classes on the root Card.
refRef<HTMLDivElement>Forwarded to the root Card.

EventStreamItem

FieldTypeDescription
idstringStable key.
severityStatusPipStatus"live" | "ok" | "warning" | "critical" | "offline" | "unknown" — rendered as a StatusPip (shape + color).
titlestringHeadline, truncates on overflow.
detailstring?Secondary line below the title.
sourcestring?Origin system, rendered as a Badge.
timestampstring | DatePre-formatted string passes through; a Date formats as HH:MM:SS. Always monospace + tabular numerals.

Design rules

  • Critical rows render motionless. The 150ms fade-in entrance is skipped for severity: "critical" (P1 rule: instant, no animation) and under prefers-reduced-motion.
  • Severity is conveyed by StatusPip shape + color, never hue alone.
  • Arrival glow respects the same gates. glowOnArrival pulses an amber halo on new rows but skips severity: "critical" (P1 rule: motionless) and prefers-reduced-motion. fill requires a parent with a bounded height — without one the scroller has nothing to fill against.
  • The scroller carries role="log" so assistive tech announces appended events without focus theft.
  • Follow-mode release is the user's signal that they're reading history — never re-pin programmatically except through the explicit toggle or follow prop.

Storybook

Composites/EventStream ↗