Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

Progress

Progress indicator as a bar or spinner, with determinate and indeterminate modes. Shows completion state for uploads, installations, and long-running operations.

Components Progress
feedback static
<arc-progress>

Overview

Progress communicates that work is happening and, when possible, how close it is to completion. It is the right component whenever a user triggers an operation whose duration is noticeable — file uploads, data imports, multi-step wizards, or background processing tasks. A clear progress signal reduces perceived wait time and reassures users that the application has not stalled. The component ships in two visual variants. The bar variant fills a horizontal track from left to right, making it ideal for operations where percentage complete is known — file transfers, form completion scores, or quota usage. The spinner variant renders a circular animation suited to compact spaces like buttons, table cells, or inline loading states where a full-width bar would feel out of proportion. Both variants support an indeterminate mode for operations whose total duration is unknown. In indeterminate mode the bar pulses or the spinner loops continuously, signaling activity without committing to a completion estimate. Switch from indeterminate to determinate as soon as the total is known — for example, once the server responds with a Content-Length header during an upload.

Guidelines

When to use

  • Use the bar variant when you can report a numeric percentage (e.g. file uploads, multi-step forms)
  • Switch from indeterminate to determinate as soon as the total work is known
  • Always provide a label prop so screen readers can announce the purpose of the indicator
  • Use the spinner variant inside buttons or inline contexts where a bar would be too wide
  • Pair with descriptive text nearby (e.g. "Uploading project files...") to add context beyond the bar alone
  • Use the sm size for inline or table-cell indicators and lg for full-width page loaders

When not to use

  • Do not show a determinate bar stuck at 0% — use indeterminate until real progress data is available
  • Do not use a spinner when you have percentage data; bars are more informative for known-length tasks
  • Do not omit the label prop — without it the progress indicator is invisible to assistive technology
  • Do not animate progress backwards; if the total changes, reset to indeterminate rather than decreasing the value
  • Do not Stack multiple progress bars in view simultaneously — consolidate into a single indicator or use a stepper
  • Do not use progress for instant actions that complete in under 300ms; a brief delay feels faster without a loader

Features

  • Bar variant with horizontal fill track for determinate completion
  • Spinner variant with circular animation for compact contexts
  • Indeterminate mode for unknown-duration operations
  • Three size presets (sm, md, lg) for different layout contexts
  • Accessible label text announced by screen readers via `aria-label`
  • ARIA progressbar role with `aria-valuenow`, `aria-valuemin`, and `aria-valuemax`
  • Respects `prefers-reduced-motion` by disabling animations
  • Smooth fill transition when value updates for determinate bar

Preview

Usage

<script type="module" src="@arclux/arc-ui"></script>

<div style="display: flex; flex-direction: column; width: 100%; gap: var(--space-lg);">
  <arc-progress value="65" label="Uploading project files..."></arc-progress>
  <arc-progress variant="spinner" indeterminate label="Processing upload"></arc-progress>
</div>
import { Progress } from '@arclux/arc-ui-react';

export function FileUploadStatus() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', width: '100%', gap: 'var(--space-lg)' }}>
      <Progress value={65} label="Uploading project files..." />
      <Progress variant="spinner" indeterminate label="Processing upload" />
    </div>
  );
}
<script setup>
import { Progress } from '@arclux/arc-ui-vue';
</script>

<template>
  <div style="display: flex; flex-direction: column; width: 100%; gap: var(--space-lg);">
    <Progress :value="65" label="Uploading project files..." />
    <Progress variant="spinner" indeterminate label="Processing upload" />
  </div>
</template>
<script>
  import { Progress } from '@arclux/arc-ui-svelte';
</script>

<div style="display: flex; flex-direction: column; width: 100%; gap: var(--space-lg);">
  <Progress value={65} label="Uploading project files..." />
  <Progress variant="spinner" indeterminate label="Processing upload" />
</div>
import { Component } from '@angular/core';
import { Progress } from '@arclux/arc-ui-angular';

