Status Monitor

System status

Checkout API is slower than usual. We’re investigating.

  • Storefront

    Operational

    Last 30 days: 100% uptimeNo incidents

  • Checkout API

    Degraded performance

    Last 30 days: 99.82% uptime2 incidents

  • Payments

    Operational

    Last 30 days: 99.95% uptime1 incident

  • Webhooks

    Operational

    Last 30 days: 100% uptimeNo incidents

Updated
@use 'sprucecss/scss/spruce' as *;

.status-monitor {
  --status-monitor-operational: #{color('success', 'alert')};
  --status-monitor-degraded: #{color('warning', 'alert')};
  --status-monitor-outage: #{color('danger', 'alert')};
  background-color: color('surface');
  border: config('border-width-base', $display) solid color('border');
  border-radius: radius('lg');
  padding: spacer('m');
  @include layout-stack('m');

  &__header {
    @include layout-stack('s');
  }

  &__title {
    font-size: font-size('h5');
    margin: 0;
  }

  &__overall {
    align-items: center;
    background-color: color-alpha('success', 0.12, 'alert');
    border-radius: radius('md');
    color: color('heading');
    display: flex;
    font-weight: 600;
    gap: spacer('xs');
    padding: spacer('xs') spacer('s');

    svg {
      block-size: 1.25rem;
      flex-shrink: 0;
      inline-size: 1.25rem;
    }

    &--degraded {
      background-color: color-alpha('warning', 0.2, 'alert');
    }

    &--outage {
      background-color: color-alpha('danger', 0.15, 'alert');
    }
  }

  &__services {
    display: grid;
    // The parent's layout-stack sets the margins.
    list-style: none;
    padding: 0;

    // The items sit side by side: clear the stack margins of the base list style.
    > li {
      margin-block: 0;
    }
  }

  &__service {
    border-block-start: config('border-width-base', $display) solid color('border');
    padding-block: spacer('s');
    @include layout-stack('xs');
  }

  &__row {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: spacer('xxs') spacer('s');
    justify-content: space-between;
  }

  &__name {
    font-family: inherit;
    font-size: config('font-size-base', $typography);
    margin: 0;
  }

  &__status {
    align-items: center;
    display: inline-flex;
    font-size: config('font-size-sm', $typography);
    font-weight: 600;
    gap: spacer('xxs');

    &::before {
      aspect-ratio: 1;
      background-color: var(--status-monitor-operational);
      border-radius: 50%;
      content: '';
      inline-size: 0.5rem;
    }

    &--degraded::before {
      background-color: var(--status-monitor-degraded);
    }

    &--outage::before {
      background-color: var(--status-monitor-outage);
    }
  }

  &__bars {
    block-size: 2rem;
    display: grid;
    gap: 2px;
    grid-auto-columns: minmax(0, 1fr);
    grid-auto-flow: column;
    list-style: none;
    padding: 0;

    li {
      background-color: var(--status-monitor-operational);
      border-radius: 2px;
      margin: 0;
      @include transition($property: 'opacity');

      &:hover {
        opacity: 0.7;
      }
    }

    [data-status='degraded'] {
      background-color: var(--status-monitor-degraded);
    }

    [data-status='outage'] {
      background-color: var(--status-monitor-outage);
    }

    // The items sit side by side: clear the stack margins of the base list style.
    > li {
      margin-block: 0;
      padding-block: 0;
    }
  }

  &__summary,
  &__footer {
    color: color('muted');
    display: flex;
    font-size: config('font-size-sm', $typography);
    gap: spacer('s');
    justify-content: space-between;
  }

  &__footer {
    border-block-start: config('border-width-base', $display) solid color('border');
    font-size: 0.75rem;
    padding-block-start: spacer('s');
  }
}
<section class="status-monitor" aria-labelledby="status-monitor-title">
    <header class="status-monitor__header">
        <h3 class="status-monitor__title" id="status-monitor-title">System status</h3>
        <p class="status-monitor__overall status-monitor__overall--degraded" role="status">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>
            Checkout API is slower than usual. We’re investigating.
        </p>
    </header>
    <ul class="status-monitor__services" role="list">
        <li class="status-monitor__service">
            <div class="status-monitor__row">
                <h4 class="status-monitor__name" id="status-storefront">Storefront</h4>
                <span class="status-monitor__status status-monitor__status--operational">Operational</span>
            </div>
            <ol class="status-monitor__bars" role="list" aria-hidden="true">
                <li data-status="operational" title="Sep 5: No downtime"></li>
                <li data-status="operational" title="Sep 6: No downtime"></li>
                <li data-status="operational" title="Sep 7: No downtime"></li>
                <li data-status="operational" title="Sep 8: No downtime"></li>
                <li data-status="operational" title="Sep 9: No downtime"></li>
                <li data-status="operational" title="Sep 10: No downtime"></li>
                <li data-status="operational" title="Sep 11: No downtime"></li>
                <li data-status="operational" title="Sep 12: No downtime"></li>
                <li data-status="operational" title="Sep 13: No downtime"></li>
                <li data-status="operational" title="Sep 14: No downtime"></li>
                <li data-status="operational" title="Sep 15: No downtime"></li>
                <li data-status="operational" title="Sep 16: No downtime"></li>
                <li data-status="operational" title="Sep 17: No downtime"></li>
                <li data-status="operational" title="Sep 18: No downtime"></li>
                <li data-status="operational" title="Sep 19: No downtime"></li>
                <li data-status="operational" title="Sep 20: No downtime"></li>
                <li data-status="operational" title="Sep 21: No downtime"></li>
                <li data-status="operational" title="Sep 22: No downtime"></li>
                <li data-status="operational" title="Sep 23: No downtime"></li>
                <li data-status="operational" title="Sep 24: No downtime"></li>
                <li data-status="operational" title="Sep 25: No downtime"></li>
                <li data-status="operational" title="Sep 26: No downtime"></li>
                <li data-status="operational" title="Sep 27: No downtime"></li>
                <li data-status="operational" title="Sep 28: No downtime"></li>
                <li data-status="operational" title="Sep 29: No downtime"></li>
                <li data-status="operational" title="Sep 30: No downtime"></li>
                <li data-status="operational" title="Oct 1: No downtime"></li>
                <li data-status="operational" title="Oct 2: No downtime"></li>
                <li data-status="operational" title="Oct 3: No downtime"></li>
                <li data-status="operational" title="Oct 4: No downtime"></li>
            </ol>
            <p class="status-monitor__summary"><span><span class="sr-only">Last 30 days: </span>100% uptime</span><span>No incidents</span></p>
        </li>
        <li class="status-monitor__service">
            <div class="status-monitor__row">
                <h4 class="status-monitor__name" id="status-checkout-api">Checkout API</h4>
                <span class="status-monitor__status status-monitor__status--degraded">Degraded performance</span>
            </div>
            <ol class="status-monitor__bars" role="list" aria-hidden="true">
                <li data-status="operational" title="Sep 5: No downtime"></li>
                <li data-status="operational" title="Sep 6: No downtime"></li>
                <li data-status="operational" title="Sep 7: No downtime"></li>
                <li data-status="operational" title="Sep 8: No downtime"></li>
                <li data-status="operational" title="Sep 9: No downtime"></li>
                <li data-status="operational" title="Sep 10: No downtime"></li>
                <li data-status="operational" title="Sep 11: No downtime"></li>
                <li data-status="operational" title="Sep 12: No downtime"></li>
                <li data-status="operational" title="Sep 13: No downtime"></li>
                <li data-status="degraded" title="Sep 14: Degraded performance"></li>
                <li data-status="operational" title="Sep 15: No downtime"></li>
                <li data-status="operational" title="Sep 16: No downtime"></li>
                <li data-status="operational" title="Sep 17: No downtime"></li>
                <li data-status="operational" title="Sep 18: No downtime"></li>
                <li data-status="operational" title="Sep 19: No downtime"></li>
                <li data-status="operational" title="Sep 20: No downtime"></li>
                <li data-status="operational" title="Sep 21: No downtime"></li>
                <li data-status="operational" title="Sep 22: No downtime"></li>
                <li data-status="operational" title="Sep 23: No downtime"></li>
                <li data-status="operational" title="Sep 24: No downtime"></li>
                <li data-status="operational" title="Sep 25: No downtime"></li>
                <li data-status="operational" title="Sep 26: No downtime"></li>
                <li data-status="operational" title="Sep 27: No downtime"></li>
                <li data-status="operational" title="Sep 28: No downtime"></li>
                <li data-status="operational" title="Sep 29: No downtime"></li>
                <li data-status="operational" title="Sep 30: No downtime"></li>
                <li data-status="operational" title="Oct 1: No downtime"></li>
                <li data-status="operational" title="Oct 2: No downtime"></li>
                <li data-status="operational" title="Oct 3: No downtime"></li>
                <li data-status="degraded" title="Oct 4: Degraded performance"></li>
            </ol>
            <p class="status-monitor__summary"><span><span class="sr-only">Last 30 days: </span>99.82% uptime</span><span>2 incidents</span></p>
        </li>
        <li class="status-monitor__service">
            <div class="status-monitor__row">
                <h4 class="status-monitor__name" id="status-payments">Payments</h4>
                <span class="status-monitor__status status-monitor__status--operational">Operational</span>
            </div>
            <ol class="status-monitor__bars" role="list" aria-hidden="true">
                <li data-status="operational" title="Sep 5: No downtime"></li>
                <li data-status="operational" title="Sep 6: No downtime"></li>
                <li data-status="operational" title="Sep 7: No downtime"></li>
                <li data-status="operational" title="Sep 8: No downtime"></li>
                <li data-status="operational" title="Sep 9: No downtime"></li>
                <li data-status="operational" title="Sep 10: No downtime"></li>
                <li data-status="operational" title="Sep 11: No downtime"></li>
                <li data-status="operational" title="Sep 12: No downtime"></li>
                <li data-status="operational" title="Sep 13: No downtime"></li>
                <li data-status="operational" title="Sep 14: No downtime"></li>
                <li data-status="operational" title="Sep 15: No downtime"></li>
                <li data-status="operational" title="Sep 16: No downtime"></li>
                <li data-status="operational" title="Sep 17: No downtime"></li>
                <li data-status="operational" title="Sep 18: No downtime"></li>
                <li data-status="operational" title="Sep 19: No downtime"></li>
                <li data-status="operational" title="Sep 20: No downtime"></li>
                <li data-status="operational" title="Sep 21: No downtime"></li>
                <li data-status="outage" title="Sep 22: Partial outage"></li>
                <li data-status="operational" title="Sep 23: No downtime"></li>
                <li data-status="operational" title="Sep 24: No downtime"></li>
                <li data-status="operational" title="Sep 25: No downtime"></li>
                <li data-status="operational" title="Sep 26: No downtime"></li>
                <li data-status="operational" title="Sep 27: No downtime"></li>
                <li data-status="operational" title="Sep 28: No downtime"></li>
                <li data-status="operational" title="Sep 29: No downtime"></li>
                <li data-status="operational" title="Sep 30: No downtime"></li>
                <li data-status="operational" title="Oct 1: No downtime"></li>
                <li data-status="operational" title="Oct 2: No downtime"></li>
                <li data-status="operational" title="Oct 3: No downtime"></li>
                <li data-status="operational" title="Oct 4: No downtime"></li>
            </ol>
            <p class="status-monitor__summary"><span><span class="sr-only">Last 30 days: </span>99.95% uptime</span><span>1 incident</span></p>
        </li>
        <li class="status-monitor__service">
            <div class="status-monitor__row">
                <h4 class="status-monitor__name" id="status-webhooks">Webhooks</h4>
                <span class="status-monitor__status status-monitor__status--operational">Operational</span>
            </div>
            <ol class="status-monitor__bars" role="list" aria-hidden="true">
                <li data-status="operational" title="Sep 5: No downtime"></li>
                <li data-status="operational" title="Sep 6: No downtime"></li>
                <li data-status="operational" title="Sep 7: No downtime"></li>
                <li data-status="operational" title="Sep 8: No downtime"></li>
                <li data-status="operational" title="Sep 9: No downtime"></li>
                <li data-status="operational" title="Sep 10: No downtime"></li>
                <li data-status="operational" title="Sep 11: No downtime"></li>
                <li data-status="operational" title="Sep 12: No downtime"></li>
                <li data-status="operational" title="Sep 13: No downtime"></li>
                <li data-status="operational" title="Sep 14: No downtime"></li>
                <li data-status="operational" title="Sep 15: No downtime"></li>
                <li data-status="operational" title="Sep 16: No downtime"></li>
                <li data-status="operational" title="Sep 17: No downtime"></li>
                <li data-status="operational" title="Sep 18: No downtime"></li>
                <li data-status="operational" title="Sep 19: No downtime"></li>
                <li data-status="operational" title="Sep 20: No downtime"></li>
                <li data-status="operational" title="Sep 21: No downtime"></li>
                <li data-status="operational" title="Sep 22: No downtime"></li>
                <li data-status="operational" title="Sep 23: No downtime"></li>
                <li data-status="operational" title="Sep 24: No downtime"></li>
                <li data-status="operational" title="Sep 25: No downtime"></li>
                <li data-status="operational" title="Sep 26: No downtime"></li>
                <li data-status="operational" title="Sep 27: No downtime"></li>
                <li data-status="operational" title="Sep 28: No downtime"></li>
                <li data-status="operational" title="Sep 29: No downtime"></li>
                <li data-status="operational" title="Sep 30: No downtime"></li>
                <li data-status="operational" title="Oct 1: No downtime"></li>
                <li data-status="operational" title="Oct 2: No downtime"></li>
                <li data-status="operational" title="Oct 3: No downtime"></li>
                <li data-status="operational" title="Oct 4: No downtime"></li>
            </ol>
            <p class="status-monitor__summary"><span><span class="sr-only">Last 30 days: </span>100% uptime</span><span>No incidents</span></p>
        </li>
    </ul>
    <footer class="status-monitor__footer">
        <span><span aria-hidden="true">30 days ago</span></span>
        <span>Updated <time datetime="2026-10-04T09:41">2 minutes ago</time></span>
        <span><span aria-hidden="true">Today</span></span>
    </footer>
