Skip to content

Progress

Experimental Alpha

This library is a work-in-progress. We are releasing it early to gather feedback, but it is not ready for production.

A progress component is used to display the progress of a task. It can show determinate progress (with a specific value) or indeterminate progress (loading state without a known duration).

Examples

Vue
Lit
React
Live Preview

Indeterminate Progress

When no value is provided, the progress bar is indeterminate.

Progress with Value

Set the value prop to a number to show progress.

Progress with Custom Max

Set the max prop to a number to define the maximum value.

CSS Shadow Parts Customization

Use CSS Shadow Parts to customize the component's appearance.

View Vue Code
<template>
  <section>
    <div class="mbe4">
      <h2>Indeterminate Progress</h2>
      <p class="mbs2 mbe3">When no <code>value</code> is provided, the progress bar is indeterminate.</p>
      <VueProgress label="Loading..." />
    </div>
    <div class="mbe4">
      <h2>Progress with Value</h2>
      <p class="mbs2 mbe3">Set the <code>value</code> prop to a number to show progress.</p>
      <VueProgress
        :value="50"
        label="50% complete"
      />
    </div>
    <div class="mbe4">
      <h2>Progress with Custom Max</h2>
      <p class="mbs2 mbe3">Set the <code>max</code> prop to a number to define the maximum value.</p>
      <VueProgress
        :value="150"
        :max="200"
        label="150 of 200"
      />
    </div>
    <div class="mbe4">
      <h2>CSS Shadow Parts Customization</h2>
      <p class="mbs2 mbe3">Use CSS Shadow Parts to customize the component's appearance.</p>
      <VueProgress
        :value="75"
        label="Customized progress"
        class="custom-progress"
      />
    </div>
  </section>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import { VueProgress } from "agnosticui-core/progress/vue";

export default defineComponent({
  name: "ProgressExamples",
  components: {
    VueProgress,
  },
});
</script>

<style>
.custom-progress::part(ag-progress-bar) {
  background-color: var(--ag-purple-100);
  height: 1.5rem;
}

.custom-progress::part(ag-progress-bar)::-webkit-progress-value {
  background-color: var(--ag-purple-500);
}

.custom-progress::part(ag-progress-bar)::-moz-progress-bar {
  background-color: var(--ag-purple-500);
}
</style>
Live Preview
View Lit / Web Component Code
import { LitElement, html } from 'lit';
import 'agnosticui-core/progress';

export class ProgressLitExamples extends LitElement {
  // Render in light DOM to access global utility classes
  createRenderRoot() {
    return this;
  }

  render() {
    return html`
      <section>
        <div class="mbe4">
          <h2>Indeterminate Progress</h2>
          <p class="mbs2 mbe3">When no <code>value</code> is provided, the progress bar is indeterminate.</p>
          <ag-progress label="Loading..."></ag-progress>
        </div>
        <div class="mbe4">
          <h2>Progress with Value</h2>
          <p class="mbs2 mbe3">Set the <code>value</code> prop to a number to show progress.</p>
          <ag-progress
            value="50"
            label="50% complete"
          ></ag-progress>
        </div>
        <div class="mbe4">
          <h2>Progress with Custom Max</h2>
          <p class="mbs2 mbe3">Set the <code>max</code> prop to a number to define the maximum value.</p>
          <ag-progress
            value="150"
            max="200"
            label="150 of 200"
          ></ag-progress>
        </div>
        <div class="mbe4">
          <h2>CSS Shadow Parts Customization</h2>
          <p class="mbs2 mbe3">Use CSS Shadow Parts to customize the component's appearance.</p>
          <ag-progress
            value="75"
            label="Customized progress"
            class="custom-progress"
          ></ag-progress>
        </div>
      </section>

      <style>
        .custom-progress::part(ag-progress-bar) {
          background-color: var(--ag-purple-100);
          height: 1.5rem;
        }

        .custom-progress::part(ag-progress-bar)::-webkit-progress-value {
          background-color: var(--ag-purple-500);
        }

        .custom-progress::part(ag-progress-bar)::-moz-progress-bar {
          background-color: var(--ag-purple-500);
        }
      </style>
    `;
  }
}

// Register the custom element
customElements.define('progress-lit-examples', ProgressLitExamples);

Interactive Preview: Click the "Open in StackBlitz" button below to see this example running live in an interactive playground.

View React Code
import { ReactProgress } from "agnosticui-core/progress/react";

export default function ProgressReactExamples() {
  return (
    <section>
      <div className="mbe4">
        <h2>Indeterminate Progress</h2>
        <p className="mbs2 mbe3">
          When no <code>value</code> is provided, the progress bar is indeterminate.
        </p>
        <ReactProgress label="Loading..." />
      </div>
      <div className="mbe4">
        <h2>Progress with Value</h2>
        <p className="mbs2 mbe3">
          Set the <code>value</code> prop to a number to show progress.
        </p>
        <ReactProgress value={50} label="50% complete" />
      </div>
      <div className="mbe4">
        <h2>Progress with Custom Max</h2>
        <p className="mbs2 mbe3">
          Set the <code>max</code> prop to a number to define the maximum value.
        </p>
        <ReactProgress value={150} max={200} label="150 of 200" />
      </div>
      <div className="mbe4">
        <h2>CSS Shadow Parts Customization</h2>
        <p className="mbs2 mbe3">
          Use CSS Shadow Parts to customize the component's appearance.
        </p>
        <ReactProgress
          value={75}
          label="Customized progress"
          className="custom-progress"
        />
      </div>
    </section>
  );
}
Open in StackBlitz

Usage

TIP

The framework examples below import AgnosticUI as an npm package. Alternatively, you can use the CLI for complete control, AI/LLM visibility, and full code ownership:

bash
npx ag init --framework FRAMEWORK # react, vue, lit, svelte, etc.
npx ag add Progress

The CLI copies source code directly into your project, giving you full visibility and control. After running npx ag add, you'll receive exact import instructions.

Vue
vue
<template>
  <VueProgress :value="50" :max="100" label="Loading..." />
  
  <!-- Indeterminate progress (no value) -->
  <VueProgress label="Processing..." />
  
  <!-- Custom size -->
  <VueProgress :value="75" :max="100" label="Uploading..." size="large" />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { VueProgress } from 'agnosticui-core/Progress/vue/VueProgress';

export default defineComponent({
  components: { VueProgress }
});
</script>
React
tsx
import { ReactProgress } from 'agnosticui-core/Progress/react/ReactProgress';

export default function Example() {
  return (
    <>
      <ReactProgress value={50} max={100} label="Loading..." />
      
      {/* Indeterminate progress (no value) */}
      <ReactProgress label="Processing..." />
      
      {/* Custom size */}
      <ReactProgress value={75} max={100} label="Uploading..." size="large" />
    </>
  );
}
Lit (Web Components)
html
<script type="module">
  import 'agnosticui-core/Progress/core/Progress';
</script>

<!-- Determinate progress -->
<ag-progress value="50" max="100" label="Loading..."></ag-progress>

<!-- Indeterminate progress (no value attribute) -->
<ag-progress label="Processing..."></ag-progress>

<!-- Custom size -->
<ag-progress value="75" max="100" label="Uploading..." size="large"></ag-progress>

Using property binding in Lit templates:

javascript
import { html } from 'lit';
import 'agnosticui-core/Progress/core/Progress';

const template = html`
  <ag-progress .value=${50} .max=${100} .label=${"Loading..."}></ag-progress>
`;

Props

PropTypeDefaultDescription
valuenumber | undefinedundefinedThe current value of the progress bar. If not provided, the progress bar is indeterminate.
maxnumber100The maximum value of the progress bar.
labelstring''An accessible label for the progress bar. This label is visually hidden but announced by screen readers.
size'small' | 'medium' | 'large''medium'Size of the progress bar.

CSS Shadow Parts

PartDescription
ag-progress-wrapperThe main container element for the component
progress-labelThe visually hidden label element
ag-progress-barThe native <progress> element

CSS Custom Properties

The Progress component can be customized using CSS custom properties:

PropertyDescriptionDefault
--ag-progress-widthWidth of the progress bar100%
--ag-progress-heightHeight of the progress barSize-dependent

Customization Example

css
/* Custom width */
ag-progress {
  --ag-progress-width: 300px;
}

/* Custom styling via shadow parts */
ag-progress::part(ag-progress-bar) {
  border-radius: 4px;
}

ag-progress::part(ag-progress-bar)::-webkit-progress-value {
  background: linear-gradient(90deg, #3b82f6, #8b5cf6);
}

ag-progress::part(ag-progress-bar)::-moz-progress-bar {
  background: linear-gradient(90deg, #3b82f6, #8b5cf6);
}

Sizes

The Progress component supports three sizes:

  • small: Compact progress bar (height: var(--ag-space-2))
  • medium (default): Standard progress bar (height: var(--ag-space-3))
  • large: Prominent progress bar (height: var(--ag-space-4))

Determinate vs Indeterminate

Determinate Progress

Shows a specific completion percentage. Use when you know the progress amount:

vue
<VueProgress :value="75" :max="100" label="75% complete" />

Indeterminate Progress

Shows an animated loading state. Use when progress duration is unknown:

vue
<VueProgress label="Loading..." />

The indeterminate state displays an animated gradient that moves across the progress bar.

Accessibility

The Progress component follows WCAG accessibility guidelines:

  • Uses the native HTML5 <progress> element for proper semantics
  • The label prop provides accessible text that is visually hidden but announced by screen readers
  • The <progress> element has aria-label set to the label value
  • Indeterminate state is properly indicated to assistive technologies
  • The component maintains proper ARIA attributes (value, max) for determinate progress

Best Practices

  • Always provide a meaningful label that describes what is progressing
  • For determinate progress, update the value prop as the task progresses
  • Use indeterminate progress when you cannot calculate completion percentage
  • Consider pairing with text to show actual numbers (e.g., "Uploading 5 of 10 files")
  • Ensure adequate color contrast (4.5:1 minimum) for the progress indicator

Browser Support

The Progress component uses the native HTML5 <progress> element with enhanced styling. The indeterminate animation is supported in all modern browsers. Custom styling is applied using browser-specific pseudo-elements:

  • Chrome/Safari/Edge: ::-webkit-progress-bar, ::-webkit-progress-value
  • Firefox: ::-moz-progress-bar

Examples

File Upload Progress

vue
<template>
  <div>
    <VueProgress 
      :value="uploadProgress" 
      :max="100" 
      :label="`Uploading ${fileName}...`" 
    />
    <p>{{ uploadProgress }}% complete</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { VueProgress } from 'agnosticui-core/Progress/vue/VueProgress';

const uploadProgress = ref(0);
const fileName = ref('document.pdf');

// Simulate upload progress
const interval = setInterval(() => {
  uploadProgress.value += 10;
  if (uploadProgress.value >= 100) {
    clearInterval(interval);
  }
}, 500);
</script>

Loading State

vue
<template>
  <div>
    <VueProgress label="Loading content..." />
    <p>Please wait...</p>
  </div>
</template>