Skip to content

Progress

Reports how far a task has got, whether or not its length is known.

View source View as Markdown

Progress is a readout of how far a task has got, drawn on screen and announced to a screen reader. Useful whenever something takes long enough that the interface has to say so; leave value unset and it reports a task whose length nobody knows yet.

Uploading
x
Preparing
x
App.vue
<template>
  <div class="flex w-64 flex-col gap-5">
    <Progress.Root
      :value="value"
      aria-label="Uploading"
      class="flex flex-col gap-2"
    >
      <div
        class="type-surface-code text-surface-muted flex items-baseline justify-between"
      >
        <span>Uploading</span>
        <Progress.Value class="tabular-nums" />
      </div>

      <Progress.Track :class="track">
        <Progress.Indicator :class="indicator" />
      </Progress.Track>
    </Progress.Root>

    <Progress.Root
      :value="null"
      aria-label="Preparing"
      class="flex flex-col gap-2"
    >
      <span class="type-surface-code text-surface-muted">Preparing</span>

      <Progress.Track :class="track">
        <div class="bg-primary-solid h-full w-1/3 animate-pulse" />
      </Progress.Track>
    </Progress.Root>

    <div class="flex gap-2">
      <Button :class="button" @click="step(-20)">−20</Button>
      <Button :class="button" @click="step(20)">+20</Button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Button } from '@maas/mirror/vue/Button'
import { Progress } from '@maas/mirror/vue/Progress'

const value = ref(40)

function step(amount: number) {
  value.value = Math.min(100, Math.max(0, value.value + amount))
}

const track = 'rounded-component-round bg-surface-higher h-2 overflow-hidden'

const indicator = [
  'h-full w-full! origin-left scale-x-[calc(var(--mpr-percentage,0)*1%)]',
  'bg-primary-solid transition-transform duration-300',
  'data-[state=complete]:bg-success-solid',
].join(' ')

const button = [
  'rounded-component-md border-surface border px-2.5 py-1',
  'type-component-xs text-surface-muted hover:text-surface transition-colors',
].join(' ')
</script>

Usage guidelines

  • A progressbar has no implicit name, so render a Progress.Label, give the root an aria-label, or point aria-labelledby at the element that names it.must
  • The percentage, the formatted string and aria-valuenow all report the clamped value, so a source that overshoots max fills the track and says so. The raw value stays available on the slot and to options.getAriaValueText.may
  • options.format resolves against the runtime locale unless options.locale says otherwise. If the server and the client can differ, pin the locale, or pin the digits with minimumFractionDigits and maximumFractionDigits.should