Gauge
JSA gauge shows how far a task has gone as a square frame with a number in the middle and a caption in the open bottom. Use a spin when you don’t know the percent yet and the mark sits next to a label. Use progress for a linear bar.
Give the host an id and hand it the reading:
<k-gauge id="upload" class="k-gauge"></k-gauge>document.getElementById('upload').options = { value: 64, max: 100, label: 'Upload', format: '%',};The element writes a hidden <progress>, the frame, the reading, and the caption, and every repaint reuses the nodes it already made. Setting options also writes the modifier classes for variant, size, and indeterminate, so the tag reflects what you asked for. The fill eases when the value changes, and reduced motion drops the motion.
The reading follows value through format: leave it out for a plain number, pass % for a percent, or pass any other string ($, €, …) as a currency prefix. Change value and the dial text updates with it. Reach for text only when you need a one-off string format cannot write, like 12.4k. No value is an empty gauge, not a loading state. Pass indeterminate when you want the motion.
Classes
Section titled “Classes”| Class | Type | Description |
|---|---|---|
k-gauge | component | The one class you write. The element generates the progress, frame, reading, and caption inside it. |
Generated classes
| Class | Type | Description |
|---|---|---|
k-gauge--sm | modifier | Small dial. Written from options.size. |
k-gauge--lg | modifier | Large dial. Written from options.size. |
k-gauge--info | modifier | Fill color. Also success, warning, and danger. Written from options.variant. |
k-gauge--indeterminate | modifier | Busy sweep. Written from options.indeterminate. |
k-gauge__frame | part | The square chrome around the reading. Decorative, aria-hidden. |
k-gauge__seg | part | One side of the frame. Combined with a track or fill layer and a side. |
k-gauge__seg--track | modifier | The empty track layer. |
k-gauge__seg--fill | modifier | The filled layer. Length follows --k-gauge. |
k-gauge__seg--left | modifier | The left side of the frame. |
k-gauge__seg--top | modifier | The top side of the frame. |
k-gauge__seg--right | modifier | The right side of the frame. |
k-gauge__value | part | The reading in the middle of the dial. |
k-gauge__label | part | Caption in the open bottom. Hidden when empty. |
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
value | number | — | How far along. Clamped to 0…max. Leave it out for an empty gauge. |
max | number | 1 | The top of the range. |
label | string | — | Caption in the open bottom. Also labels the hidden progress. |
format | string | — | How to write the dial reading from value. Omit for a number. Pass "%" for a percent. Pass any other string ("$", "€", …) as a currency prefix. |
text | string | — | Override the dial reading. Use when format is not enough. Leave it out to let format drive the dial. |
variant | info | success | warning | danger | — | Fill color. Leave it out for the primary orange chrome. |
size | sm | lg | — | Dial size. Leave it out for the default. |
indeterminate | boolean | — | Busy sweep. Ignores value while set. |
Properties
Section titled “Properties”Every option above is also a property, so el.value = 80 works on its own and leaves the rest of the options alone. Three more are computed:
| Property | Type | Description |
|---|---|---|
percent | number | Read-only. Share of max the gauge shows, 0 to 100. An empty gauge reads 0. |
isEmpty | boolean | Read-only. True when there is no value. |
isComplete | boolean | Read-only. True once value reaches max. |
Methods
Section titled “Methods”| Method | Returns | Description |
|---|---|---|
increment(by) | void | Raises value by one step, or by the amount given, stopping at max. Starts from 0 when empty. |
decrement(by) | void | Lowers value the same way, stopping at 0. |
complete() | void | Fills the gauge to max. |
clear() | void | Drops value so the gauge renders empty again. |
getProgress() | HTMLProgressElement | null | The hidden progress element the gauge keeps in step. |
refresh() | void | Rewrites the progress, reading, and caption from the current options. |
Two imported helpers cover the setup cases:
| Helper | Returns | Description |
|---|---|---|
setGauge(el, value, max) | void | Sets value and max in one call. The reading follows format. max defaults to the current max; omit value to empty the gauge. |
createGauge(options) | KGauge | Builds a k-gauge element from an options object, ready to append. |
Unlike the other five elements, the gauge binds no listeners, so it has no disconnect(). Its methods also work on a gauge from createGauge() before it is appended, since it paints on demand rather than on connect.
import { createGauge, setGauge } from 'k-web-ui/js';
const gauge = createGauge({ value: 64, max: 100, label: 'Upload', format: '%',});document.body.append(gauge);setGauge(gauge, 80, 100);Examples
Section titled “Examples”The element writes the number and the caption. --k-gauge is how far the fill has gone along the three sides.
<k-gauge id="upload" class="k-gauge"></k-gauge>import 'k-web-ui/js';
document.getElementById('upload').options = {value: 64,max: 100,label: 'Upload',format: '%',};import { Component, CUSTOM_ELEMENTS_SCHEMA, type AfterViewInit } from '@angular/core';import 'k-web-ui/js';
@Component({ selector: 'app-example', standalone: true, schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <k-gauge id="upload" class="k-gauge"></k-gauge> `,})export class ExampleComponent implements AfterViewInit { ngAfterViewInit() { document.getElementById('upload').options = { value: 64, max: 100, label: 'Upload', format: '%', }; }}import { useEffect } from 'react';import 'k-web-ui/js';
export function Example() { useEffect(() => { document.getElementById('upload').options = { value: 64, max: 100, label: 'Upload', format: '%', }; }, []);
return ( <> <k-gauge id="upload" className="k-gauge"></k-gauge> </> );}Formats
Section titled “Formats”Leave format out for a number. Pass % for a percent. Pass any other string as a currency prefix. text is still there when you need a one-off like 12.4k.
<k-gauge id="open" class="k-gauge"></k-gauge><k-gauge id="balance" class="k-gauge"></k-gauge><k-gauge id="upload-pct" class="k-gauge"></k-gauge><k-gauge id="bandwidth" class="k-gauge"></k-gauge>import 'k-web-ui/js';
document.getElementById('open').options = {value: 8,max: 100,label: 'Open',};document.getElementById('balance').options = {value: 2450,max: 3000,variant: 'success',label: 'Balance',format: '$',};document.getElementById('upload-pct').options = {value: 64,max: 100,variant: 'info',label: 'Upload',format: '%',};document.getElementById('bandwidth').options = {value: 12400,max: 20000,variant: 'info',label: 'Bandwidth',text: '12.4k',};import { Component, CUSTOM_ELEMENTS_SCHEMA, type AfterViewInit } from '@angular/core';import 'k-web-ui/js';
@Component({ selector: 'app-example', standalone: true, schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <k-gauge id="open" class="k-gauge"></k-gauge> <k-gauge id="balance" class="k-gauge"></k-gauge> <k-gauge id="upload-pct" class="k-gauge"></k-gauge> <k-gauge id="bandwidth" class="k-gauge"></k-gauge> `,})export class ExampleComponent implements AfterViewInit { ngAfterViewInit() { document.getElementById('open').options = { value: 8, max: 100, label: 'Open', }; document.getElementById('balance').options = { value: 2450, max: 3000, variant: 'success', label: 'Balance', format: '$', }; document.getElementById('upload-pct').options = { value: 64, max: 100, variant: 'info', label: 'Upload', format: '%', }; document.getElementById('bandwidth').options = { value: 12400, max: 20000, variant: 'info', label: 'Bandwidth', text: '12.4k', }; }}import { useEffect } from 'react';import 'k-web-ui/js';
export function Example() { useEffect(() => { document.getElementById('open').options = { value: 8, max: 100, label: 'Open', }; document.getElementById('balance').options = { value: 2450, max: 3000, variant: 'success', label: 'Balance', format: '$', }; document.getElementById('upload-pct').options = { value: 64, max: 100, variant: 'info', label: 'Upload', format: '%', }; document.getElementById('bandwidth').options = { value: 12400, max: 20000, variant: 'info', label: 'Bandwidth', text: '12.4k', }; }, []);
return ( <> <k-gauge id="open" className="k-gauge"></k-gauge> <k-gauge id="balance" className="k-gauge"></k-gauge> <k-gauge id="upload-pct" className="k-gauge"></k-gauge> <k-gauge id="bandwidth" className="k-gauge"></k-gauge> </> );}Empty and indeterminate
Section titled “Empty and indeterminate”No value is an empty track. indeterminate is the busy sweep. prefers-reduced-motion: reduce stops the motion.
<k-gauge id="waiting" class="k-gauge"></k-gauge><k-gauge id="syncing" class="k-gauge"></k-gauge>import 'k-web-ui/js';
document.getElementById('waiting').options = { max: 100, label: 'Waiting' };document.getElementById('syncing').options = {max: 100,label: 'Syncing',indeterminate: true,};import { Component, CUSTOM_ELEMENTS_SCHEMA, type AfterViewInit } from '@angular/core';import 'k-web-ui/js';
@Component({ selector: 'app-example', standalone: true, schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <k-gauge id="waiting" class="k-gauge"></k-gauge> <k-gauge id="syncing" class="k-gauge"></k-gauge> `,})export class ExampleComponent implements AfterViewInit { ngAfterViewInit() { document.getElementById('waiting').options = { max: 100, label: 'Waiting' }; document.getElementById('syncing').options = { max: 100, label: 'Syncing', indeterminate: true, }; }}import { useEffect } from 'react';import 'k-web-ui/js';
export function Example() { useEffect(() => { document.getElementById('waiting').options = { max: 100, label: 'Waiting' }; document.getElementById('syncing').options = { max: 100, label: 'Syncing', indeterminate: true, }; }, []);
return ( <> <k-gauge id="waiting" className="k-gauge"></k-gauge> <k-gauge id="syncing" className="k-gauge"></k-gauge> </> );}Accessibility
Section titled “Accessibility”The element points aria-labelledby at the caption it writes, which is why the host needs an id. The reading is aria-hidden so the number is not read twice. The hidden <progress> is already a progressbar. Don’t add role="progressbar". prefers-reduced-motion: reduce stops the sweep.
Dos and don’ts
Section titled “Dos and don’ts”Do
- Give the host a unique
id. The generated ids derive from it. - Set
formatso the reading followsvalue. Usetextonly for one-offs. - Use
setGauge()when the value changes often.
Don’t