Open demo

CSS code

HTML
<section class="svc-panel" aria-labelledby="svc-title">
  <div class="svc-head"><h2 id="svc-title">Service status</h2><button class="svc-btn" type="button">Refresh</button></div>
  <div class="svc-scroll" role="region" tabindex="0" aria-label="Service status, scrollable">
    <table class="svc" aria-labelledby="svc-title">
      <thead><tr><th scope="col">Service</th><th scope="col">Status</th><th scope="col">Load</th><th scope="col">P95 latency</th><th scope="col"><span class="sr-only">Actions</span></th></tr></thead>
      <tbody>
        <tr><th scope="row">api-gateway<small>eu-central · 12 pods</small></th><td><span class="svc-dot ok">Operational</span></td><td class="svc-load"><span class="svc-bar ok" style="--load:42%" aria-hidden="true"><i></i></span>42%</td><td class="svc-lat">118 ms</td><td><button class="svc-act" type="button" aria-label="Actions for api-gateway">⋯</button></td></tr>
        <tr><th scope="row">auth-service<small>eu-central · 6 pods</small></th><td><span class="svc-dot ok">Operational</span></td><td class="svc-load"><span class="svc-bar ok" style="--load:31%" aria-hidden="true"><i></i></span>31%</td><td class="svc-lat">64 ms</td><td><button class="svc-act" type="button" aria-label="Actions for auth-service">⋯</button></td></tr>
        <tr><th scope="row">search-index<small>us-east · 9 pods</small></th><td><span class="svc-dot warn">Degraded</span></td><td class="svc-load"><span class="svc-bar warn" style="--load:78%" aria-hidden="true"><i></i></span>78%</td><td class="svc-lat">412 ms</td><td><button class="svc-act" type="button" aria-label="Actions for search-index">⋯</button></td></tr>
        <tr><th scope="row">media-transcode<small>us-east · 4 pods</small></th><td><span class="svc-dot err">Down</span></td><td class="svc-load"><span class="svc-bar err" style="--load:96%" aria-hidden="true"><i></i></span>96%</td><td class="svc-lat">—</td><td><button class="svc-act" type="button" aria-label="Actions for media-transcode">⋯</button></td></tr>
        <tr><th scope="row">billing-worker<small>eu-west · 3 pods</small></th><td><span class="svc-dot ok">Operational</span></td><td class="svc-load"><span class="svc-bar ok" style="--load:18%" aria-hidden="true"><i></i></span>18%</td><td class="svc-lat">89 ms</td><td><button class="svc-act" type="button" aria-label="Actions for billing-worker">⋯</button></td></tr>
      </tbody>
    </table>
  </div>
