Skip to content
Updated May 2026Edit this page ↗

Feedback Widgets

Feedback widgets communicate loading state, progress, and user action availability.

All feedback widgets respect caps.motion (disables animations when NO_MOTION=1) and caps.unicode (uses ASCII characters when NO_UNICODE=1).

Spinner

An animated indicator for indeterminate operations:

TYPESCRIPT
import { Spinner } from '@termuijs/widgets'
 
const spin = new Spinner({ height: 1 }, {
    label: 'Connecting to database...',
    color: { type: 'named', name: 'cyan' },
})
spin.mount()   // start animation
// ...later:
spin.unmount() // stop animation

When NO_MOTION=1, the spinner shows a static character instead of animating.

OptionTypeDefaultDescription
labelstringText shown next to the spinner
colorColorwhiteSpinner character color
framesstring[]Unicode brailleCustom animation frames. Falls back to ASCII |/-\ when NO_UNICODE=1.

ProgressBar

A determinate progress bar — use when you know the total:

TYPESCRIPT
import { ProgressBar } from '@termuijs/widgets'
 
const bar = new ProgressBar(
    { height: 1, flexGrow: 1 },
    {
        value: 0.0,
        fillColor: { type: 'named', name: 'green' },
        showLabel: true,
    }
)
 
// Update progress as work completes
bar.setValue(0.42)   // 42%
bar.setValue(1.0)    // done
OptionTypeDefaultDescription
valuenumber0Progress 0.0–1.0
fillColorColorgreenFilled portion color
emptyColorColorbrightBlackEmpty portion color
showLabelbooleantrueShow percentage on the right

Fill characters: / (unicode) → # / . (ASCII when NO_UNICODE=1).

Skeleton

An animated loading placeholder — use while content is loading asynchronously:

TYPESCRIPT
import { Skeleton } from '@termuijs/widgets'
 
const placeholder = new Skeleton({ flexGrow: 1, height: 3 }, {
    variant: 'shimmer',
    intervalMs: 80,
    color: { type: 'named', name: 'brightBlack' },
})

Two variants:

  • 'pulse' — alternates between two brightness levels
  • 'shimmer' — a moving highlight sweeps left to right

When NO_MOTION=1, skeleton renders as a static dimmed block.

OptionTypeDefaultDescription
variant'pulse' \| 'shimmer''shimmer'Animation style
intervalMsnumber100Animation frame interval
colorColorbrightBlackBase skeleton color

MultiProgress

Multiple labeled progress bars in a single widget — useful for parallel downloads, batch operations, or multi-step processes:

TYPESCRIPT
import { MultiProgress } from '@termuijs/widgets'
import type { ProgressItem } from '@termuijs/widgets'
 
const items: ProgressItem[] = [
    { label: 'Downloading assets', value: 0.72, color: { type: 'named', name: 'cyan' } },
    { label: 'Building bundle',    value: 0.31 },
    { label: 'Running tests',      value: 0.0,  color: { type: 'named', name: 'yellow' } },
]
 
const multi = new MultiProgress({ items }, { flexGrow: 1 })
 
// Update individual bars
items[0].value = 0.95
multi.setItems(items)

ProgressItem: { label: string, value: number, color?: Color }

CommandPalette

A searchable, filterable list of commands triggered by keyboard shortcut:

TYPESCRIPT
import { CommandPalette } from '@termuijs/widgets'
import type { Command } from '@termuijs/widgets'
 
const commands: Command[] = [
    { id: 'new',     label: 'New File',        action: () => newFile() },
    { id: 'open',    label: 'Open File...',     action: () => openPicker() },
    { id: 'save',    label: 'Save',             action: () => save() },
    { id: 'search',  label: 'Find in Files',    action: () => openSearch(), description: 'Ctrl+Shift+F' },
    { id: 'theme',   label: 'Change Theme',     action: () => openThemePicker() },
]
 
const palette = new CommandPalette({ commands }, { flexGrow: 1 })

The palette shows a text filter at the top; typing narrows the list. Enter selects the highlighted command.

Command: { id: string, label: string, action: () => void, description?: string }

See also