Navigation

v0.0.4
Data display

Uptime

How a service has been, one tick to a day.

On this page

Uptime shows how a service has been, one tick to a day: the row a status page is made of. It is a list whose items say in words what each day was like. The stylesheet draws each item as a thin upright tick and moves its words out of sight, where assistive technology still reads them.

Uptime

<div class="card max-w(480) mx-auto">  <div class="card-header">    <h3 class="card-title">API</h3>    <p class="card-description">99.94% over the last 45 days</p>    <span class="card-action badge badge-success badge-dot">Operational</span>  </div>  <ol class="uptime" aria-label="API, the last 45 days">    <li class="uptime-day">29 September: operational</li>    <li class="uptime-day">30 September: operational</li>    <li class="uptime-day">1 October: operational</li>    <li class="uptime-day">2 October: operational</li>    <li class="uptime-day">3 October: operational</li>    <li class="uptime-day">4 October: operational</li>    <li class="uptime-day">5 October: operational</li>    <li class="uptime-day">6 October: operational</li>    <li class="uptime-day">7 October: operational</li>    <li class="uptime-day">8 October: operational</li>    <li class="uptime-day">9 October: operational</li>    <li class="uptime-day uptime-degraded">10 October: degraded for 42 minutes</li>    <li class="uptime-day">11 October: operational</li>    <li class="uptime-day">12 October: operational</li>    <li class="uptime-day">13 October: operational</li>    <li class="uptime-day">14 October: operational</li>    <li class="uptime-day">15 October: operational</li>    <li class="uptime-day">16 October: operational</li>    <li class="uptime-day">17 October: operational</li>    <li class="uptime-day">18 October: operational</li>    <li class="uptime-day">19 October: operational</li>    <li class="uptime-day">20 October: operational</li>    <li class="uptime-day">21 October: operational</li>    <li class="uptime-day">22 October: operational</li>    <li class="uptime-day">23 October: operational</li>    <li class="uptime-day uptime-down">24 October: down for 18 minutes</li>    <li class="uptime-day uptime-degraded">25 October: degraded for 2 hours</li>    <li class="uptime-day">26 October: operational</li>    <li class="uptime-day">27 October: operational</li>    <li class="uptime-day">28 October: operational</li>    <li class="uptime-day">29 October: operational</li>    <li class="uptime-day">30 October: operational</li>    <li class="uptime-day">31 October: operational</li>    <li class="uptime-day">1 November: operational</li>    <li class="uptime-day">2 November: operational</li>    <li class="uptime-day">3 November: operational</li>    <li class="uptime-day">4 November: operational</li>    <li class="uptime-day">5 November: operational</li>    <li class="uptime-day">6 November: operational</li>    <li class="uptime-day">7 November: operational</li>    <li class="uptime-day">8 November: operational</li>    <li class="uptime-day">9 November: operational</li>    <li class="uptime-day">10 November: operational</li>    <li class="uptime-day">11 November: operational</li>    <li class="uptime-day">12 November: operational</li>  </ol></div>

#Quiet when it is good

A day that went well is a quiet tint of ink, not a green bar. Ninety green bars say nothing, ninety times; a calm row leaves the eye free for the days that did not go well. Those take a status hue and a class:

  • uptime-degraded, in the warning hue: the service was slow or partly failing.
  • uptime-down, in the danger hue: the service was down.
  • uptime-none, in the tone of a hairline: there is no data for that day, such as the days before the service existed.

The hue is a status and never stands alone: the words in each item say what happened and for how long. Under the pointer a tick stands taller at once, so a reader can tell which day they are on before a tooltip opens.

#Size

Ticks share the row's width, 2px apart, and are never under 2px or over 8px wide, so thirty days and ninety days both fill a card without a width written anywhere. The row is 32px tall. uptime-sm is 16px with ticks 1px apart, for a line of a table or a list.

Small

