Timeline

Component

Interactive examples and API documentation

Basic
Basic timeline.
2015-09-01
Create a services site 2015-09-01
2015-09-01
Solve initial network problems 2015-09-01
2015-09-01
Technical testing 2015-09-01
2015-09-01
Network problems being solved 2015-09-01
Code
<%= render Hakumi::Timeline::Component.new do |timeline| %>
  <% timeline.with_item(title: "2015-09-01") do %>
    Create a services site 2015-09-01
  <% end %>
  <% timeline.with_item(title: "2015-09-01") do %>
    Solve initial network problems 2015-09-01
  <% end %>
  <% timeline.with_item(title: "2015-09-01") do %>
    Technical testing 2015-09-01
  <% end %>
  <% timeline.with_item(title: "2015-09-01") do %>
    Network problems being solved 2015-09-01
  <% end %>
<% end %>
Variant
Use the variant to set the style of the timeline.
2015-09-01
Filled timeline
2015-09-02
Default dots
2015-09-03
Resolved alerts
2015-09-01
Outlined timeline
2015-09-02
Neutral states
2015-09-03
Investigations
Code
<%= render Hakumi::Space::Component.new(direction: :vertical, size: :large) do |space| %>
  <% space.with_item do %>
    <%= render Hakumi::Timeline::Component.new do |timeline| %>
      <% timeline.with_item(title: "2015-09-01", color: :green) { "Filled timeline" } %>
      <% timeline.with_item(title: "2015-09-02", color: :blue) { "Default dots" } %>
      <% timeline.with_item(title: "2015-09-03", color: :red) { "Resolved alerts" } %>
    <% end %>
  <% end %>
  <% space.with_item do %>
    <%= render Hakumi::Timeline::Component.new(variant: :outlined) do |timeline| %>
      <% timeline.with_item(title: "2015-09-01", color: :green) { "Outlined timeline" } %>
      <% timeline.with_item(title: "2015-09-02", color: :blue) { "Neutral states" } %>
      <% timeline.with_item(title: "2015-09-03", color: :red) { "Investigations" } %>
    <% end %>
  <% end %>
<% end %>
Loading and Reversing
Node supports loading to indicate loading, and reverse property to control the order of nodes.
Recording...
2015-09-03
Technical testing
2015-09-02
Solve initial network problems
2015-09-01
Create a services site
Code
<%= render Hakumi::Timeline::Component.new(
  reverse: true,
  pending: "Recording...",
  pending_dot: Hakumi::Icon::Component.new(name: :loading, spin: true, size: 12)
) do |timeline| %>
  <% timeline.with_item(title: "2015-09-01") do %>
    Create a services site
  <% end %>
  <% timeline.with_item(title: "2015-09-02") do %>
    Solve initial network problems
  <% end %>
  <% timeline.with_item(title: "2015-09-03") do %>
    Technical testing
  <% end %>
<% end %>
Alternate
Alternate timeline.
2015-09-01
Create a services site
2015-09-02
Solve initial network problems
2015-09-03
Technical testing
2015-09-03
Network problems being solved
Code
<%= render Hakumi::Timeline::Component.new(mode: :alternate) do |timeline| %>
  <% timeline.with_item(title: "2015-09-01") do %>
    Create a services site
  <% end %>
  <% timeline.with_item(title: "2015-09-02") do %>
    Solve initial network problems
  <% end %>
  <% timeline.with_item(title: "2015-09-03") do %>
    Technical testing
  <% end %>
  <% timeline.with_item(title: "2015-09-03") do %>
    Network problems being solved
  <% end %>
<% end %>
End alternate
End alternate timeline.
2015-09-01
Create a services site
2015-09-02
Solve initial network problems
2015-09-03
Technical testing
2015-09-04
Final deployment
Code
<%= render Hakumi::Timeline::Component.new(mode: :alternate) do |timeline| %>
  <% timeline.with_item(title: "2015-09-01") do %>
    Create a services site
  <% end %>
  <% timeline.with_item(title: "2015-09-02") do %>
    Solve initial network problems
  <% end %>
  <% timeline.with_item(title: "2015-09-03") do %>
    Technical testing
  <% end %>
  <% timeline.with_item(title: "2015-09-04", position: :left) do %>
    Final deployment
  <% end %>
<% end %>
Horizontal
Horizontal layout.
09:00
Kickoff
11:30
Planning
14:00
QA checks
18:00
Launch
Code
<%= render Hakumi::Timeline::Component.new(direction: :horizontal) do |timeline| %>
  <% timeline.with_item(title: "09:00") do %>
    Kickoff
  <% end %>
  <% timeline.with_item(title: "11:30", color: :green) do %>
    Planning
  <% end %>
  <% timeline.with_item(title: "14:00", color: :red) do %>
    QA checks
  <% end %>
  <% timeline.with_item(title: "18:00") do %>
    Launch
  <% end %>
<% end %>
Custom
Set a node as an icon or other custom element.
2015-09-01
Custom icon node
2015-09-02
Document review
2015-09-03
Approved deliverables
Code
<%= render Hakumi::Timeline::Component.new do |timeline| %>
  <% timeline.with_item(title: "2015-09-01", dot: Hakumi::Icon::Component.new(name: :clock_circle, size: 12), color: :blue) do %>
    Custom icon node
  <% end %>
  <% timeline.with_item(title: "2015-09-02", color: :green) do %>
    Document review
  <% end %>
  <% timeline.with_item(title: "2015-09-03", dot: Hakumi::Icon::Component.new(name: :check, size: 12), color: :green) do %>
    Approved deliverables
  <% end %>
