Search

Heatmap Tooltips

Heatmap

Show tooltips on heatmap cells to add more context.

Heatmap Tooltips
View live example →

Hover over a heatmap cell to display the tooltip, then click the Show Events button to zoom into the events that make up that cell.

When zoomed in on events, click the return return button in the bottom right hand corner to return to the original view.

The hover event returns a subItem when the targetType is 'cell'.

See Also

Hover over a heatmap cell to display the tooltip, then click the Show Events button to zoom into the events that make up that cell.

When zoomed in on events, click the return return button in the bottom right hand corner to return to the original view.

The onTimelineHover event returns a subItem when the targetType is 'cell'.

See Also

import { createTimeline } from "kronograph";
import data from "./data";

const tooltipElement = document.getElementById("my-tooltip");
const timelineElement = document.getElementById("my-timeline");
const undoButtonElement = document.getElementById("undo-button");

const valueElement = document.getElementById("tooltip-value");
const eventsFromElement = document.getElementById("tooltip-eventsfrom");
const eventsToElement = document.getElementById("tooltip-eventsto");

let lastHoverEvent = null;
let initialRange = null;

const timeline = createTimeline("my-timeline");

const timelineOptions = {
  hover: 0,
  events: {
    heatmapThreshold: 20,
    heatmapDirection: "any",
  },
};

function getValueFromAndTo(entityId, eventIds) {
  let valueFrom = 0;
  let valueTo = 0;
  const heatmapValue = timeline.options().events.heatmapValue;

  eventIds.forEach((eventId) => {
    const {
      entityIds: { from, to },
      data: eventData,
    } = timeline.getEvent(eventId);

    if (from.includes(entityId)) {
      valueFrom += heatmapValue ? eventData[heatmapValue] : 1;
    }
    if (to.includes(entityId)) {
      valueTo += heatmapValue ? eventData[heatmapValue] : 1;
    }
  });

  return { valueFrom, valueTo };
}

function showTooltip(pointerEvent) {
  const { width, height, x, y, value } = pointerEvent.subItem;
  const { valueFrom, valueTo } = getValueFromAndTo(pointerEvent.id, pointerEvent.eventIds);

  const bounds = timelineElement.getBoundingClientRect();

  const left = bounds.left + x + width / 2;
  const top = bounds.top + y - height / 2;

  tooltipElement.style.display = "flex";
  tooltipElement.style.left = `${left}px`;
  tooltipElement.style.top = `${top}px`;

  valueElement.innerText = value;
  eventsFromElement.innerText = valueFrom;
  eventsToElement.innerText = valueTo;
  lastHoverEvent = pointerEvent;
}

function hideTooltip() {
  lastHoverEvent = null;
  tooltipElement.style.display = "none";
}

function handleHover(event) {
  if (event.targetType === "cell" && event.subItem !== undefined) {
    showTooltip(event);
  } else {
    hideTooltip();
  }
}

function handleTooltipFit() {
  if (lastHoverEvent === null) {
    return;
  }
  timeline.range(lastHoverEvent.startTime, lastHoverEvent.endTime);
  undoButtonElement.style.display = "flex";
  hideTooltip();
  enableUndoButton();
}

function revertToLastVisibleRange() {
  if (initialRange !== null) {
    timeline.range(initialRange.start, initialRange.end);
    undoButtonElement.disabled = true;
  }
}

function enableUndoButton() {
  if (undoButtonElement.disabled) {
    undoButtonElement.disabled = false;
  }
}

function handleRangeChange(event) {
  if (event.why !== "auto") {
    enableUndoButton();
  }
  if (!initialRange) {
    initialRange = timeline.range();
  }
}

document.getElementById("tooltip-fit").addEventListener("click", handleTooltipFit);
undoButtonElement.addEventListener("click", revertToLastVisibleRange);
timeline.on("hover", handleHover);
timeline.on("range", handleRangeChange);

