Data display
.sb-table
Section titled “.sb-table”A data table in the HUD style: the header is a small uppercase eyebrow, rows are separated by hairlines and numbers align on tabular figures. Use real table markup: <caption>, <th scope> and <tfoot> give assistive technology the structure. Wrap the table in sb-table-wrap so it scrolls sideways on narrow screens instead of widening the page.
| Job | Fixer | District | Reward | Status |
|---|---|---|---|---|
| Ghost in the wire | Dakota | Badlands | 12,400 | Open |
| Static bloom | Regina | Watson | 8,750 | Taken |
| Cold storage | Wakako | Westbrook | 21,000 | Pending |
| Neon requiem | Padre | Heywood | 4,200 | Failed |
| Total | 46,350 | |||
<div class="sb-table-wrap"> <table class="sb-table sb-table-striped sb-table-hover"> <caption>Active jobs on the board. The selected row carries aria-selected.</caption> <thead> <tr> <th scope="col" aria-sort="ascending">Job</th> <th scope="col">Fixer</th> <th scope="col" aria-sort="none">District</th> <th scope="col" class="sb-table-num">Reward</th> <th scope="col" class="sb-table-center">Status</th> </tr> </thead> <tbody> <tr> <th scope="row">Ghost in the wire</th><td>Dakota</td><td>Badlands</td> <td class="sb-table-num">12,400</td> <td class="sb-table-center"><span class="sb-badge sb-badge-success">Open</span></td> </tr> <tr aria-selected="true"> <th scope="row">Static bloom</th><td>Regina</td><td>Watson</td> <td class="sb-table-num">8,750</td> <td class="sb-table-center"><span class="sb-badge sb-badge-info">Taken</span></td> </tr> <tr> <th scope="row">Cold storage</th><td>Wakako</td><td>Westbrook</td> <td class="sb-table-num">21,000</td> <td class="sb-table-center"><span class="sb-badge sb-badge-warning">Pending</span></td> </tr> <tr> <th scope="row">Neon requiem</th><td>Padre</td><td>Heywood</td> <td class="sb-table-num">4,200</td> <td class="sb-table-center"><span class="sb-badge sb-badge-danger">Failed</span></td> </tr> </tbody> <tfoot> <tr><th scope="row" colspan="3">Total</th><td class="sb-table-num">46,350</td><td></td></tr> </tfoot> </table></div>| Class / selector | Effect |
|---|---|
sb-table |
The table. Captions render below the table. |
sb-table-wrap |
Scroll container with a tube border and radius; also scrolls vertically if you give it a height. |
sb-table-striped |
Zebra rows. |
sb-table-hover |
Row highlight on hover. |
sb-table-compact |
Tighter cells. |
sb-table-bordered |
Vertical hairlines between cells. |
sb-table-sticky |
Sticky header cells; the wrap must have a fixed height and overflow: auto. |
sb-table-caption-top |
Moves the caption above the table. |
sb-table-num |
End-aligned numeric cell with tabular figures. sb-num does the same inside a table. |
sb-table-center |
Centered cell. |
th[aria-sort="ascending"], th[aria-sort="descending"] |
Sorted column: highlighted header with an arrow. |
th[aria-sort] |
Marks the header as sortable. |
tbody tr[aria-selected="true"], tbody tr[data-selected] |
Selected row: a tint and an accent mark on the first cell. |
| Accent | Role | Order |
|---|---|---|
| plasma | brand primary | 1 |
| laser | danger | 2 |
| ember | parameters | 3 |
| sodium | warning | 4 |
| halogen | types | 5 |
| acid | success | 6 |
| coolant | operators | 7 |
| frost | properties | 8 |
| Class | Level |
|---|---|
| Netrunner | 50 |
| Solo (data-selected) | 42 |
| Techie | 31 |
<div class="sb-table-wrap" style="height: 11rem; overflow: auto"> <table class="sb-table sb-table-compact sb-table-bordered sb-table-sticky sb-table-caption-top"> <caption>Compact, bordered, with a sticky header</caption> <thead> <tr><th scope="col">Accent</th><th scope="col">Role</th><th scope="col" class="sb-table-num">Order</th></tr> </thead> <tbody> <tr><td>plasma</td><td>brand primary</td><td class="sb-num">1</td></tr> <tr><td>laser</td><td>danger</td><td class="sb-num">2</td></tr> <tr><td>ember</td><td>parameters</td><td class="sb-num">3</td></tr> <tr><td>sodium</td><td>warning</td><td class="sb-num">4</td></tr> <tr><td>halogen</td><td>types</td><td class="sb-num">5</td></tr> <tr><td>acid</td><td>success</td><td class="sb-num">6</td></tr> <tr><td>coolant</td><td>operators</td><td class="sb-num">7</td></tr> <tr><td>frost</td><td>properties</td><td class="sb-num">8</td></tr> </tbody> </table></div><div class="sb-table-wrap"> <table class="sb-table"> <thead> <tr><th scope="col">Class</th><th scope="col" aria-sort="descending">Level</th></tr> </thead> <tbody> <tr><td>Netrunner</td><td>50</td></tr> <tr data-selected><td>Solo (data-selected)</td><td>42</td></tr> <tr><td>Techie</td><td>31</td></tr> </tbody> </table></div>The CSS only styles aria-sort. If the column header is a sort button, put the button inside the <th>, set aria-sort on the <th> and update it from your script.
.sb-kbd
Section titled “.sb-kbd”sb-kbd is a keycap: mono type, a tube border with a 2px bottom edge. Use the real <kbd> element.
<kbd class="sb-kbd">F</kbd><kbd class="sb-kbd">Esc</kbd><kbd class="sb-kbd sb-kbd-sm">sm</kbd><kbd class="sb-kbd sb-kbd-lg">Space</kbd><kbd class="sb-kbd sb-kbd-primary">E</kbd><kbd class="sb-kbd" data-pressed>Shift</kbd><span class="sb-kbd-group"><kbd class="sb-kbd">Ctrl</kbd>+<kbd class="sb-kbd">K</kbd></span>| Class / attribute | Effect |
|---|---|
sb-kbd |
Keycap, 1.5rem tall. |
sb-kbd-sm, sb-kbd-lg |
1.25rem and 2rem keycaps. |
sb-kbd-primary |
Primary ink, border and bloom, for a highlighted or bound key. |
[data-pressed], [aria-pressed="true"] |
Pressed look: primary ink and a key that sinks 1px. Set it from your key handler. |
sb-kbd-group |
Wrapper for a combination such as Ctrl + K. |
.sb-key-hint
Section titled “.sb-key-hint”A key hint is a keycap plus a label: the “[F] Interact” prompt of a HUD. sb-key-hints lays several out in a wrapping row. On a HUD they should sit on a glass strip (the demo uses the sb-glass utility) rather than straight on the game.
<div class="sb-key-hints sb-glass" style="padding: var(--sb-space-2) var(--sb-space-4); border-radius: var(--sb-radius-md)"> <span class="sb-key-hint"><kbd class="sb-kbd">F</kbd><span class="sb-key-hint-label">Interact</span></span> <span class="sb-key-hint" data-active><kbd class="sb-kbd">E</kbd><span class="sb-key-hint-label">Pick up</span></span> <span class="sb-key-hint sb-key-hint-active"><kbd class="sb-kbd">Tab</kbd><span class="sb-key-hint-label">Scanner</span></span> <span class="sb-key-hint" aria-disabled="true"><kbd class="sb-kbd">R</kbd><span class="sb-key-hint-label">Reload</span></span> <span class="sb-key-hint sb-key-hint-disabled"><kbd class="sb-kbd">Q</kbd><span class="sb-key-hint-label">Quickhack</span></span> <span class="sb-key-hint sb-key-hint-sm"><kbd class="sb-kbd sb-kbd-sm">C</kbd><span class="sb-key-hint-label">Crouch</span></span> <span class="sb-key-hint sb-key-hint-lg"><kbd class="sb-kbd sb-kbd-lg">Space</kbd><span class="sb-key-hint-label">Jump</span></span></div><div class="sb-key-hints sb-key-hints-vertical sb-glass" style="padding: var(--sb-space-2) var(--sb-space-4); border-radius: var(--sb-radius-md)"> <span class="sb-key-hint"><kbd class="sb-kbd">1</kbd><span class="sb-key-hint-label">Primary</span></span> <span class="sb-key-hint"><kbd class="sb-kbd">2</kbd><span class="sb-key-hint-label">Secondary</span></span></div>| Class / attribute | Effect |
|---|---|
sb-key-hint |
The prompt row: display type, uppercase. |
sb-key-hint-label |
The action text. |
sb-key-hint-sm, sb-key-hint-lg |
Smaller and larger prompt. |
sb-key-hint-active, [data-active] |
The prompt that is currently available: brighter label and a primary keycap. |
sb-key-hint-disabled, [aria-disabled="true"] |
Dimmed prompt. |
sb-key-hints |
Wrapping row of hints. |
sb-key-hints-vertical |
Column of hints. |
.sb-code and .sb-pre
Section titled “.sb-code and .sb-pre”sb-code is an inline code chip. sb-pre frames a block, either on a <pre> directly or on a <figure> that wraps a header, a <pre> and a caption. Wrap each line in <span class="sb-line"> to enable line numbers and per-line marks. The CSS does not highlight syntax; bring your own highlighter and keep the sb-line spans.
Inline sb-code, sb-code-primary,
sb-code-secondary, sb-code-muted
and sb-code-wrap lets a very long identifier like open77_resource_manifest_version break across lines.
<p> Inline <code class="sb-code">sb-code</code>, <code class="sb-code sb-code-primary">sb-code-primary</code>, <code class="sb-code sb-code-secondary">sb-code-secondary</code>, <code class="sb-code sb-code-muted">sb-code-muted</code> and <code class="sb-code sb-code-wrap">sb-code-wrap lets a very long identifier like open77_resource_manifest_version break across lines</code>.</p>| Class | Effect |
|---|---|
sb-code |
Inline code chip. |
sb-code-primary, sb-code-secondary, sb-code-muted |
Ink variants. |
sb-code-wrap |
Allows a long identifier to wrap. |
resource "static-bloom-hud"
version "1.0.0"
web_ui_page "dist/index.html"
web_files { "dist/**" }
client_script "old.lua"
client_script "client.lua"
pnpm add @static-bloom/css
Packages: +3
pnpm build:css
pre.sb-pre with sb-pre-wrap: a very long line that would otherwise scroll sideways wraps instead, keeping the whole statement visible on narrow viewports.
function focus() {
return 'sb-line-focus dims the other lines'
}
<figure class="sb-pre sb-pre-lines"> <div class="sb-pre-header"> <span class="sb-pre-filename">fxmanifest.lua</span> <span class="sb-pre-lang">lua</span> </div> <pre><code><span class="sb-line">resource "static-bloom-hud"</span><span class="sb-line">version "1.0.0"</span><span class="sb-line sb-line-highlight">web_ui_page "dist/index.html"</span><span class="sb-line">web_files { "dist/**" }</span><span class="sb-line sb-line-del">client_script "old.lua"</span><span class="sb-line sb-line-add">client_script "client.lua"</span></code></pre> <figcaption class="sb-pre-caption">Line numbers come from CSS counters; highlight, add and delete mark lines.</figcaption></figure><figure class="sb-pre sb-pre-terminal sb-pre-sm"> <div class="sb-pre-header"><span class="sb-pre-title">Terminal</span></div> <pre><code><span class="sb-line sb-prompt">pnpm add @static-bloom/css</span><span class="sb-line">Packages: +3</span><span class="sb-line sb-prompt">pnpm build:css</span></code></pre></figure><pre class="sb-pre sb-pre-wrap"><code>pre.sb-pre with sb-pre-wrap: a very long line that would otherwise scroll sideways wraps instead, keeping the whole statement visible on narrow viewports.</code></pre><figure class="sb-pre"> <pre><code><span class="sb-line">function focus() {</span><span class="sb-line sb-line-focus"> return 'sb-line-focus dims the other lines'</span><span class="sb-line">}</span></code></pre></figure>| Class | Effect |
|---|---|
sb-pre |
The block frame (on <pre> or <figure>); scrolls sideways on overflow. |
sb-pre-header |
Title bar of a figure. |
sb-pre-filename, sb-pre-title, sb-pre-lang |
File name, a plain title and the language tag in the header. |
sb-pre-actions |
Right-aligned slot in the header for buttons such as a copy button. |
sb-pre-caption |
Caption under the block (<figcaption>). |
sb-pre-lines |
Adds line numbers (CSS counters on .sb-line). |
sb-pre-terminal |
Terminal styling. |
sb-pre-sm |
Smaller type. |
sb-pre-wrap |
Wraps long lines instead of scrolling. |
sb-line |
One line of code. |
sb-line-highlight |
Highlighted line. |
sb-line-add, sb-line-del |
Added and deleted lines (diff). |
sb-line-focus |
Focused line; the other lines dim. |
sb-prompt |
Marks a command line in a terminal block with a prompt glyph. |
The block is scrollable, so make it reachable from the keyboard: add tabindex="0" and a name to a <pre> that can overflow, unless it sits in a figure you control.
.sb-avatar
Section titled “.sb-avatar”An avatar is a round (or square) user picture with an initials fallback and an optional status dot. Put the <img> first and the fallback after it; the fallback shows when there is no image or it fails to load. Give a meaningful alt to a lone avatar, and alt="" when the name is printed beside it.
<div class="sb-stack"> <div class="sb-cluster"> <span class="sb-avatar sb-avatar-xs"><span class="sb-avatar-fallback">xs</span></span> <span class="sb-avatar sb-avatar-sm"><span class="sb-avatar-fallback">sm</span></span> <span class="sb-avatar sb-avatar-md"><span class="sb-avatar-fallback">md</span></span> <span class="sb-avatar sb-avatar-lg"><span class="sb-avatar-fallback">lg</span></span> <span class="sb-avatar sb-avatar-xl"><span class="sb-avatar-fallback">xl</span></span> <span class="sb-avatar sb-avatar-2xl"><span class="sb-avatar-fallback">2x</span></span> </div> <div class="sb-cluster"> <span class="sb-avatar sb-avatar-square sb-avatar-sm"><span class="sb-avatar-fallback">VS</span></span> <span class="sb-avatar sb-avatar-square"><span class="sb-avatar-fallback">VS</span></span> <span class="sb-avatar sb-avatar-square sb-avatar-lg"><span class="sb-avatar-fallback">VS</span></span> <span class="sb-avatar sb-avatar-lg sb-avatar-ring"><span class="sb-avatar-fallback">GR</span></span> </div> <div class="sb-cluster"> <span class="sb-avatar sb-avatar-lg"><span class="sb-avatar-fallback">JS</span><span class="sb-avatar-status sb-avatar-status-online"></span></span> <span class="sb-avatar sb-avatar-lg"><span class="sb-avatar-fallback">AW</span><span class="sb-avatar-status sb-avatar-status-away"></span></span> <span class="sb-avatar sb-avatar-lg"><span class="sb-avatar-fallback">RA</span><span class="sb-avatar-status sb-avatar-status-busy"></span></span> <span class="sb-avatar sb-avatar-lg"><span class="sb-avatar-fallback">PW</span><span class="sb-avatar-status sb-avatar-status-offline"></span></span> </div> <div class="sb-avatar-group"> <span class="sb-avatar"><span class="sb-avatar-fallback">VS</span></span> <span class="sb-avatar"><span class="sb-avatar-fallback">JS</span></span> <span class="sb-avatar"><span class="sb-avatar-fallback">PW</span></span> <span class="sb-avatar"><span class="sb-avatar-fallback">RA</span></span> <span class="sb-avatar sb-avatar-group-count"><span class="sb-avatar-fallback">+6</span></span> </div></div>With a picture:
<span class="sb-avatar sb-avatar-lg"> <img class="sb-avatar-img" src="/avatars/vs.png" alt="V. Silverhand" /> <span class="sb-avatar-fallback">VS</span> <span class="sb-avatar-status sb-avatar-status-online"></span></span>| Class | Effect |
|---|---|
sb-avatar |
The circle, medium (2.5rem). |
sb-avatar-xs, -sm, -md, -lg, -xl, -2xl |
1.5, 2, 2.5, 3, 4 and 5rem. |
sb-avatar-square |
Rounded square instead of a circle. |
sb-avatar-ring |
Accent ring. |
sb-avatar-img |
The picture, covering the avatar. |
sb-avatar-fallback |
Initials or an icon. |
sb-avatar-status |
Status dot in the corner; combine with a state class. |
sb-avatar-status-online, -away, -busy, -offline |
Status color. The color is not the only cue: also expose the status as text. |
sb-avatar-group |
Overlapping row of avatars with a canvas-colored ring. |
sb-avatar-group-count |
The “+6” overflow avatar in a group. |
.sb-divider
Section titled “.sb-divider”A divider is a hairline. Use <hr> for a plain rule and an element with role="separator" when it carries a label.
<div class="sb-stack"> <hr class="sb-divider" /> <div class="sb-divider" role="separator">Labelled</div> <div class="sb-divider sb-divider-start" role="separator">Start aligned</div> <div class="sb-divider sb-divider-end" role="separator">End aligned</div> <hr class="sb-divider sb-divider-strong" /> <hr class="sb-divider sb-divider-dashed" /> <div class="sb-divider sb-divider-dashed sb-divider-strong" role="separator">Dashed strong</div> <hr class="sb-divider sb-divider-neon" /> <div class="sb-divider sb-divider-neon" role="separator">Neon labelled</div> <hr class="sb-divider sb-divider-tight" /> <hr class="sb-divider sb-divider-loose" /></div>| Class | Effect |
|---|---|
sb-divider |
1px hairline, or a line either side of a centered label. |
sb-divider-start, sb-divider-end |
Aligns the label to the start or the end. |
sb-divider-strong |
Stronger line color. |
sb-divider-dashed |
Dashed line. |
sb-divider-neon |
Plasma-to-ultraviolet gradient tube with a bloom. |
sb-divider-tight, sb-divider-loose |
Less and more space around the rule. |
sb-divider-vertical |
Vertical rule for a flex row. |
<div class="sb-cluster" style="min-height: 4rem; align-items: stretch"> <span>Left</span> <span class="sb-divider sb-divider-vertical"></span> <span>Middle</span> <span class="sb-divider sb-divider-vertical sb-divider-dashed"></span> <span>Dashed</span> <span class="sb-divider sb-divider-vertical sb-divider-neon"></span> <span>Neon</span></div>