CSS / SVG · 3.2 KB gzip
Progress Bar
A compact linear indicator with indeterminate flow and smoothly updated determinate progress.
progresslinearinlinedeterminate
Interactive preview
Usage
Packages are @vikast908/core and
@vikast908/loaders. Prefer 0.1.1+
(0.1.0 loaders is broken on npm).
npm install @vikast908/loaders@0.1.1 @vikast908/core@0.1.1
import '@vikast908/loaders/progress-bar'; <orbux-progress-bar state="thinking"></orbux-progress-bar>
Browser-only alternative: Download HTML (self-contained) or load the hosted ESM bundle:
<script type="module" src="http://localhost:4321/orbux/progress-bar.js"></script> <orbux-progress-bar state="thinking"></orbux-progress-bar>
Component source progress-bar.ts
import { OrbuxElement } from '@vikast908/core';
const STYLES = /* css */ `
:host{inline-size:var(--orbux-width,var(--orbux-size,160px));block-size:var(--orbux-height,8px);--_p:0}
.track{position:relative;overflow:hidden;inline-size:100%;block-size:100%;min-block-size:4px;border-radius:999px;background:color-mix(in srgb,var(--orbux-color,#6366f1) 16%,transparent)}
.fill{position:absolute;inset:0;transform-origin:left center;background:var(--orbux-color-progress,var(--orbux-color,#6366f1));transform:scaleX(var(--_p));transition:transform 120ms ease-out;border-radius:inherit}
:host(:not([data-determinate])) .fill{inline-size:42%;transform:translateX(-110%);animation:orbux-bar-flow calc(1.15s * var(--orbux-speed-scale)) ease-in-out infinite}
@keyframes orbux-bar-flow{to{transform:translateX(340%)}}
:host([data-state="streaming"]:not([data-determinate])) .fill{animation-duration:calc(.72s * var(--orbux-speed-scale))}
:host([data-state="tool-calling"]) .track{border-radius:2px;background:repeating-linear-gradient(90deg,color-mix(in srgb,var(--orbux-color,#6366f1) 18%,transparent) 0 10px,transparent 10px 13px)}
:host([data-state="idle"]) .fill{animation-play-state:paused;opacity:.4}
:host([data-state="waiting"]) .fill{animation-play-state:paused;opacity:.75;inline-size:28%}
:host([data-state="done"]) .fill{animation:none;inline-size:100%;transform:none;background:var(--orbux-color-success,#22c55e)}
:host([data-state="error"]) .fill{animation:orbux-bar-error 200ms ease-out 1;inline-size:100%;transform:none;background:var(--orbux-color-error,#ef4444)}
@keyframes orbux-bar-error{35%{translate:-2%}70%{translate:2%}}
:host([data-settled="true"]) .fill{animation:none}
:host([data-paused="true"]) .fill{animation-play-state:paused}
:host([data-reduced-motion="true"]:not([data-determinate])) .fill{animation:none;transform:none;inline-size:var(--_static,38%)}
:host([data-reduced-motion="true"][data-state="streaming"]) {--_static:72%}
:host([data-reduced-motion="true"][data-state="tool-calling"]) {--_static:55%}
:host([data-reduced-motion="true"][data-state="waiting"]) {--_static:24%}
`;
export class OrbuxProgressBar extends OrbuxElement {
protected build(): void {
const style = document.createElement('style');
style.textContent = STYLES;
const track = document.createElement('span');
track.className = 'track';
track.setAttribute('part', 'track');
const fill = document.createElement('span');
fill.className = 'fill';
fill.setAttribute('part', 'fill');
track.append(fill);
this.root.append(style, track);
}
protected onProgressChange(progress: number | null): void {
this.toggleAttribute('data-determinate', progress != null);
this.style.setProperty('--_p', String(progress ?? 0));
}
}
if (typeof customElements !== 'undefined' && !customElements.get('orbux-progress-bar')) {
customElements.define('orbux-progress-bar', OrbuxProgressBar);
}
declare global {
interface HTMLElementTagNameMap {
'orbux-progress-bar': OrbuxProgressBar;
}
}
Depends on @vikast908/core. Paste the source, add the base
element, and set state from your agent code.
Attributes & properties
| Name | Type | Description |
|---|---|---|
state | AgentState | idle · thinking · streaming · tool-calling · waiting · done · error |
progress | number (0 to 1) | Determinate progress from 0 to 1. |
size | CSS length | Overall square size. |
--orbux-width | CSS length | Optional inline-size override. |
--orbux-height | CSS length | Optional block-size override. |
speed | number | Animation speed multiplier (1 = default). |
label | string | Accessible label (defaults per state). |
paused | boolean | Freeze the animation. |
Respects prefers-reduced-motion, exposes
status/progressbar semantics with a live label, and auto-pauses (sets
data-paused) when offscreen or the tab is hidden.