timeline.options(timelineOptions);
timeline.set(data);
timeline.fit();
export default {
  entities: {
    "Aurora Bancorp": {
      color: "#4e79a7",
    },
    "Better Life Bank": {
      color: "#f28e2c",
    },
    "Ace Financial Group": {
      color: "#e15759",
    },
    "Grand Mutual Bank": {
      color: "#76b7b2",
    },
    "Felicity Financial Services": {
      color: "#59a14f",
    },
  },
  events: {
    event0: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 103,
      },
      time: 1716845042401.983,
    },
    event1: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 1522,
      },
      time: 1704300247970.444,
    },
    event2: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 2519,
      },
      time: 1704826361998.4548,
    },
    event3: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 1744,
      },
      time: 1721561387584.9785,
    },
    event4: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 1292,
      },
      time: 1721436187577.0662,
    },
    event5: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 1913,
      },
      time: 1715184891178.0125,
    },
    event6: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 1379,
      },
      time: 1720022197785.7358,
    },
    event7: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 2108,
      },
      time: 1713047293850.0168,
    },
    event8: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 39987,
      },
      time: 1719556922296.1238,
    },
    event9: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 6269,
      },
      time: 1717726178569.1255,
    },
    event10: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 4629,
      },
      time: 1718167137411.861,
    },
    event11: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 4112,
      },
      time: 1719690540773.6128,
    },
    event12: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 44477,
      },
      time: 1718653783292.392,
    },
    event13: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 86674,
      },
      time: 1719055763972.7158,
    },
    event14: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 96953,
      },
      time: 1718812764374.0154,
    },
    event15: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 57831,
      },
      time: 1717355969771.8218,
    },
    event16: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 1992,
      },
      time: 1721029217990.7224,
    },
    event17: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 471,
      },
      time: 1722545977814.828,
    },
    event18: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 2274,
      },
      time: 1712785338304.0298,
    },
    event19: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 3067,
      },
      time: 1706715885813.1304,
    },
    event20: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 670,
      },
      time: 1705034721408.0198,
    },
    event21: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 648,
      },
      time: 1719489884462.4038,
    },
    event22: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 325,
      },
      time: 1721614571235.6663,
    },
    event23: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 851,
      },
      time: 1705237236251.1895,
    },
    event24: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 3121,
      },
      time: 1721380170448.32,
    },
    event25: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 1778,
      },
      time: 1719476838892.334,
    },
    event26: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 3781,
      },
      time: 1714459016034.4941,
    },
    event27: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 1165,
      },
      time: 1713136401986.9214,
    },
    event28: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 2237,
      },
      time: 1712559528845.578,
    },
    event29: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 1535,
      },
      time: 1720931783679.7734,
    },
    event30: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 1622,
      },
      time: 1721528143853.7964,
    },
    event31: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 523,
      },
      time: 1709514478039.349,
    },
    event32: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1257,
      },
      time: 1715409427247.5706,
    },
    event33: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 736,
      },
      time: 1707482336867.2246,
    },
    event34: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 184,
      },
      time: 1725199319145.929,
    },
    event35: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1058,
      },
      time: 1713232568113.0273,
    },
    event36: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1429,
      },
      time: 1721868788309.195,
    },
    event37: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1197,
      },
      time: 1707839323010.2188,
    },
    event38: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 2522,
      },
      time: 1717712034817.7363,
    },
    event39: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 3094,
      },
      time: 1724919209625.5513,
    },
    event40: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1121,
      },
      time: 1718493292818.4546,
    },
    event41: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 2878,
      },
      time: 1714709244615.406,
    },
    event42: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1504,
      },
      time: 1715372672224.4255,
    },
    event43: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 320,
      },
      time: 1710331215554.826,
    },
    event44: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1906,
      },
      time: 1710184345462.6362,
    },
    event45: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1246,
      },
      time: 1725198486655.9883,
    },
    event46: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1476,
      },
      time: 1706451804586.463,
    },
    event47: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 192,
      },
      time: 1723811742494.3857,
    },
  },
  eventTypes: {
    default: {
      lineWidth: 2,
      color: "#00a2ed",
    },
  },
};
<!doctype html>
<html>
  <head>
    <link rel="stylesheet" href="@ci/theme/kg/css/examples.css" />
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <div class="story">
      <div class="story__timeline" id="my-timeline">
        <button
          class="button button--neutral"
          id="undo-button"
          disabled
          title="Return To Previous View"
        >
          <i class="fas fa-undo"></i>
        </button>
      </div>
      <div id="my-tooltip" class="story__tooltip stack stack--small">
        <div>
          <div class="story__label--grey">Cell Value:</div>
          <div class="story__spacer"></div>
          <div class="story__label--white" id="tooltip-value"></div>
        </div>
        <div>
          <div class="story__label--grey">Events from:</div>
          <div class="story__spacer"></div>
          <div class="story__label--white" id="tooltip-eventsfrom"></div>
        </div>
        <div>
          <div class="story__label--grey">Events to:</div>
          <div class="story__spacer"></div>
          <div class="story__label--white" id="tooltip-eventsto"></div>
        </div>
        <div>
          <button class="button button--neutral" title="Focus Events in Cell" id="tooltip-fit">
            <span className="story__label">Show Events</span>
          </button>
        </div>
      </div>
    </div>
    <script type="module" src="./code.js"></script>
  </body>
