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 HakumiComponents::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 HakumiComponents::Space::Component.new(direction: :vertical, size: :large) do |space| %>
  <% space.with_item do %>
    <%= render HakumiComponents::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 HakumiComponents::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 HakumiComponents::Timeline::Component.new(
  reverse: true,
  pending: "Recording...",
  pending_dot: HakumiComponents::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 HakumiComponents::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 HakumiComponents::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 HakumiComponents::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 HakumiComponents::Timeline::Component.new do |timeline| %>
  <% timeline.with_item(title: "2015-09-01", dot: HakumiComponents::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: HakumiComponents::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 HakumiComponents::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 HakumiComponents::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 HakumiComponents::Timeline::Component.new(mode: :alternate) do |timeline| %>
  <% timeline.with_item(title: "Sprint 01", color: :green) do %>
    <%= render HakumiComponents::Space::Component.new(direction: :vertical, size: :small) do |space| %>
      <% space.with_item do %>
        <%= render(HakumiComponents::Typography::Title::Component.new(level: 5)) { "Design review" } %>
      <% end %>
      <% space.with_item do %>
        <%= render(HakumiComponents::Typography::Text::Component.new(type: :secondary)) { "Tickets: 12 · Lead: Sofía" } %>
      <% end %>
    <% end %>
  <% end %>
  <% timeline.with_item(title: "Sprint 02", color: :blue) do %>
    <%= render HakumiComponents::Space::Component.new(direction: :vertical, size: :small) do |space| %>
      <% space.with_item do %>
        <%= render(HakumiComponents::Typography::Title::Component.new(level: 5)) { "Implementation" } %>
      <% end %>
      <% space.with_item do %>
        <%= render(HakumiComponents::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 HakumiComponents::Space::Component.new(direction: :vertical, size: :small) do |space| %>
      <% space.with_item do %>
        <%= render(HakumiComponents::Typography::Title::Component.new(level: 5)) { "Stabilization" } %>
      <% end %>
      <% space.with_item do %>
        <%= render(HakumiComponents::Typography::Text::Component.new(type: :secondary)) { "Regression suite + launch plan" } %>
      <% end %>
    <% end %>
  <% end %>
<% end %>
Programmatic
Render a timeline with HakumiComponents.renderComponent.
Code
<%= render HakumiComponents::Space::Component.new(size: :default) do %>
  <%= render(HakumiComponents::Button::Component.new(id: "timeline-programmatic-render", type: :primary)) { "Render timeline" } %>
  <%= render(HakumiComponents::Button::Component.new(id: "timeline-programmatic-reverse")) { "Toggle reverse" } %>
<% end %>

<%= render HakumiComponents::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.
items Array<Hash> [] Programmatic item definitions. Each item supports title, body, color, dot, position, and loading.

Timeline.Item API

Prop Type Default Description
title String nil Title or time label for the item.
body String or Component nil Item body 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

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