Chronoline visualizes a series of chained events.
<style>
    .custom-marker {
        display: flex;
        width: 2rem;
        height: 2rem;
        align-items: center;
        justify-content: center;
        color: #ffffff;
        border-radius: 50%;
        z-index: 1;
    }
    .ui-chronoline-event-content,
    .ui-chronoline-event-opposite {
        line-height: 1;
    }
    @media screen and (max-width: 960px) {
        .customized-chronoline .ui-chronoline-event:nth-child(even) {
            flex-direction: row !important;
        }
        .customized-chronoline .ui-chronoline-event:nth-child(even) .ui-chronoline-event-content {
            text-align: left !important;
        }
        .customized-chronoline .ui-chronoline-event-opposite {
            flex: 0;
        }
        .customized-chronoline .ui-card {
            margin-top: 1rem;
        }
    }
</style>
<div class="card">
    <h:form>
        <p:messages showDetail="true">
            <p:autoUpdate/>
        </p:messages>
        <h5>Left Align</h5>
        <p:chronoline value="#{chronolineView.events}" var="event">
            <p:commandLink action="#{chronolineView.clickOnEvent(event)}" process="@this">
                <h6 class="mb-0">#{event.status}</h6>
            </p:commandLink>
        </p:chronoline>
    </h:form>
</div>
<div class="card">
    <h5>Right Align</h5>
    <p:chronoline value="#{chronolineView.events}" var="event" align="right">
        #{event.status}
    </p:chronoline>
</div>
<div class="card">
    <h5>Alternate Align</h5>
    <p:chronoline value="#{chronolineView.events}" var="event" align="alternate">
        #{event.status}
    </p:chronoline>
</div>
<div class="card">
    <h5>Opposite Content</h5>
    <p:chronoline value="#{chronolineView.events}" var="event">
        #{event.status}
        <f:facet name="opposite">
            <small class="text-secondary">#{event.date}</small>
        </f:facet>
    </p:chronoline>
</div>
<div class="card">
    <h:form>
        <h5>Customized</h5>
        <p:chronoline value="#{chronolineView.events}" var="event" align="alternate" styleClass="customized-chronoline">
            <p:card>
                <f:facet name="title">
                    #{event.status}
                </f:facet>
                <f:facet name="subtitle">
                    #{event.date}
                </f:facet>
                <p:graphicImage rendered="#{not empty event.image}" width="200" styleClass="shadow-1"
                            value="../../resources/demo/images/product/#{event.image}" alt="#{event.image}"/>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt
                    quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!</p>
                <p:commandButton value="Read more" styleClass="ui-button-flat"/>
            </p:card>
            <f:facet name="marker">
            <span class="custom-marker shadow-1" style="background-color: #{event.color}"><i class="#{event.icon}"/></span>
            </f:facet>
        </p:chronoline>
    </h:form>
</div>
<div class="card">
    <h5>Horizontal</h5>
    <h6>Top Align</h6>
    <p:chronoline value="#{chronolineView.events2}" var="event" layout="horizontal" align="top">
        #{event}
    </p:chronoline>
    <h6>Bottom Align</h6>
    <p:chronoline value="#{chronolineView.events2}" var="event" layout="horizontal" align="bottom">
        #{event}
    </p:chronoline>
    <h6>Alternate Align</h6>
    <p:chronoline value="#{chronolineView.events2}" var="event" layout="horizontal" align="alternate">
        #{event}
    </p:chronoline>
</div>
package org.primefaces.showcase.view.data;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Named;
import java.util.ArrayList;
import java.util.List;
import io.quarkus.runtime.annotations.RegisterForReflection;
@Named
@RequestScoped
@RegisterForReflection(serialization = true)
public class ChronolineView {
    private List<Event> events;
    private List<String> events2;
    @PostConstruct
    public void init() {
        events = new ArrayList<>();
        events.add(new Event("Ordered", "15/10/2020 10:30", "pi pi-shopping-cart", "#9C27B0", "game-controller.jpg"));
        events.add(new Event("Processing", "15/10/2020 14:00", "pi pi-cog", "#673AB7"));
        events.add(new Event("Shipped", "15/10/2020 16:15", "pi pi-shopping-cart", "#FF9800"));
        events.add(new Event("Delivered", "16/10/2020 10:00", "pi pi-check", "#607D8B"));
        events2 = new ArrayList<>();
        events2.add("2020");
        events2.add("2021");
        events2.add("2022");
        events2.add("2023");
    }
    public List<Event> getEvents() {
        return events;
    }
    public List<String> getEvents2() {
        return events2;
    }
    @RegisterForReflection
    public static class Event {
        String status;
        String date;
        String icon;
        String color;
        String image;
        public Event() {
        }
        public Event(String status, String date, String icon, String color) {
            this.status = status;
            this.date = date;
            this.icon = icon;
            this.color = color;
        }
        public Event(String status, String date, String icon, String color, String image) {
            this.status = status;
            this.date = date;
            this.icon = icon;
            this.color = color;
            this.image = image;
        }
        public String getStatus() {
            return status;
        }
        public void setStatus(String status) {
            this.status = status;
        }
        public String getDate() {
            return date;
        }
        public void setDate(String date) {
            this.date = date;
        }
        public String getIcon() {
            return icon;
        }
        public void setIcon(String icon) {
            this.icon = icon;
        }
        public String getColor() {
            return color;
        }
        public void setColor(String color) {
            this.color = color;
        }
        public String getImage() {
            return image;
        }
        public void setImage(String image) {
            this.image = image;
        }
    }
}