Skip to content

Meter ​

A meter is a measurement that happens to be somewhere in its range: disk used, budget spent, seats filled. It is not going anywhere — that is what separates it from a ProgressBar, which is a task on its way to finishing. The tell is that a meter has no indeterminate state; a quantity you cannot measure is not a quantity yet.

ts
import { Label, Meter, MeterFill, MeterOutput, MeterTrack } from "ropav";

The parts mirror the bar's: MeterTrack is the groove, MeterFill shows how much of it is taken, MeterOutput prints the value, and a Label says what is being measured.

Storage72%
color
size
template
<Meter class="w-80" :value="72">
  <Label>Storage</Label>
  <MeterOutput />
  <MeterTrack>
    <MeterFill />
  </MeterTrack>
</Meter>

Colour as a threshold ​

A meter is usually read at a glance, so the colour is doing the work: green while there is room, amber when it is getting tight, red when it is not. Derive it from the value rather than writing it per row, so the thresholds live in one place.

Documents34%
Photos71%
System94%
meter-thresholds.vue
vue
<script setup lang="ts">
import { Label, Meter, MeterFill, MeterOutput, MeterTrack } from "ropav";

const disks = [
  { label: "Documents", value: 34 },
  { label: "Photos", value: 71 },
  { label: "System", value: 94 },
] as const;

// The colour is the reading, so it is derived from the value rather than written per row.
const colorFor = (value: number) => (value >= 90 ? "danger" : value >= 70 ? "warning" : "success");
</script>

<template>
  <div class="stack">
    <Meter
      v-for="disk in disks"
      :key="disk.label"
      :color="colorFor(disk.value)"
      :value="disk.value"
    >
      <Label>{{ disk.label }}</Label>
      <MeterOutput />
      <MeterTrack><MeterFill /></MeterTrack>
    </Meter>
  </div>
</template>

<style scoped>
.stack {
  display: flex;
  width: 100%;
  max-width: var(--rp-container-md);
  flex-direction: column;
  gap: calc(var(--rp-spacing) * 6);
}
</style>

Accessibility ​

  • The root is a role="meter", which every current browser and screen reader reads out as a level. It is a single role rather than a meter progressbar fallback list: axe does not read fallback lists, and flagged every aria-value* attribute on one as not allowed.
  • Colour is a threshold and never the message. The output beside the label is what says 94%; the red says it faster to a reader who can see it, and nothing at all to one who cannot.
  • format-options sets how the value reads. A percentage suits a proportion; bytes or a count suit a quantity the reader thinks about in those terms, and value-label replaces the text where neither fits.

API ​

Meter

PropTypeDefaultDescription
ariaDescribedbystring—
ariaLabelstring—
ariaLabelledbystring—
color"default" | "accent" | "success" | "warning" | "danger""accent"Meter color.
formatOptionsIntl.NumberFormatOptions{style: "percent"}Localized number formatting.
idstring—
maxValuenumber100
minValuenumber0
size"xs" | "sm" | "md" | "lg""md"Meter size.
valuenumber0Current quantity.
valueLabelstring—Explicit text announced and rendered for the current value.

The default slot receives:

Slot propType
percentagenumber
valueTextstring | undefined

MeterFill

PropTypeDefaultDescription
stylestring | CSSProperties—

MeterOutput

Slots: default.

MeterTrack

Slots: default.