Display glyphs
@ponchia/ui/glyphs is a small, frozen bitmap icon set rendered on the same
.ui-dotmatrix dot primitive as every other dot surface (see
dot surfaces).
CSS-first to the core: a glyph is just a grid of dot cells — . off, # hot,
* accent — so it re-skins with the same --field-dot* tokens and the Tier-3
display knobs as the rest of the dot family. No icon font, no SVG sprite, no
runtime dependency. The module is side-effect-free and SSR-safe (renderGlyph
returns a string; nothing touches the DOM).
import { renderGlyph } from '@ponchia/ui/glyphs';
el.innerHTML = renderGlyph('check', { label: 'Done' });
Load @ponchia/ui/css or the leaf @ponchia/ui/css/dots.css before rendering
glyphs. The cell path uses .ui-dotmatrix, the mask path uses .ui-icon, and
renderReadout() uses .ui-readout.
The authoritative API is the generated, CI-drift-checked glyphs/glyphs.d.ts.
Read it before guessing a name — GlyphName is a literal union, so a typo is a
type error.
Three render paths
A glyph can be drawn three ways; pick by size regime.
| Path | Call | DOM | When |
|---|---|---|---|
| Dot display | renderGlyph(name) |
GLYPH_SIZE² cells (256) |
the signature dot-matrix look at display sizes |
| Solid pixel | renderGlyph(name, { solid: true }) |
256 cells, fused | legible crisp icon at small/inline sizes (~16–24px) |
| Mask icon | renderGlyph(name, { render: 'mask' }) |
one .ui-icon node |
icon-at-scale (e.g. one per table row): inherits currentColor, scales with the text |
The mask path is the lightest — one node instead of 256 — and the right default
for an icon repeated many times. It is single-tone: an accent * cell renders
the same as a hot # cell (both become opaque mask regions).
Pixel-crisp sizes: the bitmap is a 16-unit grid, so the dot/solid paths look sharpest at integer multiples (16/32/48/64px). The mask path scales smoothly with the text; arbitrary
emsizes soften the edges slightly, which is fine for inline use.
renderGlyph(name, options)
| Option | Type | Default | Effect |
|---|---|---|---|
grid |
boolean | true |
show the unlit panel dots; false → glyph-only |
solid |
boolean | false |
square, gapless pixels (implies glyph-only) |
anim |
'reveal' | 'pulse' |
— | decorative animation (reduced-motion-safe) |
label |
string | — | expose as role="img" with this name; omit → decorative (aria-hidden) |
dot |
CSS length | 0.08em |
one dot size (--dotmatrix-dot; sanitized) |
gap |
CSS length | — | gap between dots (--dotmatrix-gap; sanitized) |
render |
'mask' |
— | the one-node .ui-icon path |
size |
CSS length | 1em |
with render: 'mask', the icon size (--icon-size) |
Registry and lower-level helpers
The public registry is intentionally plain data:
GLYPH_SIZEis the grid edge length.GLYPHSis the frozen name → bitmap registry.GLYPH_NAMESis the sorted, frozen name list.glyph(name)returns the raw bitmap rows orundefined.glyphCells(name)returns the 256 row-major cell descriptors.glyphMask(name)returns the CSSurl(...)value used by the mask renderer.
Big numeric readout — renderReadout
Compose digits and punctuation into a row of dot-matrix glyphs — the Nothing-style hero numeric for a KPI, clock, countdown, or percentage.
import { renderReadout } from '@ponchia/ui/glyphs';
el.innerHTML = renderReadout('12:48', { label: '12:48 remaining' });
el.innerHTML = renderReadout('73%', { label: '73 percent of quota', render: 'mask' });
Recognised characters: 0-9, :, ,, ., %, -, +, and space (a blank
advance). Anything else is skipped. Every per-glyph option (solid, render,
dot, gap, anim) passes through to each character; gap sets the spacing
between characters. The digits are decorative — the readout's value is its
accessible name, so pass a label (it defaults to the raw text). Output wraps
in .ui-readout (see dot surfaces).
Finding a glyph — findGlyphs / GLYPH_TAGS
Names follow the "depict, don't name the purpose" convention (trash, not
delete). findGlyphs(query) resolves an intent word to real names by matching
the name OR a curated search alias (GLYPH_TAGS), case-insensitively:
import { findGlyphs } from '@ponchia/ui/glyphs';
findGlyphs('delete'); // → ['trash']
findGlyphs('chart'); // → ['bar-chart']
findGlyphs(''); // → every name
DOM placeholders — initDotGlyph
When you would rather drop a placeholder than inline markup, the optional
initDotGlyph behavior (@ponchia/ui/behaviors) expands
[data-bronto-glyph="name"] in place. It is idempotent and returns a cleanup.
| Attribute | Value | Effect |
|---|---|---|
data-bronto-glyph |
glyph name | expand into a .ui-dotmatrix grid |
data-bronto-glyph-label |
text | expose as role="img"; omit → decorative |
data-bronto-glyph-solid |
— | square, gapless pixel glyph |
data-bronto-glyph-anim |
reveal | pulse |
decorative animation |
data-bronto-glyph-render |
mask |
the one-node .ui-icon path (not 256 cells) |
data-bronto-glyph-size |
CSS length | with render="mask", sets --icon-size |
An unknown name is left untouched.
Accessibility
- A glyph next to a text label is redundant → keep it decorative (
aria-hidden, the default). - An icon-only control labels the control (
aria-labelon the<button>), not the glyph. - A standalone meaningful glyph passes
label→role="img"+aria-label. - A cell-mode glyph is a sea of 256 nodes; the wrapper carries the single
role="img"/aria-hidden, so assistive tech never walks the cells.
Two-tone glyphs
The accent (*) tone lifts one feature of a glyph onto --field-dot-accent.
The curated two-tone set is spark, warning, and info; every other glyph is
monotone. Two-tone only shows in the cell render — the mask path is single-tone.
Related
- Dot surfaces covers the underlying grid and readout styles.
- Usage explains when to use each glyph render path.
- Reference lists the generated dot and icon classes.