Skip to content

[FEATURE]: Add ProgressBar component to Basic Catalog #1992

Description

@minhphu102003
  • I have searched the existing issues to make sure this feature has not already been requested.

Is your feature request related to a problem? Please describe.

I'm always frustrated when I need to display task progress, loading states, or completion percentages in agent-generated UIs, but the A2UI Basic Catalog has no dedicated component for it.

Currently there are two workarounds, both inadequate:

Workaround 1: Misusing Slider as a progress bar

The official spec example itself sets this pattern — 06_music-player.json uses {"component": "Slider", "id": "progress"} bound to {path: "/progress"}. The eval prompts (eval/src/prompts.ts lines 138, 331) further train agents to use "Slider named 'Progress'".

A Slider is an interactive input (role="slider", two-way binding, user-draggable). Using it as a read-only display is semantically incorrect:

  • Screen readers announce it as "slider" not "progress bar"
  • Users can accidentally drag it, changing the data model
  • No support for indeterminate (unknown duration) loading states
  • No percentage text overlay — the agent must add a separate Text component

Workaround 2: Plain Text

Examples like 23_step-counter.json show progress as raw text: "84% of 10,000 goal". This completely lacks visual affordance.

Describe the Proposed Solution

Add a ProgressBar component to the Basic Catalog (both v0.9.1 and v1.0).

Properties:

Property Type Required Default Description
value DynamicNumber yes Current progress value (data-bound)
max number no 100 Maximum value (static range)
label DynamicString no Text description (e.g. "Downloading...")
variant "determinate" | "indeterminate" no "determinate" determinate = proportional fill; indeterminate = animated marquee
showPercentage boolean no true Show "45%" text overlay

Key differences from Slider:

  • Read-only (no user interaction, no two-way binding)
  • Indeterminate mode for unknown-duration loading
  • Built-in percentage display
  • ARIA role="progressbar" (not role="slider")
  • No min property (always starts at 0)
  • No checks / validation

Example usages:

// Determinate — 3/5 modules complete
{
  "id": "course_progress",
  "component": "ProgressBar",
  "value": 3,
  "max": 5,
  "label": "Module 3/5"
}

// Indeterminate — processing
{
  "id": "loading",
  "component": "ProgressBar",
  "variant": "indeterminate",
  "label": "Analyzing data..."
}

// Data-bound
{
  "id": "upload_progress",
  "component": "ProgressBar",
  "value": { "path": "/upload/percent" },
  "label": { "path": "/upload/fileName" }
}

Describe Alternatives Considered

  1. Keep using Slider — Rejected because Slider is an input component with fundamentally different semantics (interactive, two-way binding, no indeterminate mode).
  2. Keep using Text with formatString — Rejected because it lacks visual progress indication and forces percentage computation onto every agent.
  3. Add a readOnly property to Slider — Rejected because it would complicate the Slider schema and still lack indeterminate mode, built-in percentage display, and correct ARIA role.
  4. Implement only in custom catalogs (community-managed) — This is what a2ui-oat (discussion a2ui-oat: Framework-free web renderer with 37 components (v0.9) #1033) and a2ui-vue have already done. However, this means every renderer re-implements the same component in isolation. A first-class component in the Basic Catalog would benefit all A2UI users.

Additional Context

Protocol version: v0.9.1 (active), v1.0 (candidate)

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: needs-triageauto-managed: https://github.com/a2ui-project/a2ui/blob/main/scripts/triage.mjs

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions