Skip to content

ProgressCircle ​

A progress circle says exactly what a ProgressBar says, in a frame that has no width to spend: a tile, a table cell, a button. Reach for the bar wherever there is a row to fill, because a bar carries a label and a printed value alongside it and a ring has room for neither.

ts
import {
  ProgressCircle,
  ProgressCircleFillCircle,
  ProgressCircleTrack,
  ProgressCircleTrackCircle,
} from "ropav";

The track is an <svg>: ProgressCircleTrackCircle draws the unfilled ring and ProgressCircleFillCircle draws the arc over it. Both are needed, and in that order — the fill is painted second because it sits on top.

color
size
template
<ProgressCircle aria-label="Uploading" :value="60">
  <ProgressCircleTrack>
    <ProgressCircleTrackCircle />
    <ProgressCircleFillCircle />
  </ProgressCircleTrack>
</ProgressCircle>

When the end is not known ​

is-indeterminate spins the arc instead of sizing it, the same way the bar animates its fill. There is no label beside a circle to carry the wait, so name it with aria-label in both states.

progress-circle-indeterminate.vue
vue
<script setup lang="ts">
import {
  ProgressCircle,
  ProgressCircleFillCircle,
  ProgressCircleTrack,
  ProgressCircleTrackCircle,
} from "ropav";
</script>

<template>
  <ProgressCircle aria-label="Uploading" :value="60">
    <ProgressCircleTrack>
      <ProgressCircleTrackCircle />
      <ProgressCircleFillCircle />
    </ProgressCircleTrack>
  </ProgressCircle>

  <ProgressCircle aria-label="Contacting the server" is-indeterminate>
    <ProgressCircleTrack>
      <ProgressCircleTrackCircle />
      <ProgressCircleFillCircle />
    </ProgressCircleTrack>
  </ProgressCircle>
</template>

An indeterminate circle and a Spinner look alike and are not the same thing: the spinner is the right one where progress will never be measurable, the circle where the number is simply not known yet and will be.

Accessibility ​

  • The circle is a role="progressbar" with the same value attributes as the bar, so what a screen reader hears does not depend on which of the two you drew.
  • The ring is an unnamed <svg> with no text in it, so aria-label is the only name the circle has and it is not optional. A bar can lean on the Label beside it; this cannot.
  • Where the ring sits beside text that already names the wait, point at that text with aria-labelledby rather than repeating it.

API ​

ProgressCircle

PropTypeDefaultDescription
ariaDescribedbystring—
ariaLabelstring—
ariaLabelledbystring—
color"default" | "accent" | "success" | "warning" | "danger""accent"Progress circle color.
formatOptionsIntl.NumberFormatOptions{style: "percent"}Localized number formatting.
idstring—
isIndeterminateboolean—Whether progress is not currently measurable.
maxValuenumber100
minValuenumber0
size"xs" | "sm" | "md" | "lg""md"Progress circle size.
valuenumber0Current progress.
valueLabelstring—Explicit text announced for the current value.

The default slot receives:

Slot propType
isIndeterminateboolean
percentagenumber | undefined
valueTextstring | undefined

ProgressCircleFillCircle

ProgressCircleFillCircle takes nothing but class.

ProgressCircleTrack

Slots: default.

ProgressCircleTrackCircle

ProgressCircleTrackCircle takes nothing but class.