@Component({
  imports: [Progress],
  template: `
    <div style="display: flex; flex-direction: column; width: 100%; gap: var(--space-lg);">
      <arc-progress [value]="65" label="Uploading project files..." />
      <arc-progress variant="spinner" indeterminate label="Processing upload" />
    </div>
  `,
})
export class FileUploadStatusComponent {}
import { Progress } from '@arclux/arc-ui-solid';

export function FileUploadStatus() {
  return (
    <div style={{ display: 'flex', 'flex-direction': 'column', width: '100%', gap: 'var(--space-lg)' }}>
      <Progress value={65} label="Uploading project files..." />
      <Progress variant="spinner" indeterminate label="Processing upload" />
    </div>
  );
}
import { Progress } from '@arclux/arc-ui-preact';

export function FileUploadStatus() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', width: '100%', gap: 'var(--space-lg)' }}>
      <Progress value={65} label="Uploading project files..." />
      <Progress variant="spinner" indeterminate label="Processing upload" />
    </div>
  );
}
<!-- Auto-generated by @arclux/prism — do not edit manually -->
<!-- arc-progress — requires progress.css + base.css (or arc-ui.css) -->
<div class="arc-progress">
  <div>
   Label
   <div
   class="progress__spinner"
   role="progressbar"
   aria-valuenow="Indeterminate"
   aria-valuemin="0"
   aria-valuemax="100"
   aria-label="Label"
   >
   <svg viewBox="0 0 44 44">
   <circle class="progress__spinner-track" cx="22" cy="22" r="20"></circle>
   <circle class="progress__spinner-fill" cx="22" cy="22" r="20"></circle>
   </svg>
   </div>
   </div>
</div>
<!-- Auto-generated by @arclux/prism — do not edit manually -->
<!-- arc-progress — self-contained, no external CSS needed -->
<style>
  @media (prefers-reduced-motion: reduce) {
    .arc-progress .progress__fill,
        .arc-progress .progress__spinner svg,
        .arc-progress .progress__spinner-fill { animation: none; }
  }
</style>
<div class="arc-progress" style="display: block">
  <div>
   Label
   <div
   class="progress__spinner" style="display: inline-block"
   role="progressbar"
   aria-valuenow="Indeterminate"
   aria-valuemin="0"
   aria-valuemax="100"
   aria-label="Label"
   >
   <svg viewBox="0 0 44 44">
   <circle style="fill: none; stroke: rgb(24, 24, 30); stroke-width: 3" cx="22" cy="22" r="20"></circle>
   <circle class="progress__spinner-fill" style="fill: none; stroke: rgb(77, 126, 247); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 80, 200; stroke-dashoffset: 0; animation: spinner-dash 1.4s ease-in-out infinite" cx="22" cy="22" r="20"></circle>
   </svg>
   </div>
   </div>
</div>

API

value number 0
Current completion percentage from 0 to 100. Only meaningful in determinate mode. The bar fills proportionally and aria-valuenow updates to match, giving screen readers a live reading.
variant 'bar' | 'spinner' 'bar'
Selects the visual shape. Bar renders a horizontal track with a fill that grows from left to right — best for wide containers and known percentages. Spinner renders a circular indicator suited to compact inline or button contexts.
size 'sm' | 'md' | 'lg' 'md'
Controls the thickness of the bar track or the diameter of the spinner. Small (sm) fits inside table cells and tight layouts. Medium (md) is the standard default. Large (lg) is appropriate for page-level or hero loading states.
indeterminate boolean false
When true, the bar pulses or the spinner loops without a fixed endpoint. Use this when the total work is unknown. Switch to determinate (indeterminate=false) and set a value as soon as real progress data becomes available.
show-value boolean false
Displays the current percentage value next to the label.
label string ''
Accessible label text applied as aria-label on the underlying progressbar role element. This is the only way screen readers can convey the purpose of the indicator. Always provide a meaningful label such as "Uploading report.pdf" rather than a generic "Loading".

See Also