</section>

Status Monitor

A service status panel with the overall state, the current state of every service and its uptime history for the last 30 days.

Anatomy

  • .status-monitor__overall: the summary banner (--degraded, --outage; operational by default).
  • .status-monitor__service: the name, the __status (--degraded, --outage), the __bars (one li per day with data-status) and the __summary (uptime and incidents).

Accessibility and Usability

  • The state is always written out ("Degraded performance"); the colored dot is decorative.
  • The 30 bars would be 30 extra stops for a screen reader, so the bar list is aria-hidden and the __summary says the same in one sentence ("Last 30 days: 99.82% uptime, 2 incidents"). Link the incidents to their reports in a real status page.
  • The overall banner is a role="status" live region: update its text and screen readers announce the change without moving the focus.
  • Every bar has a title with the date and the state for mouse users.

Technical Details

  • Dependency-free: the bars are a CSS grid with grid-auto-flow: column, so any number of days fills the width.
  • The colors are the --status-monitor-operational, --status-monitor-degraded and --status-monitor-outage custom properties (the success, warning and danger alert colors).
  • Poll your status endpoint and swap the HTML when you need live updates.

Documentation

Learn about Spruce CSS through our extensive documentation.

Components

Explore our UI library of accessible components built with Spruce CSS.

Blocks and Pages

Full-width page blocks and complete page templates, ready to copy.

Find us on GitHub

Did you find a bug? Have an idea or a question? Please open an issue to help us develop the project.