</section>
CSS
/* Dark status table: a panel with a header bar, glowing status dots, load bars and a row action button.
   The table sits in a focusable scroll region so narrow screens scroll it sideways. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.svc-panel{width:100%;max-width:800px;background:#151b24;color:#e6ecf5;border:1px solid #232d3b;border-radius:16px;overflow:hidden}
.svc-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px 22px;border-bottom:1px solid #232d3b}
.svc-head h2{font-size:1rem;font-weight:700;letter-spacing:-.01em;margin:0}
.svc-btn{border:1px solid #2d3a4c;background:#1c2532;color:#dbe4f0;font:inherit;font-size:.82rem;font-weight:600;padding:8px 14px;border-radius:9px;cursor:pointer;transition:background-color .15s}
.svc-btn:hover{background:#243044}
.svc-scroll{position:relative;overflow-x:auto}
.svc-scroll:focus-visible{outline:2px solid #7aa7ff;outline-offset:-2px}
.svc{width:100%;border-collapse:collapse;font-size:.87rem}
.svc th,.svc td{text-align:left}
.svc thead th{font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#7d8aa0;padding:11px 22px;background:#11161e}
.svc tbody th,.svc td{padding:13px 22px;border-top:1px solid #1d2634}
.svc tbody tr{transition:background-color .12s}
.svc tbody tr:hover{background:#1a2230}
.svc tbody th{font-weight:600;color:#f0f4fa;white-space:nowrap}
.svc tbody th small{display:block;font-size:.83em;font-weight:400;color:#8794aa}
.svc-dot{display:inline-flex;align-items:center;gap:7px;font-size:.8rem;font-weight:600;white-space:nowrap}
.svc-dot::before{content:"";width:8px;height:8px;border-radius:50%;background:currentColor;box-shadow:0 0 8px currentColor}
.svc .ok{color:#3fd68f}.svc .warn{color:#eab308}.svc .err{color:#f87171}
.svc-load{white-space:nowrap}
.svc-bar{display:inline-block;width:110px;height:6px;margin-right:8px;vertical-align:middle;background:#232d3b;border-radius:999px;overflow:hidden}
.svc-bar i{display:block;width:var(--load);height:100%;border-radius:999px;background:currentColor}
.svc-lat{font-variant-numeric:tabular-nums;color:#aeb9cc;white-space:nowrap}
.svc-act{border:0;background:none;color:#8794aa;font:inherit;font-size:1.05rem;line-height:1;cursor:pointer;padding:4px 8px;border-radius:7px}
.svc-act:hover{background:#232d3b;color:#e6ecf5}
.svc-btn:focus-visible,.svc-act:focus-visible{outline:2px solid #7aa7ff;outline-offset:2px}
@media (prefers-reduced-motion:reduce){.svc-btn,.svc tbody tr{transition:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<section class="svc-panel w-100" data-bs-theme="dark" aria-labelledby="svc-title">
  <div class="svc-head d-flex align-items-center justify-content-between gap-3"><h2 id="svc-title">Service status</h2><button class="btn" type="button">Refresh</button></div>
  <div class="svc-scroll table-responsive position-relative" role="region" tabindex="0" aria-label="Service status, scrollable">
    <table class="table table-hover table-borderless svc align-middle mb-0" aria-labelledby="svc-title">
      <thead><tr><th scope="col">Service</th><th scope="col">Status</th><th scope="col">Load</th><th scope="col">P95 latency</th><th scope="col"><span class="visually-hidden">Actions</span></th></tr></thead>
      <tbody>
        <tr><th scope="row">api-gateway<small>eu-central · 12 pods</small></th><td><span class="svc-dot ok">Operational</span></td><td class="text-nowrap"><div class="progress d-inline-flex ok" aria-hidden="true"><div class="progress-bar" style="width:42%"></div></div>42%</td><td class="svc-lat text-nowrap">118 ms</td><td><button class="btn svc-act" type="button" aria-label="Actions for api-gateway">⋯</button></td></tr>
        <tr><th scope="row">auth-service<small>eu-central · 6 pods</small></th><td><span class="svc-dot ok">Operational</span></td><td class="text-nowrap"><div class="progress d-inline-flex ok" aria-hidden="true"><div class="progress-bar" style="width:31%"></div></div>31%</td><td class="svc-lat text-nowrap">64 ms</td><td><button class="btn svc-act" type="button" aria-label="Actions for auth-service">⋯</button></td></tr>
        <tr><th scope="row">search-index<small>us-east · 9 pods</small></th><td><span class="svc-dot warn">Degraded</span></td><td class="text-nowrap"><div class="progress d-inline-flex warn" aria-hidden="true"><div class="progress-bar" style="width:78%"></div></div>78%</td><td class="svc-lat text-nowrap">412 ms</td><td><button class="btn svc-act" type="button" aria-label="Actions for search-index">⋯</button></td></tr>
        <tr><th scope="row">media-transcode<small>us-east · 4 pods</small></th><td><span class="svc-dot err">Down</span></td><td class="text-nowrap"><div class="progress d-inline-flex err" aria-hidden="true"><div class="progress-bar" style="width:96%"></div></div>96%</td><td class="svc-lat text-nowrap">—</td><td><button class="btn svc-act" type="button" aria-label="Actions for media-transcode">⋯</button></td></tr>
        <tr><th scope="row">billing-worker<small>eu-west · 3 pods</small></th><td><span class="svc-dot ok">Operational</span></td><td class="text-nowrap"><div class="progress d-inline-flex ok" aria-hidden="true"><div class="progress-bar" style="width:18%"></div></div>18%</td><td class="svc-lat text-nowrap">89 ms</td><td><button class="btn svc-act" type="button" aria-label="Actions for billing-worker">⋯</button></td></tr>
      </tbody>
    </table>
  </div>
</section>
CSS
/* Bootstrap .table-hover in a data-bs-theme="dark" panel, recoloured through --bs-table-* variables.
   Load bars are .progress, the buttons are .btn with their --bs-btn-* variables set. */