<div class="card max-w(480) mx-auto">  <dl class="data-list">    <div class="data-list-item">      <dt class="data-list-term">Dashboard</dt>      <dd class="data-list-value">        <ol class="uptime uptime-sm" aria-label="Dashboard, the last 14 days">          <li class="uptime-day">30 October: operational</li>          <li class="uptime-day">31 October: operational</li>          <li class="uptime-day">1 November: operational</li>          <li class="uptime-day">2 November: operational</li>          <li class="uptime-day">3 November: operational</li>          <li class="uptime-day">4 November: operational</li>          <li class="uptime-day">5 November: operational</li>          <li class="uptime-day">6 November: operational</li>          <li class="uptime-day">7 November: operational</li>          <li class="uptime-day">8 November: operational</li>          <li class="uptime-day">9 November: operational</li>          <li class="uptime-day">10 November: operational</li>          <li class="uptime-day">11 November: operational</li>          <li class="uptime-day">12 November: operational</li>        </ol>      </dd>    </div>    <div class="data-list-item">      <dt class="data-list-term">Webhooks</dt>      <dd class="data-list-value">        <ol class="uptime uptime-sm" aria-label="Webhooks, the last 14 days">          <li class="uptime-day uptime-none">30 October: no data</li>          <li class="uptime-day uptime-none">31 October: no data</li>          <li class="uptime-day uptime-none">1 November: no data</li>          <li class="uptime-day">2 November: operational</li>          <li class="uptime-day">3 November: operational</li>          <li class="uptime-day">4 November: operational</li>          <li class="uptime-day uptime-degraded">5 November: degraded for 12 minutes</li>          <li class="uptime-day">6 November: operational</li>          <li class="uptime-day">7 November: operational</li>          <li class="uptime-day">8 November: operational</li>          <li class="uptime-day">9 November: operational</li>          <li class="uptime-day">10 November: operational</li>          <li class="uptime-day">11 November: operational</li>          <li class="uptime-day">12 November: operational</li>        </ol>      </dd>    </div>  </dl></div>

#Uptime or heatmap

A tick is a state: well, degraded, down, unknown. When each cell is a number on a scale, such as requests per day, use a heatmap, whose cells are as dark as their value. The state of a service now is a badge with a dot.

#Accessibility

  • Write it as an <ol>, oldest day first, and name it with aria-label: the service and the period.
  • Each item's text is the day and what happened, in words: "24 October: down for 18 minutes". It is not shown, but it is what a screen reader reads, so do not leave an item empty.
  • Give the summary beside the row as text too: the share of time the service was up, and its state now.
  • In forced colors a good day is the text color, a day that was not is the system highlight, and a day with no data is the system's grey.

#Classes

ClassDescription
uptimeThe row, 32px tall: ticks that share its width, 2px apart
uptime-smA 16px row with ticks 1px apart, for a line of a table. With uptime
uptime-dayOne day, as a tick in a quiet tint of ink. Its text says what the day was like and is moved out of sight
uptime-degradedA day the service was slow or partly failing, in the warning hue. With uptime-day
uptime-downA day the service was down, in the danger hue. With uptime-day
uptime-noneA day with no data, in the tone of a hairline. With uptime-day

#Custom properties

PropertyDefaultDescription
--uptime-height2remHeight of the row
--uptime-gap2pxSpace between ticks
--uptime-colorvar(--color-surface-inverse)The ink a good day is tinted with

#Source

@master/ui/components/uptime.css
/* * Uptime: how a service has been, one tick to a day. * It is a list whose items say in words what each day was like; the stylesheet draws each as a thin upright * tick and keeps the words for assistive technology. A day that went well is a quiet tint of ink, so the row * is calm and the days that did not go well are what is seen: degraded in the warning hue, down in the danger * hue, and a day with no data as a hairline's tone. The hues are a status, and the words in each item say it. * Ticks share the row's width, 2px apart, between 2px and 8px wide and 32px tall. Under the pointer a tick * stands taller, at once. */@layer components {  .uptime {    --uptime-height: 2rem;    --uptime-gap: 2px;    --uptime-color: var(--color-surface-inverse);    display: flex;    align-items: flex-end;    gap: var(--uptime-gap);    min-width: 0;    height: var(--uptime-height);    margin: 0;    padding: 0;    list-style: none;    &.uptime-sm {      --uptime-height: 1rem;      --uptime-gap: 1px;    }    @media (forced-colors: active) {      --uptime-color: CanvasText;    }  }  /* One day. Its words are moved out of sight, not removed. */  .uptime-day {    --uptime-fill: color-mix(in oklab, var(--uptime-color) 24%, transparent);    flex: 1 1 0;    min-width: 2px;    max-width: .5rem;    height: 100%;    margin: 0;    padding: 0;    border-radius: 1.5px;    overflow: hidden;    background: var(--uptime-fill);    text-indent: -100vmax;    white-space: nowrap;    cursor: default;    &.uptime-degraded {      --uptime-fill: var(--color-warning);    }    &.uptime-down {      --uptime-fill: var(--color-danger);    }    /* No data: the day is there, and nothing is known about it. */    &.uptime-none {      --uptime-fill: var(--color-line-strong);    }    @media (hover: hover) {      &:hover {        --uptime-fill: color-mix(in oklab, var(--uptime-color) 55%, transparent);        scale: 1 1.18;        transform-origin: bottom;        &.uptime-degraded {          --uptime-fill: var(--color-warning);        }        &.uptime-down {          --uptime-fill: var(--color-danger);        }        &.uptime-none {          --uptime-fill: var(--color-line-mark);        }      }    }    @media (forced-colors: active) {      forced-color-adjust: none;      &.uptime-degraded, &.uptime-down {        --uptime-fill: Highlight;      }      &.uptime-none {        --uptime-fill: GrayText;      }    }  }}