78 UI Kit
Components

Badges & tags

Five small pieces for labeling things. Badges carry status (and a status line explains one), tags carry user-supplied keywords, score pills carry a number on a good/medium/bad scale, and the eyebrow is a section label.

Badges

_78-badge plus a tone: _78-badge-{tone}, where the tone is one of the six the whole kit uses. The semantic tones mean what they always mean, so a danger badge is a problem in every theme — they do not follow your accent.

Default Accent Active Pending Failed Info Draft
badges
<span class="_78-badge">Default</span>
<span class="_78-badge _78-badge-accent">Accent</span>
<span class="_78-badge _78-badge-success">Active</span>
<span class="_78-badge _78-badge-warn">Pending</span>
<span class="_78-badge _78-badge-danger">Failed</span>
<span class="_78-badge _78-badge-info">Info</span>
<span class="_78-badge _78-badge-dim">Draft</span>
Changed in 0.3.0
Badges used to be -green and -red where alerts were -success and -danger, and the wrong one failed silently. Every tone name now works on every component, and the old names (green, red, plus amber and yellow for warn) keep working for good. The docs use the canonical names.

Dot badges

_78-badge-dot adds a small filled circle before the text, in the badge's own color. It reads as a live status rather than a category.

Live Degraded Down
dot badges
<span class="_78-badge _78-badge-success _78-badge-dot">Live</span>
<span class="_78-badge _78-badge-warn _78-badge-dot">Degraded</span>
<span class="_78-badge _78-badge-danger _78-badge-dot">Down</span>

Category badges

For a label that names a kind of thing rather than a state — a source, a team, a type — use a category, _78-badge-cat-1 to _78-badge-cat-6. Their hues are kept clear of success, warn and danger, so “Scout” never reads as a caution. Use them in order. New in 0.3.0

AI You Watch list Scout Re-entry Manual
category badges
<span class="_78-badge _78-badge-cat-1">AI</span>
<span class="_78-badge _78-badge-cat-2">You</span>
<span class="_78-badge _78-badge-cat-3">Watch list</span>
<span class="_78-badge _78-badge-cat-4">Scout</span>
<span class="_78-badge _78-badge-cat-5">Re-entry</span>
<span class="_78-badge _78-badge-cat-6">Manual</span>

The same six work on tags (_78-tag-cat-*), text (_78-text-cat-*) and the data-viz primitives (_78-tone-cat-*). See Tones.

Status line

A badge on its own says what; _78-status adds the dim sentence that says so what — "Market: caution", then "half risk until the index reclaims its 50-day". The badge stays whole, and the caption takes the rest of the line. When less than about 14em is left, as on a phone, the caption drops to a line of its own instead of squeezing into a narrow column beside the badge.

Market: caution half risk on new entries until the index reclaims its 50-day average
Market: normal full size
Not checked yet the check runs after the close
_78-status
<div class="site-demo-block">
  <div class="_78-status">
    <span class="_78-badge _78-badge-warn">Market: caution</span>
    <span class="_78-status-text">half risk on new entries until the index reclaims its 50-day average</span>
  </div>
  <div class="_78-status">
    <span class="_78-badge _78-badge-success _78-badge-dot">Market: normal</span>
    <span class="_78-status-text">full size</span>
  </div>
  <div class="_78-status">
    <span class="_78-badge _78-badge-dim">Not checked yet</span>
    <span class="_78-status-text">the check runs after the close</span>
  </div>
</div>

Inside a sentence or a toolbar, _78-status-inline makes it an inline element and keeps the caption only as wide as its text:

Sync on last run 2 min ago

_78-status-inline
<p>
  Sync
  <span class="_78-status _78-status-inline">
    <span class="_78-badge _78-badge-success">on</span>
    <span class="_78-status-text">last run 2 min ago</span>
  </span>
</p>
ClassWhat it does
_78-statusA wrapping flex row, baseline-aligned: --space-2 between the badge and the caption, --space-1 between lines.
_78-status-textThe caption: --fs-sm, --dim. Fills the line; drops below the badge when the line is too short.
_78-status-inlineInline, with a caption only as wide as its text.

Any badge tone works, and so does a _78-tag. Put the explanation in the caption rather than only in a title — a tooltip doesn't exist on a phone.

Tags

_78-tag is the pill for user-supplied keywords. _78-tag-accent highlights one, and any other tone works the same way (_78-tag-success, _78-tag-danger …). A removable tag carries a <button> — styled either by being a plain button inside the tag, or explicitly with _78-tag-x when you need a different element or a more specific hook.

design onboarding starred shipped blocked needs-review q4 ×
tags
<span class="_78-tag">design</span>
<span class="_78-tag">onboarding</span>
<span class="_78-tag _78-tag-accent">starred</span>
<span class="_78-tag _78-tag-success">shipped</span>
<span class="_78-tag _78-tag-danger">blocked</span>
<span class="_78-tag">needs-review <button type="button" aria-label="Remove needs-review">&times;</button></span>
<span class="_78-tag">q4 <span class="_78-tag-x" role="button" tabindex="0" aria-label="Remove q4">&times;</span></span>
Always give the remove control its own aria-label naming the tag. A page of buttons all called “×” is unusable by keyboard or screen reader. A real <button> is preferable to _78-tag-x on a span — it is focusable and clickable for free.

Score pills

_78-score-pill shows a number on a three-step scale. The tone is yours to assign, since only you know which way is good — the class does not read the number.

92 61 18 n/a
score pills
<span class="_78-score-pill _78-high">92</span>
<span class="_78-score-pill _78-mid">61</span>
<span class="_78-score-pill _78-low">18</span>
<span class="_78-score-pill">n/a</span>
ClassColor
_78-high--success on --success-lo
_78-mid--warn on --warn-lo
_78-low--danger on --danger-lo
noneNeutral — for “no score yet”

Eyebrow

_78-eyebrow is the small uppercase label above a heading or section. It is inline by default — put it on a div, or add _78-mb-8, when you want it on its own line. Inside a _78-card-title it becomes a block automatically.

Billing Current plan

Team, billed annually.

eyebrow in a card title
<div class="_78-card">
  <div class="_78-card-title">
    <span class="_78-eyebrow">Billing</span>
    Current plan
  </div>
  <p style="margin:0">Team, billed annually.</p>
</div>