.svc-panel{max-width:800px;--bs-body-bg:#151b24;background:#151b24;color:#e6ecf5;border:1px solid #232d3b;border-radius:16px;overflow:hidden}
.svc-head{padding:18px 22px;border-bottom:1px solid #232d3b}
.svc-head h2{font-size:1rem;font-weight:700;letter-spacing:-.01em;line-height:normal;margin:0}
.svc-panel .btn{--bs-btn-font-size:.82rem;--bs-btn-font-weight:600;--bs-btn-line-height:normal;--bs-btn-padding-x:14px;--bs-btn-padding-y:8px;--bs-btn-border-radius:9px;
  --bs-btn-color:#dbe4f0;--bs-btn-bg:#1c2532;--bs-btn-border-color:#2d3a4c;--bs-btn-hover-color:#dbe4f0;--bs-btn-hover-bg:#243044;--bs-btn-hover-border-color:#2d3a4c;
  --bs-btn-active-color:#e6ecf5;--bs-btn-active-bg:#2a374b;--bs-btn-active-border-color:#2d3a4c;--bs-btn-focus-box-shadow:0 0 0 2px #7aa7ff}
.svc-panel .svc-act{--bs-btn-font-size:1.05rem;--bs-btn-line-height:1;--bs-btn-padding-x:8px;--bs-btn-padding-y:4px;--bs-btn-border-radius:7px;
  --bs-btn-color:#8794aa;--bs-btn-bg:transparent;--bs-btn-border-color:transparent;--bs-btn-hover-color:#e6ecf5;--bs-btn-hover-bg:#232d3b;--bs-btn-hover-border-color:transparent}
.svc-scroll:focus-visible{outline:2px solid #7aa7ff;outline-offset:-2px}
.svc{--bs-table-bg:transparent;--bs-table-color:#e6ecf5;--bs-table-border-color:#1d2634;--bs-table-hover-bg:#1a2230;--bs-table-hover-color:#e6ecf5;font-size:.87rem}
.svc>thead>tr>th{--bs-table-bg:#11161e;--bs-table-color:#7d8aa0;font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:11px 22px}
.svc>tbody>tr>*{padding:13px 22px;border-top:1px solid var(--bs-table-border-color)}
.svc tbody th{font-weight:600;white-space:nowrap;--bs-table-color:#f0f4fa;--bs-table-hover-color:#f0f4fa}
.svc tbody th small{display:block;font-size:.83em;font-weight:400;color:#8794aa}
.svc-dot{display:inline-flex;align-items:center;gap:7px;font-size:.8rem;font-weight:600;white-space:nowrap}
.svc-dot::before{content:"";width:8px;height:8px;border-radius:50%;background:currentColor;box-shadow:0 0 8px currentColor}
.svc .ok{color:#3fd68f}.svc .warn{color:#eab308}.svc .err{color:#f87171}
.svc .progress{--bs-progress-height:6px;--bs-progress-bg:#232d3b;--bs-progress-border-radius:999px;width:110px;margin-right:8px;vertical-align:middle}
.svc .progress-bar{border-radius:999px}
.svc .progress.ok{--bs-progress-bar-bg:#3fd68f}.svc .progress.warn{--bs-progress-bar-bg:#eab308}.svc .progress.err{--bs-progress-bar-bg:#f87171}
.svc-lat{font-variant-numeric:tabular-nums;--bs-table-color:#aeb9cc;--bs-table-hover-color:#aeb9cc}
.svc-scroll:focus-visible,.svc-panel .btn:focus-visible{outline:2px solid #7aa7ff}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<section aria-labelledby="svc-title" class="w-full max-w-[800px] overflow-hidden rounded-2xl border border-[#232d3b] bg-[#151b24] text-[#e6ecf5]">
  <div class="flex items-center justify-between gap-3 border-b border-[#232d3b] px-[22px] py-[18px]"><h2 id="svc-title" class="text-base font-bold tracking-[-.01em]">Service status</h2><button type="button" class="cursor-pointer rounded-[9px] border border-[#2d3a4c] bg-[#1c2532] px-3.5 py-2 text-[.82rem] font-semibold text-[#dbe4f0] transition-colors duration-150 hover:bg-[#243044] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#7aa7ff] motion-reduce:transition-none">Refresh</button></div>
  <div role="region" tabindex="0" aria-label="Service status, scrollable" class="relative overflow-x-auto focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#7aa7ff]">
    <table aria-labelledby="svc-title" class="w-full border-collapse text-left text-[.87rem]">
      <thead class="bg-[#11161e] text-[.72rem] font-bold tracking-[.06em] text-[#7d8aa0] uppercase [&_th]:px-[22px] [&_th]:py-[11px]"><tr><th scope="col">Service</th><th scope="col">Status</th><th scope="col">Load</th><th scope="col">P95 latency</th><th scope="col"><span class="sr-only">Actions</span></th></tr></thead>
      <tbody class="[&>tr>*]:border-t [&>tr>*]:border-[#1d2634] [&>tr>*]:px-[22px] [&>tr>*]:py-[13px]">
        <tr class="transition-colors duration-[120ms] hover:bg-[#1a2230] motion-reduce:transition-none"><th scope="row" class="font-semibold whitespace-nowrap text-[#f0f4fa]">api-gateway<small class="block text-[.83em] font-normal text-[#8794aa]">eu-central · 12 pods</small></th><td><span class="inline-flex items-center gap-[7px] text-[.8rem] font-semibold whitespace-nowrap text-[#3fd68f] before:size-2 before:rounded-full before:bg-current before:shadow-[0_0_8px_currentColor] before:content-['']">Operational</span></td><td class="whitespace-nowrap"><span aria-hidden="true" class="mr-2 inline-block h-1.5 w-[110px] overflow-hidden rounded-full bg-[#232d3b] align-middle"><i class="block h-full w-[42%] rounded-full bg-[#3fd68f]"></i></span>42%</td><td class="whitespace-nowrap text-[#aeb9cc] tabular-nums">118 ms</td><td><button type="button" aria-label="Actions for api-gateway" class="cursor-pointer rounded-[7px] px-2 py-1 text-[1.05rem] leading-none text-[#8794aa] hover:bg-[#232d3b] hover:text-[#e6ecf5] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#7aa7ff]">⋯</button></td></tr>
        <tr class="transition-colors duration-[120ms] hover:bg-[#1a2230] motion-reduce:transition-none"><th scope="row" class="font-semibold whitespace-nowrap text-[#f0f4fa]">auth-service<small class="block text-[.83em] font-normal text-[#8794aa]">eu-central · 6 pods</small></th><td><span class="inline-flex items-center gap-[7px] text-[.8rem] font-semibold whitespace-nowrap text-[#3fd68f] before:size-2 before:rounded-full before:bg-current before:shadow-[0_0_8px_currentColor] before:content-['']">Operational</span></td><td class="whitespace-nowrap"><span aria-hidden="true" class="mr-2 inline-block h-1.5 w-[110px] overflow-hidden rounded-full bg-[#232d3b] align-middle"><i class="block h-full w-[31%] rounded-full bg-[#3fd68f]"></i></span>31%</td><td class="whitespace-nowrap text-[#aeb9cc] tabular-nums">64 ms</td><td><button type="button" aria-label="Actions for auth-service" class="cursor-pointer rounded-[7px] px-2 py-1 text-[1.05rem] leading-none text-[#8794aa] hover:bg-[#232d3b] hover:text-[#e6ecf5] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#7aa7ff]">⋯</button></td></tr>
        <tr class="transition-colors duration-[120ms] hover:bg-[#1a2230] motion-reduce:transition-none"><th scope="row" class="font-semibold whitespace-nowrap text-[#f0f4fa]">search-index<small class="block text-[.83em] font-normal text-[#8794aa]">us-east · 9 pods</small></th><td><span class="inline-flex items-center gap-[7px] text-[.8rem] font-semibold whitespace-nowrap text-[#eab308] before:size-2 before:rounded-full before:bg-current before:shadow-[0_0_8px_currentColor] before:content-['']">Degraded</span></td><td class="whitespace-nowrap"><span aria-hidden="true" class="mr-2 inline-block h-1.5 w-[110px] overflow-hidden rounded-full bg-[#232d3b] align-middle"><i class="block h-full w-[78%] rounded-full bg-[#eab308]"></i></span>78%</td><td class="whitespace-nowrap text-[#aeb9cc] tabular-nums">412 ms</td><td><button type="button" aria-label="Actions for search-index" class="cursor-pointer rounded-[7px] px-2 py-1 text-[1.05rem] leading-none text-[#8794aa] hover:bg-[#232d3b] hover:text-[#e6ecf5] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#7aa7ff]">⋯</button></td></tr>
        <tr class="transition-colors duration-[120ms] hover:bg-[#1a2230] motion-reduce:transition-none"><th scope="row" class="font-semibold whitespace-nowrap text-[#f0f4fa]">media-transcode<small class="block text-[.83em] font-normal text-[#8794aa]">us-east · 4 pods</small></th><td><span class="inline-flex items-center gap-[7px] text-[.8rem] font-semibold whitespace-nowrap text-[#f87171] before:size-2 before:rounded-full before:bg-current before:shadow-[0_0_8px_currentColor] before:content-['']">Down</span></td><td class="whitespace-nowrap"><span aria-hidden="true" class="mr-2 inline-block h-1.5 w-[110px] overflow-hidden rounded-full bg-[#232d3b] align-middle"><i class="block h-full w-[96%] rounded-full bg-[#f87171]"></i></span>96%</td><td class="whitespace-nowrap text-[#aeb9cc] tabular-nums">—</td><td><button type="button" aria-label="Actions for media-transcode" class="cursor-pointer rounded-[7px] px-2 py-1 text-[1.05rem] leading-none text-[#8794aa] hover:bg-[#232d3b] hover:text-[#e6ecf5] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#7aa7ff]">⋯</button></td></tr>
        <tr class="transition-colors duration-[120ms] hover:bg-[#1a2230] motion-reduce:transition-none"><th scope="row" class="font-semibold whitespace-nowrap text-[#f0f4fa]">billing-worker<small class="block text-[.83em] font-normal text-[#8794aa]">eu-west · 3 pods</small></th><td><span class="inline-flex items-center gap-[7px] text-[.8rem] font-semibold whitespace-nowrap text-[#3fd68f] before:size-2 before:rounded-full before:bg-current before:shadow-[0_0_8px_currentColor] before:content-['']">Operational</span></td><td class="whitespace-nowrap"><span aria-hidden="true" class="mr-2 inline-block h-1.5 w-[110px] overflow-hidden rounded-full bg-[#232d3b] align-middle"><i class="block h-full w-[18%] rounded-full bg-[#3fd68f]"></i></span>18%</td><td class="whitespace-nowrap text-[#aeb9cc] tabular-nums">89 ms</td><td><button type="button" aria-label="Actions for billing-worker" class="cursor-pointer rounded-[7px] px-2 py-1 text-[1.05rem] leading-none text-[#8794aa] hover:bg-[#232d3b] hover:text-[#e6ecf5] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#7aa7ff]">⋯</button></td></tr>
      </tbody>
    </table>
  </div>
</section>

About this set

A dark admin panel for service health: a header bar with a title and a Refresh button, then a table of services with a glowing status dot, a load bar, a latency figure and a row action button. The dots are a CSS pseudo-element with a box-shadow in the current text colour, so Operational, Degraded and Down only need a class to change colour, and the word is always printed next to the dot so colour is never the only signal. Load bars are decorative and hidden from assistive technology because the percentage is printed beside them. Each row action button is named after its service, for example Actions for api-gateway, and the empty header above that column carries visually hidden text. Use it for infrastructure dashboards, queue monitors or any status list on a dark background. The table sits in a focusable scroll region inside the rounded panel, so on a phone the columns scroll sideways while service names stay on one line. The Bootstrap version runs inside data-bs-theme=”dark” with .table-hover, .progress bars and .btn buttons; the Tailwind version uses before: utilities for the dots.

What’s included

  • Glowing status dots drawn in CSS, always paired with a status word
  • Load bars with the percentage printed beside them
  • Named row action buttons, one per service
  • Dark palette with text contrast of 4.5:1 or more
  • Scrollable table region inside the rounded panel

Accessibility

The panel is a section labelled by its heading and the table uses scope on every header. Row action buttons have aria-labels that name the service, the actions column has a visually hidden header, and the bars are aria-hidden next to their printed value. Buttons and the scroll region show a light blue focus outline, and hover transitions are removed under prefers-reduced-motion.

Customise it

Status colours are the .ok, .warn and .err rules (#3fd68f, #eab308, #f87171) and the panel colours are on .svc-panel. In Bootstrap the table uses --bs-table-* variables and the bars use --bs-progress-bar-bg per state; in Tailwind change the hex values in the text-, bg- and border- utilities.