PhiaUi.Components.Timeline (phia_ui v0.1.17)

Copy Markdown View Source

Vertical timeline / activity feed component.

Renders a vertical sequence of events with connecting lines, optional icons or dot markers, and timestamped content. CSS-only — no JavaScript required.

Sub-components

ComponentElementPurpose
timeline/1<ol>Ordered list container for the full event sequence
timeline_item/1<li>Single event row with connector line, marker, content

Basic usage

<.timeline>
  <.timeline_item timestamp="Just now">
    New comment added to ticket #1234.
  </.timeline_item>
  <.timeline_item timestamp="2 hours ago">
    Status changed from <strong>Open</strong> to <strong>In Progress</strong>.
  </.timeline_item>
  <.timeline_item timestamp="Yesterday">
    Ticket assigned to Jane Smith.
  </.timeline_item>
</.timeline>

With icons

Provide a <:icon> slot to replace the default dot marker with an icon:

<.timeline>
  <.timeline_item timestamp="10:32 AM">
    <:icon><.icon name="check-circle" size={:sm} class="text-green-500" /></:icon>
    Deployment completed successfully.
  </.timeline_item>
  <.timeline_item timestamp="10:15 AM">
    <:icon><.icon name="upload-cloud" size={:sm} class="text-blue-500" /></:icon>
    Build uploaded to staging environment.
  </.timeline_item>
  <.timeline_item timestamp="10:00 AM">
    <:icon><.icon name="git-commit" size={:sm} /></:icon>
    Commit <code>a3f9c2e</code> pushed to main.
  </.timeline_item>
</.timeline>

Order history / e-commerce tracking

<.timeline>
  <.timeline_item timestamp="March 3, 2:14 PM">
    <:icon><.icon name="package-check" size={:sm} class="text-green-500" /></:icon>
    <strong>Delivered</strong>  Left at front door.
  </.timeline_item>
  <.timeline_item timestamp="March 3, 8:02 AM">
    <:icon><.icon name="truck" size={:sm} class="text-blue-500" /></:icon>
    <strong>Out for delivery</strong>  With courier.
  </.timeline_item>
  <.timeline_item timestamp="March 2, 11:45 PM">
    <:icon><.icon name="warehouse" size={:sm} /></:icon>
    <strong>In transit</strong>  Arrived at local facility.
  </.timeline_item>
  <.timeline_item timestamp="March 1, 9:30 AM">
    <:icon><.icon name="package" size={:sm} /></:icon>
    Order packed and ready for collection.
  </.timeline_item>
</.timeline>

Audit log / user activity feed

<.timeline>
  <%= for event <- @audit_events do %>
    <.timeline_item timestamp={Calendar.strftime(event.inserted_at, "%b %d, %H:%M")}>
      <:icon>
        <.avatar size="sm">
          <.avatar_image src={event.user.avatar_url} alt={event.user.name} />
          <.avatar_fallback name={event.user.name} />
        </.avatar>
      </:icon>
      <span class="font-medium">{event.user.name}</span>
      {event.description}
    </.timeline_item>
  <% end %>
</.timeline>

How the connector line works

Each timeline_item/1 contains an absolutely-positioned <span> that draws a 1px bg-border line from just below the marker to the bottom of the item. The last item's connector is hidden via Tailwind's last-of-type:hidden utility, preventing a dangling line below the final event.

Accessibility

The <ol> element communicates that the events are ordered (chronological). Screen readers announce item count and position (e.g. "list item 1 of 5"). Add aria-label to the <ol> via :rest when the context is not obvious:

<.timeline aria-label="Order tracking events">
  ...
</.timeline>

Summary

Functions

Renders a vertical timeline container.

Renders a single event item in the timeline.

Functions

timeline(assigns)

Renders a vertical timeline container.

Uses space-y-6 for comfortable vertical spacing between events. Place timeline_item/1 components inside.

Attributes

  • class (:string) - Additional CSS classes applied to the <ol> container. Defaults to nil.
  • Global attributes are accepted. HTML attributes forwarded to the <ol> element (e.g. aria-label).

Slots

  • inner_block (required) - timeline_item/1 children, in display order (newest first or oldest first, your choice).

timeline_item(assigns)

Renders a single event item in the timeline.

Each item consists of three layers:

  1. Connector line — a 1px bg-border vertical line spanning from the marker to the next item. Hidden on the last item via last-of-type:hidden.
  2. Marker — a 24×24px circle (ring-1 ring-border) containing either the :icon slot content or a small primary-coloured dot.
  3. Content — optional timestamp in muted small text followed by the main event description.

Example

<.timeline_item timestamp="2 hours ago">
  <:icon>
    <.icon name="user-plus" size={:sm} class="text-primary" />
  </:icon>
  <strong>Jane Smith</strong> joined the organization.
</.timeline_item>

Attributes

  • timestamp (:string) - Optional timestamp label displayed above the event content (e.g. "2 hours ago", "March 3, 10:32 AM"). When nil, no timestamp is shown. Defaults to nil.
  • class (:string) - Additional CSS classes applied to the <li> element. Defaults to nil.
  • Global attributes are accepted. HTML attributes forwarded to the <li> element.

Slots

  • icon - Optional icon or custom marker. When provided, replaces the default dot. Use <.icon>, <.avatar>, or any element. Sized to fit the 24×24px marker circle.
  • inner_block (required) - Event description content. Supports any HEEx — plain text, formatted HTML, or components.