DEV3 Technologies home

Incident update timeline

A vertical incident timeline with colour-coded status dots and timestamps, newest update first, built from a semantic ordered list.

Tailwind CSSFeedback and empty statestimelineincidentstatuslist

Live preview

Code

<section class="mx-auto max-w-xl px-4" aria-labelledby="inc-title">
  <h2 id="inc-title" class="text-lg font-semibold text-slate-900">Elevated API errors</h2>
  <p class="mb-5 text-sm text-slate-500">Started 14:02 UTC &middot; Resolved after 47 minutes</p>

  <!-- Newest update first, as readers expect on a status page -->
  <ol class="relative ml-3 border-l-2 border-slate-200">
    <li class="mb-6 ml-6">
      <span class="absolute -left-[9px] mt-1 size-4 rounded-full border-2 border-white bg-emerald-500" aria-hidden="true"></span>
      <div class="flex flex-wrap items-baseline gap-x-2">
        <strong class="text-emerald-700">Resolved</strong>
        <time datetime="2026-01-12T14:49:00Z" class="text-xs text-slate-500">14:49 UTC</time>
      </div>
      <p class="mt-1 text-sm text-slate-700">The fix is deployed and error rates are back to normal.</p>
    </li>
    <li class="mb-6 ml-6">
      <span class="absolute -left-[9px] mt-1 size-4 rounded-full border-2 border-white bg-sky-500" aria-hidden="true"></span>
      <div class="flex flex-wrap items-baseline gap-x-2">
        <strong class="text-sky-700">Monitoring</strong>
        <time datetime="2026-01-12T14:31:00Z" class="text-xs text-slate-500">14:31 UTC</time>
      </div>
      <p class="mt-1 text-sm text-slate-700">A fix was released. We are watching the results.</p>
    </li>
    <li class="mb-6 ml-6">
      <span class="absolute -left-[9px] mt-1 size-4 rounded-full border-2 border-white bg-amber-500" aria-hidden="true"></span>
      <div class="flex flex-wrap items-baseline gap-x-2">
        <strong class="text-amber-700">Identified</strong>
        <time datetime="2026-01-12T14:15:00Z" class="text-xs text-slate-500">14:15 UTC</time>
      </div>
      <p class="mt-1 text-sm text-slate-700">A database connection limit was reached.</p>
    </li>
    <li class="ml-6">
      <span class="absolute -left-[9px] mt-1 size-4 rounded-full border-2 border-white bg-rose-500" aria-hidden="true"></span>
      <div class="flex flex-wrap items-baseline gap-x-2">
        <strong class="text-rose-700">Investigating</strong>
        <time datetime="2026-01-12T14:02:00Z" class="text-xs text-slate-500">14:02 UTC</time>
      </div>
      <p class="mt-1 text-sm text-slate-700">Some requests to the API are failing. We are looking into it.</p>
    </li>
  </ol>
</section>

How it works

What it solves

During an outage people want the current status and the story so far, without hunting through chat messages. A timeline with the latest update on top gives both in one scroll.

How it works

The list is an ol with a left border that acts as the spine. Every item is shifted right with ml-6, and its dot is an absolutely positioned span placed with -left-[9px] so it sits centered on the border line (half of the dot width plus half of the 2px stroke). The white ring around each dot, made with border-white, cuts a clean gap in the spine.

Each update uses a strong word for the phase and a time element with a machine readable datetime attribute, so scripts and assistive tools can parse the time while people read "14:49 UTC". Colours follow a simple lifecycle: rose while investigating, amber once identified, sky when monitoring and green on resolution.

Adapting it

  • Render the items from an updates table ordered by newest first.
  • Convert times to the reader's zone on the client by reading the datetime value.
  • Add a short link to the affected components under the heading.

Pitfalls

  • Ordered lists announce position numbers to some screen readers; this is fine, but keep the order consistent.
  • If you change the dot size, recompute the negative offset.
  • Do not drop the text phase and rely on colour; many readers cannot tell the dots apart.

How to use it

  1. Place the section on your incident detail page.
  2. Loop updates from your database into the list items, newest first.
  3. Pick the dot colour and heading colour from the update phase.
  4. Output the timestamp in the datetime attribute in UTC ISO format.

Licence: DEV3 Snippet Licence. Free to use, change and ship in personal and commercial projects. Attribution is appreciated, not required. Please do not redistribute snippets as a collection.

Related snippets