78 UI Kit
Components

Tones

Six names, the same on every component that takes a tone — and they are simply the token names. Learn them once and a badge, an alert, a sparkline and a toast all answer to the same word.

The six names

Write the canonical name. The aliases are there so older markup keeps working and so a reasonable guess never fails silently; they style identically and they are permanent.

ToneTokenAliasesUse it for
accent--accent—Your brand color, or a neutral highlight with no good/bad meaning.
success--successgreenDone, healthy, up-is-good.
warn--warnamber, yellowNeeds attention, but nothing is broken.
danger--dangerredFailed, destructive, down-is-bad.
info--info—Neutral information.
dim--dim—De-emphasized. On an alert or a modal it is the plain look, stated.

The semantic tones never follow your accent: danger is red in every theme, because a “themed red that isn't red” is a usability trap.

Every component, every tone

Both themes at once, whatever the page itself is set to. The grid is built from _78.tone.names, the kit's own list, so it can't fall out of step with it.

Where each name goes

ComponentHow you give it a tone
Badge_78-badge-{tone}
Tag_78-tag-{tone}
Text_78-text-{tone}, or the short _78-{tone}
Stat-card number_78-stat-card__num _78-{tone}
Inline alert_78-alert-{tone}
Data-viz (sparkline, progress, bar row, donut, figure, split bar)_78-tone-{tone}, data-tone="{tone}", or tone: '{tone}' in JS
Modal_78.modal.open({ tone }) (also confirm / alert), or _78-modal-{tone} on your own dialog
Toast_78.notify(msg, { type }); 'danger' is the same as the toast's own 'error'

The JavaScript options, live:

Categories

A status tone means something. When a label names a kind of thing instead — where a record came from, which team owns it, what type it is — a status tone lies: a source called “Scout” in warn reads as a caution. Categories are for those labels.

Six hues — violet, teal, rose, olive, orchid, bronze — chosen to sit clear of the semantic hues, so a category never reads as success, warn or danger. Like the semantics they don't follow your accent, and each clears 4.5:1 as badge text on its own tint in both themes.

WhereClass
Badge_78-badge-cat-1 … _78-badge-cat-6
Tag_78-tag-cat-1 … -cat-6
Text_78-text-cat-1 or _78-cat-1 …
Data-viz_78-tone-cat-1 …, or data-tone="cat-1"
Tokens--cat-1 … --cat-6, each with a -lo tint
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>
  • Use them in order. cat-6 (bronze) is the one nearest a state, warn, so a list of five or fewer never reaches it.
  • Alerts, modals and toasts don't take categories — they are about states.
  • The theme generator outputs them on the same fixed hues, fitted per theme for contrast, so a generated theme always has all six.

Aliases

Each pair below is one rule, written two ways. The alias is a selector on the same rule rather than a copy, so the two can never drift.

_78-badge-danger _78-badge-red _78-badge-success _78-badge-green _78-badge-warn _78-badge-amber
_78-text-danger _78-text-red _78-danger _78-red
aliases
<div class="site-demo-block">
  <div class="_78-flex _78-flex-wrap _78-gap-8">
    <span class="_78-badge _78-badge-danger">_78-badge-danger</span>
    <span class="_78-badge _78-badge-red">_78-badge-red</span>
    <span class="_78-badge _78-badge-success">_78-badge-success</span>
    <span class="_78-badge _78-badge-green">_78-badge-green</span>
    <span class="_78-badge _78-badge-warn">_78-badge-warn</span>
    <span class="_78-badge _78-badge-amber">_78-badge-amber</span>
  </div>
  <div class="_78-flex _78-flex-wrap _78-gap-8">
    <span class="_78-text-danger _78-fw-600">_78-text-danger</span>
    <span class="_78-text-red _78-fw-600">_78-text-red</span>
    <span class="_78-danger _78-fw-600">_78-danger</span>
    <span class="_78-red _78-fw-600">_78-red</span>
  </div>
</div>

In JavaScript, _78.tone() turns any tone or alias into its canonical name:

_78.tone
_78.tone('red')      // → 'danger'
_78.tone('Amber')    // → 'warn'
_78.tone('brand')    // → null
_78.tone.names       // → ['accent', 'success', 'warn', 'danger', 'info', 'dim']
_78.tone.aliases     // → { green: 'success', red: 'danger', amber: 'warn', yellow: 'warn' }
New in 0.3.0
Before 0.3.0 the same meaning had different names on different components: danger was -red on a badge and on text, but -danger on an alert and a sparkline, and there was no _78-badge-danger or _78-text-success at all. The wrong name left the element unstyled, with no error. Every name now works everywhere; nothing was removed.

What isn't a tone

  • Button variants. _78-btn-primary, -ghost and -danger describe an action, not a state. There is no success button on purpose.
  • Score-pill bands. _78-high / _78-mid / _78-low are positions on a scale; they happen to use the success, warn and danger colors.
  • The segmented control's _78-seg-accent. A style for the selected segment, not a meaning.