RingProgress

A ring whose arc shows how much of a task is done.

72%
<script setup lang="ts">
  import { RingProgress } from '@hina-ui/vue'
</script>

<template>
  <RingProgress :value="72" show-value />
</template>
vue

Usage

import { RingProgress } from '@hina-ui/vue'
ts

value and max mean the same as in Progress; the arc is drawn clockwise from the top in proportion to the two. The centre is empty by default, and showValue shows the percentage there.

40%
<script setup lang="ts">
  import { Inline, RingProgress } from '@hina-ui/vue'
</script>

<template>
  <Inline gap="lg" align="center">
    <RingProgress :value="40" />
    <RingProgress :value="40" show-value />
  </Inline>
</template>
vue

Examples

Centre content

The default slot replaces the centre content, for example an icon once done, or use format to rewrite the value text.

3/8
<script setup lang="ts">
  import { Check } from '@lucide/vue'
  import { Inline, RingProgress } from '@hina-ui/vue'

  const format = (value: number, max: number) => `${value}/${max}`
</script>

<template>
  <Inline gap="lg" align="center">
    <RingProgress :value="100" tone="success">
      <Check class="text-success size-6" />
    </RingProgress>
    <RingProgress :value="3" :max="8" show-value :format="format" />
  </Inline>
</template>
vue

Label

label sits below the ring.

58%
Read
91%
Bookmarked
<script setup lang="ts">
  import { Inline, RingProgress } from '@hina-ui/vue'
</script>

<template>
  <Inline gap="xl" align="start">
    <RingProgress :value="58" show-value label="Read" />
    <RingProgress :value="91" show-value label="Bookmarked" tone="info" />
  </Inline>
</template>
vue

Changing the value

When value changes the arc length transitions smoothly, whether it grows or shrinks.

30%
<script setup lang="ts">
  import { ref } from 'vue'
  import { Button, Inline, RingProgress, Stack } from '@hina-ui/vue'

  const value = ref(30)
  const step = (delta: number) => {
    value.value = Math.min(100, Math.max(0, value.value + delta))
  }
</script>

<template>
  <Stack gap="md" align="center">
    <RingProgress :value="value" show-value size="lg" />
    <Inline gap="sm">
      <Button size="sm" variant="soft" tone="neutral" :disabled="value === 0" @click="step(-10)">
        −10
      </Button>
      <Button size="sm" variant="soft" tone="neutral" :disabled="value === 100" @click="step(10)">
        +10
      </Button>
    </Inline>
  </Stack>
</template>
vue

Sizes

Three diameters, md by default. The ring thickness and the centre text scale with the diameter.

60%
60%
60%
<script setup lang="ts">
  import { Inline, RingProgress } from '@hina-ui/vue'
</script>

<template>
  <Inline gap="lg" align="center">
    <RingProgress :value="60" size="sm" show-value />
    <RingProgress :value="60" show-value />
    <RingProgress :value="60" size="lg" show-value />
  </Inline>
</template>
vue

Tones

tone sets the arc colour, the accent colour by default.

<script setup lang="ts">
  import { Inline, RingProgress } from '@hina-ui/vue'
</script>

<template>
  <Inline gap="lg" align="center">
    <RingProgress :value="70" />
    <RingProgress :value="70" tone="neutral" />
    <RingProgress :value="100" tone="success" />
    <RingProgress :value="70" tone="warning" />
    <RingProgress :value="70" tone="danger" />
    <RingProgress :value="70" tone="info" />
  </Inline>
</template>
vue

Indeterminate

Leaving out value means the total is unknown: a quarter-length arc spins around the ring.

Connecting
<script setup lang="ts">
  import { RingProgress } from '@hina-ui/vue'
</script>

<template>
  <RingProgress label="Connecting" />
</template>
vue

Behavior

  • The arc is drawn clockwise from the top with round ends; nothing is drawn when value is 0.
  • When value changes the arc length transitions smoothly, with duration and easing from the motion variables; an out-of-range value is clamped.
  • The indeterminate spin runs at the same pace as Spinner. When reduced motion is on the spin stops and the arc stays visible.

Accessibility

  • The ring carries role="progressbar", with aria-valuenow, aria-valuemin and aria-valuemax following value and max; an indeterminate ring has no aria-valuenow.
  • The accessible name is label when given, otherwise the value text, and for an indeterminate ring the locale’s “Loading”.
  • With format the result is also written to aria-valuetext.
  • The drawing itself is hidden from assistive technology; the centre content remains readable.

API

Props

Prop
Type
Default
Description
value
number | null
null
Current progress; leave out for indeterminate
max
number
100
Total
label
string
—
Label below the ring
showValue
boolean
false
Whether to show the value text in the centre
format
(value: number, max: number) => string
percentage
Format of the value text
tone
'accent' | 'neutral' | 'success' | 'warning' | 'danger' | 'info'
'accent'
Arc colour
size
'sm' | 'md' | 'lg'
'md'
Diameter
class
string
—
Extra classes on the root element

Other attributes fall through to the ring element carrying role="progressbar".

Slots

Slot
Description
default
Centre content, the showValue text by default