ComponentsTimeline

Timeline

component

Vertical events with state dots — activity feeds, build history, version logs.

Release progress
Where v2.4.0 is in the pipeline.
  1. v2.4.0 deployed2 min ago
    Production · 12 services updated
  2. Running testsin progress
    348 / 412 passed
  3. Build artifacts
    Pending — waits on test pass
  4. Notify subscribers

Composes: Avatar · Badges & pills

Recipe CSS

This is the exact CSS your kit ships for Timeline — token-driven, so it re-themes with every knob. Get it (and the rest) from the configurator's Use kit panel.

/* === Timeline (Tier 4 #17) ===========================================
 * Verticale events met dots + connecting line. De line is een ::before
 * pseudo-element die door alle items loopt; eindigt op het laatste item.
 * Dots: filled (done), pulse-ring (current), hollow (future). */
.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
}
.timeline::before {
  content: '';
  position: absolute;
  left: 10px;
  top: 10px;
  bottom: 10px;
  width: 1.5px;
  background: var(--k-border);
}
.timeline__item {
  position: relative;
  display: flex;
  gap: var(--k-s-14);
  padding: var(--k-s-6) 0;
  z-index: 1;
}
.timeline__dot {
  flex-shrink: 0;
  width: calc(var(--k-in-h-default) - 0.875rem);
  height: calc(var(--k-in-h-default) - 0.875rem);
  border-radius: 50%;
  background: var(--k-surface);
  border: max(1.5px, var(--k-bw)) solid var(--k-border);
  display: grid;
  place-items: center;
  color: var(--k-fg-muted);
  margin-top: 1px;
}
.timeline__dot svg { width: var(--k-icon-xs); height: var(--k-icon-xs); }
.timeline__item--done .timeline__dot {
  background: var(--k-primary);
  border-color: transparent;
  color: var(--k-primary-fg);
}
.timeline__item--current .timeline__dot {
  background: var(--k-surface);
  border-color: var(--k-primary);
  position: relative;
}
/* The not-yet / future state (the 3rd checklist step beside --done / --current),
   so a status tracker reads done › current › upcoming without hand-rolled greys. */
.timeline__item--upcoming .timeline__title { color: var(--k-fg-muted); }
.timeline__item--upcoming .timeline__dot { color: var(--k-fg-faint); }
.timeline__pulse {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--k-primary);
  position: relative;
}
.timeline__pulse::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  background: var(--k-primary);
  opacity: 0.25;
  animation: timeline-pulse 1.6s ease-in-out infinite;
}
@keyframes timeline-pulse {
  0%, 100% { transform: scale(1); opacity: 0.25; }
  50% { transform: scale(1.6); opacity: 0; }
}
.timeline__body { flex: 1; min-width: 0; padding-bottom: var(--k-s-4); }
.timeline__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--k-s-8);
}
.timeline__title { font-size: var(--k-type-body); font-weight: var(--k-weight-semibold); color: var(--k-fg); }
.timeline__time {
  font-size: var(--k-type-caption);
  color: var(--k-fg-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.timeline__desc { font-size: var(--k-type-small); color: var(--k-fg-muted); margin-top: var(--k-s-2); }