</html>
@import url("https://fonts.googleapis.com/css?family=Muli:200,400,500,700&display=swap");

body {
  font-family: "Muli", "Helvetica Neue", Helvetica, sans-serif;
  font-weight: 400;
  margin: 0;
}

.story {
  background-color: hsl(210, 18%, 22%); /* Charcoal */
  color: hsl(214, 15%, 91%);
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.story__timeline {
  flex: 2;
  min-height: 0px;
}

.story__tooltip {
  background-color: hsl(209, 15%, 28%);
  border-radius: 0.1975rem;
  color: hsl(216, 33%, 97%);
  display: none;
  max-height: 300px;
  max-width: 300px;
  overflow-y: auto;
  padding: 0.666rem;
  position: absolute;
  z-index: 1;
}

.story__label {
  font-size: 0.8em;
}

.story__label--grey {
  color: hsl(211, 13%, 65%);
  font-size: 0.8em;
}

.story__label--white {
  color: hsl(214, 15%, 91%);
  font-size: 0.8em;
  margin-left: var(--s-3);
}

.story__spacer {
  flex: 1;
}

#tooltip-fit {
  font-size: 16px;
  white-space: nowrap;
}

.stack {
  flex-direction: column;
  justify-content: flex-start;
}

.story__tooltip > * {
  display: flex;
  align-items: center;
}

.stack > * {
  margin-bottom: 0;
  margin-top: 0;
}

.stack > * + * {
  margin-top: 1rem;
}

.stack--small > * + * {
  margin-top: 0.666rem;
}

#undo-button {
  border-radius: 10rem;
  height: 50px;
  width: 50px;
  position: fixed;
  right: 20px;
  bottom: 60px;
  background-color: #0691d3;
  z-index: 1;
}

#undo-button:disabled {
  background-color: grey;
}

#undo-button:hover:not(:disabled) {
  background-color: #ffffff;
}
import React, { useState, useRef } from "react";
import { createRoot } from "react-dom/client";
import Timeline from "kronograph/react/Timeline";
import data from "./data";

const options = {
  hover: 0,
  events: {
    heatmapThreshold: 20,
    heatmapDirection: "any",
  },
};

function getValueFromAndTo(entityId, eventIds) {
  let valueFrom = 0;
  let valueTo = 0;
  const heatmapValue = options.events.heatmapValue;

  eventIds.forEach((eventId) => {
    const {
      entityIds: { from, to },
      data: eventData,
    } = data.events[eventId];

    if (from.includes(entityId)) {
      valueFrom += heatmapValue ? eventData[heatmapValue] : 1;
    }
    if (to.includes(entityId)) {
      valueTo += heatmapValue ? eventData[heatmapValue] : 1;
    }
  });

  return { valueFrom, valueTo };
}

export const Demo = () => {
  const timelineRef = useRef(null);
  const initialRange = useRef(null);
  const [tooltip, setTooltip] = useState(null);
  const [undoButton, setUndoButton] = useState(false);
  const [range, setRange] = useState();

  return (
    <div className="story">
      <Timeline
        className="story__timeline"
        entities={data.entities}
        ref={timelineRef}
        events={data.events}
        eventTypes={data.eventTypes}
        range={range}
        options={options}
        onTimelineChange={(event) => {
          if (event.range) {
            if (!initialRange.current) {
              initialRange.current = event.range;
            }
            setUndoButton(true);
            setRange(event.range);
          }
        }}
        onTimelineHover={(pointerEvent) => {
          if (pointerEvent.targetType === "cell" && pointerEvent.subItem !== undefined) {
            const { valueFrom, valueTo } = getValueFromAndTo(
              pointerEvent.id,
              pointerEvent.eventIds
            );
            const { width, height, x, y } = pointerEvent.subItem;
            setTooltip({
              value: pointerEvent.subItem.value,
              valueFrom,
              valueTo,
              startTime: pointerEvent.startTime,
              endTime: pointerEvent.endTime,
              left: x + width / 2,
              top: y - height / 2,
            });
          } else {
            setTooltip(null);
          }
        }}
      />
      <button
        onClick={() => {
          setRange(initialRange.current);
          setUndoButton(false);
        }}
        className="button button--neutral"
        disabled={undoButton}
        id="undo-button"
        title="Return To Previous View"
      >
        <i className="fas fa-undo"></i>
      </button>
      {tooltip ? (
        <div
          id="my-tooltip"
          className="story__tooltip stack stack--small"
          style={{
            display: "flex",
            left: tooltip.left,
            top: tooltip.top,
          }}
        >
          <div>
            <div className="story__label--grey">Cell Value:</div>
            <div className="story__spacer"></div>
            <div className="story__label--white">{tooltip.value}</div>
          </div>
          <div>
            <div className="story__label--grey">Events from:</div>
            <div className="story__spacer"></div>
            <div className="story__label--white">{tooltip.valueFrom}</div>
          </div>
          <div>
            <div className="story__label--grey">Events to:</div>
            <div className="story__spacer"></div>
            <div className="story__label--white">{tooltip.valueTo}</div>
          </div>
          <div>
            <button
              onClick={() => {
                initialRange.current = { start: range.start, end: range.end };
                setRange({ start: tooltip.startTime, end: tooltip.endTime });
                setTooltip(null);
                setUndoButton(true);
              }}
              className="button button--neutral"
              title="Focus Events in Cell"
              id="tooltip-fit"
            >
              <span className="story__label">Show Events</span>
            </button>
          </div>
        </div>
      ) : null}
    </div>
  );
};

