Skip to content

Components / Sections

Status Board

A status page in one section: the state of everything as the heading with its light (it pulses three times, then stays lit), the uptime of the days shown as a Gauge, each service with its state and a bar for every day (up, degraded, an outage, maintenance, no data) rising in turn as the board arrives, and the incidents with their updates, newest first. Pointing at a bar names its day; the days that were not clean are written out for a screen reader under each service, so nothing depends on the bars. A narrow box shows the last thirty days. All of it is data at build. Zero JavaScript.

Live demo

Status

Everything is running

  • Sending API

    Running

    90 days99.98% uptimeToday

    Degraded: 11 Sept

  • Webhooks

    Running

    90 days99.91% uptimeToday

    Degraded: 20 Sept. Outage: 19 Sept

  • DashboardPlanned maintenance is announced a week ahead

    Running

    90 days100.00% uptimeToday

    Maintenance: 25 Aug

Incidents

  1. Webhooks delivered late

    Resolved

    Webhooks

    1. Every queued event has been delivered. We are adding a second queue so this cannot back up again.

    2. Events are being delivered between five and twelve minutes late. Sending is not affected.

Live, from the library itself, at full size: scroll, hover, navigate away and back. The demo is never gated.

Variants · each row writes the attribute the prop writes; the section's own CSS answers

tone
density

Measured

JavaScript of its own

0 B

Uses Reveal and the shared runtime (1.9 kB raw, once per site). With those included: 3.0 kB raw.

CSS 15.8 kB raw including the base tokens. Measured from a production build, and again in CI for every change that can move it.

Browser support

Baseline · widely available

Chrome 105 · Firefox 110 · Safari 16; needs container-units. Elsewhere: without container queries every day's bar shows at any width.

Install Pro

The demo above is never gated; the source is. With a key in components.json (see account), the registry serves it like any other item:

terminal
npx shadcn@latest add @moonarc-pro/status-board
src/pages/index.astro
---
import StatusBoard from '@/components/moonarc/pro/StatusBoard.astro';
import status from '../content/status.json';
---
<StatusBoard
  level={1}
  updated={status.updated}
  updatedText="Updated 9 October 2026, 08:00 UTC"
  services={status.services}
  incidents={status.incidents}
/>

Without a key the registry answers 401 with an upgrade message. Everything this section composes is free: gauge, reveal.

Props

PropTypeDefaultDescription
services{ name; status; uptime; days; note? }[]noneEach service: status now (up, degraded, down, maintenance), uptime in percent over the days shown, and days, one character a day, oldest first and today last: u up, d degraded, o an outage, m maintenance, - no data.
incidents{ title; status; services?; updates: { at; text }[] }[][]The incidents, newest first; status is investigating, identified, monitoring or resolved; at is an ISO date and time.
updatedstringnoneThe day the data was written (YYYY-MM-DD): the last bar is this day. A value that is not a day stops the build.
updatedTextstringnoneHow the update time is printed; unset, the day as given.
eyebrowstringnoneA short line above the heading.
headlinestringnoneThe heading; unset, the words for the overall state ("Everything is running"). Slot "headline" wins.
wordsPartial<Words>noneEvery word the board prints: the overall and per-service states, the incident states, Uptime, days, Today, Incidents, the line for none, and noData for a day with no data.
localestring'en-GB'A BCP 47 locale for the dates.
level1 | 2 | 32Heading level of the heading; the incidents' heading is one below.
tone'surface' | 'muted' | 'ink' | 'brand'unset (paints nothing)The section's ground.
density'compact' | 'cozy' | 'roomy''cozy'Block padding ×0.8 / ×1 / ×1.25 through --ma-density.

Theming and overrides

The section reads the theme contract (shadcn's variable names with the base tokens as fallback), so a pasted theme or one --ma-brand recolours it. Its class names are the override surface and stay stable; a named slot replaces the matching prop with your own markup.

Classes

.ma-in.ma-sr.ma-status.ma-status__affected.ma-status__badge.ma-status__bar.ma-status__bars.ma-status__eyebrow.ma-status__foot.ma-status__gauge.ma-status__head.ma-status__headline.ma-status__ihead.ma-status__incident.ma-status__incidents.ma-status__inner.ma-status__ititle.ma-status__light.ma-status__list.ma-status__meta.ma-status__name.ma-status__note.ma-status__service.ma-status__services.ma-status__state.ma-status__subhead.ma-status__update.ma-status__updated.ma-status__updates.ma-status__uptime.ma-status__words

Slots

slot="eyebrow"slot="headline"

Reduced motion

The bars are there at once, the light stays lit without pulsing and the gauge is drawn full.

With ClientRouter

CSS and Reveal; the bars rise again on a fresh page.

Why it is built this way

Replaces: Hosted status page widgets · Uptime bar sections on developer sites. See the migration table.

A bar chart whose bars grow from the baseline one after another when it scrolls into view; hovering a bar shows its value.

every browserscroll

Gauge

Data

A ring, a three-quarter arc or a half circle that fills to a value as it scrolls into view, the number counting up in the middle with it and a label under it.

newly · Chrome 91 · Firefox 128 · Safari 17scroll

Lists dated releases in a hairline list.

every browserscroll

Where a service runs: the world in dots with each region pinned and pulsing in turn, a chip at each pin with its code and the latency measured there, and under the map the same regions as a list (name, code, figure), so a reader who cannot see the map, or reads on a narrow screen where the chips would crowd, loses nothing.

every browserscrollalways

Also: view transitions · how costs are measured · browser support · accessibility policy · five-minute setup · MCP for agents · this page as Markdown