Skip to the page
TACTILE UI

Kit part · Charts

LED bar chart

A bar chart built like a studio meter bridge: columns of LED segments behind a smoked window, green then amber then red, with a peak segment that lingers and a lit readout for the exact value.

Element
<tui-ledbars>
Needs
kit.css + kit.mjs
Rules
ledbars.rules.md · 5
Finishes
Aluminium · Graphite · Porcelain · Black
Volumes
Tactile · Quiet
On this page
  1. Variants
  2. Every state, at once
  3. API
  4. Markup
  5. Accessibility
  6. How it’s built
  7. Rules
  8. Related parts
01

Variants

Zones · green, amber, red
One colour · no lines
Lying down · long names
Low is bad · alarm under warn
02

Every state, at once

Both finishes, side by side. Hover, pressed and focus are forced with .is-hover, .is-down and .is-focus; checked and disabled are real.

Aluminium

PartRest · shows the highestHover a columnFocus a columnPeak heldOff the scaleNo reading
Columns

Graphite

PartRest · shows the highestHover a columnFocus a columnPeak heldOff the scaleNo reading
Columns
03

API

NameKindValuesWhat it does
<tui-ledbars>elementbuilds its own insideThe chart: a printed title, a lit readout, the scale, the smoked window with one column per reading, and the names.
values · labelsattributecomma-separatedThe readings and their names, in column order. Changing values animates; changing labels sets new columns.
labelattributerequiredPrinted as the title and the name of the group: “Requests per minute”.
min · maxattribute0 · 100The scale. Values past it pin the bar at the end and say so in words.
warn · alarmattributenumbers in the scale’s unitsWhere the segments turn amber and red, and the wedges on the scale. Alarm under warn means low is bad (a battery, a budget).
lampattribute"green" · "amber" · "red" · "blue" · "white"The one colour when there is no warn or alarm.
segmentsattribute4–60 · autoSegments per bar. Auto picks 16–25 so each is a round amount: 0–2,000 in twenty of 100.
peakattributeboolean · "hold"A peak segment that lingers 1.2 s at the last top, then falls; "hold" keeps it until resetPeaks() (the busiest minute of the hour).
unit · unit-textattribute"req/min" · "requests per minute"The unit on the readout, and as it is read out.
decimalsattributeauto from the rangeDecimals on the readout and in the words.
orientattribute"vertical" · "horizontal" · "auto"Columns stand up or lie down. Auto lies them down when the names do not fit under their columns.
label-everyattributeautoPrint every nth name: 3 for the hours of a day. Auto thins the names only as much as they need.
activeattributecolumn indexWith .is-hover or .is-focus, the column those forced states show.
--tui-ledbars-led · --tui-ledbars-gapCSS property5px · 2pxA segment’s length and the gap between segments: the chart’s height is segments × (led + gap).
--tui-ledbars-thick · --tui-ledbars-colgapCSS property10px · autoA lying bar’s width; the space between columns (auto: 30% of a channel, 2–6px).
.setData(values, labels?, { instant })methodnumbers or { label, value }New readings. Numbers keep the columns; pairs set new ones. instant skips the ballistics.
.resetPeaks()method—Drop every held peak back to its bar.
.data · .activepropertyarray · indexThe readings; the column the readout shows.
data-stateattribute"running" · "asleep"Written by the part: running only while a column moves.
Tabkeyboardone stopEnters the chart on the last column you were on, the first at the start.
← → · ↑ ↓ · Home · Endkeyboardcolumn to columnMove between columns; the readout shows the one with focus.
Point · touchpointernearest columnThe readout shows the column under the pointer or finger; leaving puts back the focused or the highest.
.is-hover · .is-focusclasson <tui-ledbars>, with activeForced states, for documentation and specimens only.
04

Markup

<tui-ledbars label="Requests per minute" unit="req/min" unit-text="requests per minute"
    min="0" max="2000" warn="1500" alarm="1800" peak
    labels="api,auth,search,billing,queue,cdn,mail,db"
    values="1284,1920,1610,420,880,1130,260,740"></tui-ledbars>

<!-- 24 hours, one colour, every third hour printed -->
<tui-ledbars label="kWh per hour · today" unit="kWh" min="0" max="4"
    label-every="3" labels="00,01,02,…,23" values="0.42,0.38,…"></tui-ledbars>
import '/kit/kit.mjs';   // defines <tui-ledbars>

const bars = document.querySelector('tui-ledbars');

// Same columns, new readings: they move with a meter's ballistics.
setInterval(async () => {
  const perService = await fetch('/metrics/rpm').then((r) => r.json());   // { api: 1302, auth: 1710, … }
  bars.setData(Object.values(perService));
}, 5000);

// New columns: pass { label, value } pairs.
bars.setData(steps.map((s) => ({ label: s.name, value: s.tokens })));

Needs kit.css and kit.mjs. How to install the kit.

05

Accessibility

  • The chart is a role="group" named by its label and described by one generated sentence: how many bars, the range, the highest and lowest, and who is over each line.
  • Every column is a role="meter" named by its label, with aria-valuenow, min, max and an aria-valuetext in words: “1,920 requests per minute, over the alarm line at 1,800”. They update with the data; browse through them to read the whole chart.
  • One tab stop, then the arrow keys, Home and End. Focus is a 2px ring drawn in light on the glass, where an ink ring would vanish.
  • Colour is never alone: the scale prints a wedge at each line, the readout prints the value, and the words say which line it is past.
  • Reduced motion: the bars jump to the new readings; the peak segment keeps showing the last reading’s top until the next, without falling.
06

How it’s built

A custom element that writes plain DOM: every segment is an <i> with its zone colour set once, and a frame only toggles is-on on the segments that changed. The lit layer is a pseudo-element with a hot centre and a glow in the segment’s own colour; unlit, the colour shows at 15% through the smoke. The window is the kit’s display glass with its glare fixed over the columns. Ballistics are two time constants (60 ms up, 420 ms down) and the peak holds 1.2 s then falls at 55% of the scale a second. The loop runs only while a column moves: it sleeps when every bar is on its reading, pauses off screen and in a hidden tab, and clamps a frame to 1/30 s. Names are measured on a canvas once per width, so thinning them costs no layout.

07

Rules

ledbars.rules.mdIn the brain

The window shows the shape; the readout and the words carry the numbers. Set the warning and alarm lines where the job says, not where they look good.

5 rules in this file, with the foundations they rest on and the anti-patterns that break them. Full rules ship in the brain with the Pass.

08

Ladder

An LED ladder for levels and load: green, then amber, then red, the way a recording level has always been read.

03600:0012:0024:00

Plot

Line charts drawn as light on glass, or as ink on a panel: gridlines faint, two traces at most, a red line for now.

Latency p95182ms

Readout

A printed label over a value: key figures, with the unit small and the change in words.

Docs
Finish
Volume