const root = createRoot(document.getElementById("my-timeline"));
root.render(<Demo />);
export default {
  entities: {
    "Aurora Bancorp": {
      color: "#4e79a7",
    },
    "Better Life Bank": {
      color: "#f28e2c",
    },
    "Ace Financial Group": {
      color: "#e15759",
    },
    "Grand Mutual Bank": {
      color: "#76b7b2",
    },
    "Felicity Financial Services": {
      color: "#59a14f",
    },
  },
  events: {
    event0: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 103,
      },
      time: 1716845042401.983,
    },
    event1: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 1522,
      },
      time: 1704300247970.444,
    },
    event2: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 2519,
      },
      time: 1704826361998.4548,
    },
    event3: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 1744,
      },
      time: 1721561387584.9785,
    },
    event4: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 1292,
      },
      time: 1721436187577.0662,
    },
    event5: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 1913,
      },
      time: 1715184891178.0125,
    },
    event6: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 1379,
      },
      time: 1720022197785.7358,
    },
    event7: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Better Life Bank",
      },
      data: {
        amount: 2108,
      },
      time: 1713047293850.0168,
    },
    event8: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 39987,
      },
      time: 1719556922296.1238,
    },
    event9: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 6269,
      },
      time: 1717726178569.1255,
    },
    event10: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 4629,
      },
      time: 1718167137411.861,
    },
    event11: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 4112,
      },
      time: 1719690540773.6128,
    },
    event12: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 44477,
      },
      time: 1718653783292.392,
    },
    event13: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 86674,
      },
      time: 1719055763972.7158,
    },
    event14: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 96953,
      },
      time: 1718812764374.0154,
    },
    event15: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 57831,
      },
      time: 1717355969771.8218,
    },
    event16: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 1992,
      },
      time: 1721029217990.7224,
    },
    event17: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 471,
      },
      time: 1722545977814.828,
    },
    event18: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 2274,
      },
      time: 1712785338304.0298,
    },
    event19: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 3067,
      },
      time: 1706715885813.1304,
    },
    event20: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 670,
      },
      time: 1705034721408.0198,
    },
    event21: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 648,
      },
      time: 1719489884462.4038,
    },
    event22: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 325,
      },
      time: 1721614571235.6663,
    },
    event23: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Ace Financial Group",
      },
      data: {
        amount: 851,
      },
      time: 1705237236251.1895,
    },
    event24: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 3121,
      },
      time: 1721380170448.32,
    },
    event25: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 1778,
      },
      time: 1719476838892.334,
    },
    event26: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 3781,
      },
      time: 1714459016034.4941,
    },
    event27: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 1165,
      },
      time: 1713136401986.9214,
    },
    event28: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 2237,
      },
      time: 1712559528845.578,
    },
    event29: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 1535,
      },
      time: 1720931783679.7734,
    },
    event30: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 1622,
      },
      time: 1721528143853.7964,
    },
    event31: {
      entityIds: {
        from: "Aurora Bancorp",
        to: "Grand Mutual Bank",
      },
      data: {
        amount: 523,
      },
      time: 1709514478039.349,
    },
    event32: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1257,
      },
      time: 1715409427247.5706,
    },
    event33: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 736,
      },
      time: 1707482336867.2246,
    },
    event34: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 184,
      },
      time: 1725199319145.929,
    },
    event35: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1058,
      },
      time: 1713232568113.0273,
    },
    event36: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1429,
      },
      time: 1721868788309.195,
    },
    event37: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1197,
      },
      time: 1707839323010.2188,
    },
    event38: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 2522,
      },
      time: 1717712034817.7363,
    },
    event39: {
      entityIds: {
        from: "Better Life Bank",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 3094,
      },
      time: 1724919209625.5513,
    },
    event40: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1121,
      },
      time: 1718493292818.4546,
    },
    event41: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 2878,
      },
      time: 1714709244615.406,
    },
    event42: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1504,
      },
      time: 1715372672224.4255,
    },
    event43: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 320,
      },
      time: 1710331215554.826,
    },
    event44: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1906,
      },
      time: 1710184345462.6362,
    },
    event45: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1246,
      },
      time: 1725198486655.9883,
    },
    event46: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 1476,
      },
      time: 1706451804586.463,
    },
    event47: {
      entityIds: {
        from: "Ace Financial Group",
        to: "Felicity Financial Services",
      },
      data: {
        amount: 192,
      },
      time: 1723811742494.3857,
    },
  },
  eventTypes: {
    default: {
      lineWidth: 2,
      color: "#00a2ed",
    },
  },
};
<!doctype html>
<html>
  <head>
    <link rel="stylesheet" href="@ci/theme/kg/css/examples.css" />
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <div id="my-timeline" style="height: 100vh"></div>
    <script type="module" src="./code.jsx"></script>
  </body>