<% end %>
Title
Use title show time alone.
09:00
11:30
14:00
18:00
Code
<%= render Hakumi::Timeline::Component.new do |timeline| %>
  <% timeline.with_item(title: "09:00") %>
  <% timeline.with_item(title: "11:30") %>
  <% timeline.with_item(title: "14:00") %>
  <% timeline.with_item(title: "18:00") %>
<% end %>
Title Offset
Use titleSpan to set the title span space.
2015-09-01 09:00
Start deployment
2015-09-01 12:00
Verification and QA
2015-09-01 18:00
Release completed
Code
<%= render Hakumi::Timeline::Component.new(title_span: "160px") do |timeline| %>
  <% timeline.with_item(title: "2015-09-01 09:00") do %>
    Start deployment
  <% end %>
  <% timeline.with_item(title: "2015-09-01 12:00") do %>
    Verification and QA
  <% end %>
  <% timeline.with_item(title: "2015-09-01 18:00") do %>
    Release completed
  <% end %>
<% end %>
Semantic Sample
Achieve richer custom styles by using semantic structure.
Sprint 01
Design review
Tickets: 12 · Lead: Sofía
Sprint 02
Implementation
API, UI, and QA in parallel
Sprint 03
Stabilization
Regression suite + launch plan
Code
<%= render Hakumi::Timeline::Component.new(mode: :alternate) do |timeline| %>
  <% timeline.with_item(title: "Sprint 01", color: :green) do %>
    <%= render Hakumi::Space::Component.new(direction: :vertical, size: :small) do |space| %>
      <% space.with_item do %>
        <%= render(Hakumi::Typography::Title::Component.new(level: 5)) { "Design review" } %>
      <% end %>
      <% space.with_item do %>
        <%= render(Hakumi::Typography::Text::Component.new(type: :secondary)) { "Tickets: 12 · Lead: Sofía" } %>
      <% end %>
    <% end %>
  <% end %>
  <% timeline.with_item(title: "Sprint 02", color: :blue) do %>
    <%= render Hakumi::Space::Component.new(direction: :vertical, size: :small) do |space| %>
      <% space.with_item do %>
        <%= render(Hakumi::Typography::Title::Component.new(level: 5)) { "Implementation" } %>
      <% end %>
      <% space.with_item do %>
        <%= render(Hakumi::Typography::Text::Component.new(type: :secondary)) { "API, UI, and QA in parallel" } %>
      <% end %>
    <% end %>
  <% end %>
  <% timeline.with_item(title: "Sprint 03", color: :red) do %>
    <%= render Hakumi::Space::Component.new(direction: :vertical, size: :small) do |space| %>
      <% space.with_item do %>
        <%= render(Hakumi::Typography::Title::Component.new(level: 5)) { "Stabilization" } %>
      <% end %>
      <% space.with_item do %>
        <%= render(Hakumi::Typography::Text::Component.new(type: :secondary)) { "Regression suite + launch plan" } %>
      <% end %>
    <% end %>
  <% end %>
<% end %>
Programmatic
Render a timeline with HakumiComponents.renderComponent.
Code
<%= render Hakumi::Space::Component.new(size: :middle) do %>
  <%= render(Hakumi::Button::Component.new(id: "timeline-programmatic-render", type: :primary)) { "Render timeline" } %>
  <%= render(Hakumi::Button::Component.new(id: "timeline-programmatic-reverse")) { "Toggle reverse" } %>
<% end %>

<%= render Hakumi::Container::Component.new(id: "timeline-programmatic-target", padded: false, style: "min-height: 180px;") %>

<script>
  (() => {
    let instance = null

    const wire = () => {
      if (!window.HakumiComponents?.renderComponent) return false

      const renderButton = document.getElementById("timeline-programmatic-render")
      const reverseButton = document.getElementById("timeline-programmatic-reverse")

      renderButton?.addEventListener("click", async () => {
        const result = await window.HakumiComponents.renderComponent("timeline", {
          target: "#timeline-programmatic-target",
          mode: "replace",
          params: {
            id: "timeline-programmatic",
            pending: "Syncing...",
            items: JSON.stringify([
              { title: "09:00", body: "Check-in" },
              { title: "12:00", body: "Deploy" },
              { title: "15:00", body: "Verification" }
            ])
          }
        })

        instance = result.instance
      })

      reverseButton?.addEventListener("click", () => instance?.setReverse?.(!instance?.getReverse?.()))

      return true
    }

    if (wire()) return

    const onReady = () => {
      if (wire()) {
        document.removeEventListener("turbo:load", onReady)
        window.removeEventListener("load", onReady)
      }
    }

    document.addEventListener("turbo:load", onReady)
    window.addEventListener("load", onReady)
  })()
</script>

Timeline API

Prop Type Default Description
direction Symbol :vertical Layout direction. Options: :vertical, :horizontal.
mode Symbol :left Item placement for vertical layout. Options: :left, :right, :alternate.
reverse Boolean false Reverse the display order of items.
pending String or Boolean nil Show a pending node with optional text.
pending_dot Component or String nil Custom dot for the pending node.
title_span String nil CSS width for the title column (e.g., '160px').
variant Symbol :filled Visual style. Options: :filled, :outlined.

Timeline.Item API

Prop Type Default Description
title String nil Title or time label for the item.
content String nil Item content when no block is supplied.
color Symbol or String :blue Dot color token (:blue, :green, :red, :gray) or custom CSS color.
dot Component or String nil Custom dot element or icon component.
position Symbol nil Override item position. Options: :left, :right.
loading Boolean false Show loading indicator inside the dot.

JavaScript API (element.hakumiTimeline)

Prop Type Default Description
getItems() Function - Return item metadata in display order.
getReverse() Function - Returns current reverse state.
setReverse(value) Function - Set reverse state and update DOM order.
toggleReverse() Function - Toggle reverse state.