Skip to content

Timeline View

The FUITimelineCell and FUITimelineMarkerCell are Interface-Builder-designable UITableViewCell controls, used to construct the Timeline View, which presents information or events in chronological order.


The FUITimelinePreviewTableViewCell is an Interface-Builder-designable UI component that extends NibDesignableTableViewCell which contains a FUITimelinePreviewView. It resizes itself to fit content using the auto-layout size of FUITimelinePreviewView.


The FUITimelinePreviewView shows an excerpt of your project's milestones in a convenient linear visual presentation. By default, each task node is ordered by date and can be classified as open, complete, or end. Timeline Preview augments task management by prioritizing overdue tasks as well as tasks closest to their due date but not yet marked as complete. This implementation aims to present the most pressing issues to the top of your task queue. Timeline Preview is supported across all currently supported Apple iOS devices.




  • FUITimelineCell is a selectable cell intended for timelines that require open and complete status that displays timeline details. Selecting the cell changes the card background color to the framework-preferred color: FioriUIColorStyle.line.
  • It uses a vertical line and nodeImageView as a separator. Left of the vertical line is the timeline event stack view that contains eventLabel and eventImageView; right of the vertical line is the main stack view that contains headlineLabel and subheadlineLabel.
  • Below the main view is an attribute stack view with attributeLabel and subAttributeLabel laid out horizontally.
  • To the right of the main view is a status view that contains statusLabel, statusImage, substatusLabel, and substatusImage laid out vertically.


  • FUITimelineMarkerCell is a non-selectable cell with selectionStyle set to .none that is intended for timelines with start, inactive, early end, and end status that displays timeline information.
  • It uses a vertical line and a node image as a separator. Left of the vertical line is the timeline event section that contains eventLabel and eventImageView; right of the vertical line is titleLabel.
  • The vertical line contains leadingTimeline on the top, nodeImageView in the middle, and a trailingTimeline at the bottom.


A FUITimelineCell can be used freely within any UITableView:

Register the FUITimelineCell and FUITimelineMarkerCell controls in the viewDidLoad function:

    override func viewDidLoad() {
        tableView.register(FUITimelineCell.self, forCellReuseIdentifier: FUITimelineCell.reuseIdentifier)
        tableView.register(FUITimelineMarkerCell.self, forCellReuseIdentifier: FUITimelineMarkerCell.reuseIdentifier)
        // ...

Initialize and configure cells in tableView(_:cellForRowAt:):

Though both options are marked public, you should always use the Text: String and Image: UIImage properties to set cell content, instead of directly setting values to the @IBOutlet. This allows the implementation to optimize the constraints for the given content. It is fine to set other properties of the @IBOutlet, such as font style or color, opacity, etc.

  • For FUITimelineCell:
    let cell = tableView.dequeueReusableCell(withIdentifier: FUITimelineCell.reuseIdentifier, for: indexPath) as! FUITimelineCell
    cell.headlineText = "Planned Downtime Period Identified"
    cell.subheadlineText = "Work Package"
    cell.nodeImage =
    cell.eventText = "9:45\nAM"
    cell.eventImage = #imageLiteral(resourceName: "rain")
    cell.statusImage = #imageLiteral(resourceName: "ErrorIcon")
    cell.subStatusText = "Active"
    return cell
  • For FUITimelineMarkerCell:
    let cell = tableView.dequeueReusableCell(withIdentifier: FUITimelineMarkerCell.reuseIdentifier, for: indexPath) as! FUITimelineMarkerCell
    cell.titleText = "Project Start"
    cell.nodeImage = FUITimelineNode.start
    cell.eventText = "12/6/15"
    cell.showLeadingTimeline = false
    return cell
  • For FUITimelinePreviewTableViewCell:
    //Your data model
    var data: [FUITimelineItem] {
    let item0 = FUITimelineItem()
    item0.title = "Planned Downtime Period Identified for Tasks"
    item0.due = Date(timeIntervalSinceNow: -86400 * 2) // 86400 sec equal to 1 day
    item0.status = .complete

    let item1 = FUITimelineItem()
    item1.title = "UX Design Review"
    item1.due = Date(timeIntervalSinceNow: -86400)
    item1.status = .open

    let item2 = FUITimelineItem()
    item2.title = "Planned Downtime Period Identified for Tasks"
    item2.due = Date()
    item2.status = .open

    let item3 = FUITimelineItem()
    item3.title = "UX Design Review"
    item3.due = Date(timeIntervalSinceNow: 86400)
    item3.status = .open

    let item4 = FUITimelineItem()
    item4.title = "Project End"
    item4.due = Date(timeIntervalSinceNow: 86400 * 2.0)
    item4.status = .end

    return [item0, item1, item2, item3, item4]

    //override dataSource method
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: FUITimelinePreviewTableViewCell.reuseIdentifier, for: indexPath) as! FUITimelinePreviewTableViewCell

    cell.timelinePreviewView.header.titleLabel.text = "Timeline"
    cell.timelinePreviewView.header.attributeLabel.text = "attribute"
    cell.timelinePreviewView.header.isDisclosureAccessoryHidden = false
    cell.timelinePreviewView.header.didSelectHandler = {
        print("header is selected")

    cell.timelinePreviewView.numberOfColumns = 4 //set numberOfColumns if you want to change number of columns showing

    return cell

Last update: April 14, 2021