</html>
@import url("https://fonts.googleapis.com/css?family=Muli:200,400,500,700&display=swap");

body {
  font-family: "Muli", "Helvetica Neue", Helvetica, sans-serif;
  font-weight: 400;
  margin: 0;
}

.story {
  background-color: hsl(210, 18%, 22%); /* Charcoal */
  color: hsl(214, 15%, 91%);
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.story__timeline {
  flex: 2;
  min-height: 0px;
}

.story__tooltip {
  background-color: hsl(209, 15%, 28%);
  border-radius: 0.1975rem;
  color: hsl(216, 33%, 97%);
  display: none;
  max-height: 300px;
  max-width: 300px;
  overflow-y: auto;
  padding: 0.666rem;
  position: absolute;
  z-index: 1;
}

.story__label {
  font-size: 0.8em;
}

.story__label--grey {
  color: hsl(211, 13%, 65%);
  font-size: 0.8em;
}

.story__label--white {
  color: hsl(214, 15%, 91%);
  font-size: 0.8em;
  margin-left: var(--s-3);
}

.story__spacer {
  flex: 1;
}

#tooltip-fit {
  font-size: 16px;
  white-space: nowrap;
}

.stack {
  flex-direction: column;
  justify-content: flex-start;
}

.story__tooltip > * {
  display: flex;
  align-items: center;
}

.stack > * {
  margin-bottom: 0;
  margin-top: 0;
}

.stack > * + * {
  margin-top: 1rem;
}

.stack--small > * + * {
  margin-top: 0.666rem;
}

#undo-button {
  border-radius: 10rem;
  height: 50px;
  width: 50px;
  position: fixed;
  right: 20px;
  bottom: 60px;
  background-color: #0691d3;
  z-index: 1;
}

#undo-button:disabled {
  background-color: grey;
}

#undo-button:hover:not(:disabled) {
  background-color: #ffffff;
}

Terms of use

These terms do not alter or supersede any existing agreements between you (or your employer) and us.

By accessing or using any Content you agree to be bound by these Terms of Use. Please review these terms carefully before using the website.

The contents of this website, including but not limited to any text, code samples, API references, schemas, interactive tools, and other materials (collectively, the 'Content'), are made available for informational and internal evaluation purposes only. All intellectual property rights in the Content are reserved. No licence is granted to use the Content for any commercial purpose, or to copy, distribute, modify, reverse-engineer, or incorporate any part of the Content into any product or service, without our prior written consent.

This Content is provided “as is” and “as available,” without any representations, warranties, or guarantees of any kind, whether express or implied, including but not limited to implied warranties of merchantability, fitness for a particular purpose, non-infringement, or accuracy. To the fullest extent permitted by applicable law, we expressly exclude and disclaim all implied warranties, conditions, and other terms that might otherwise be implied.

We disclaim all liability for any loss or damage, whether direct, indirect, incidental, consequential, or otherwise, arising from any reliance placed on the Content or from your use of it, to the fullest extent permitted by applicable law. By continuing to access or use the Content, you acknowledge and agree to these terms.