Vize

Meter

Accessible, unstyled native Meter primitive.

Package @vizejs/ui/meter
Maturity stable
Own the source vize lib pull meter
Requires id
Aliases gauge, usage meter, storage meter, threshold meter
Covers HTML meter element, WAI-ARIA meter role, React Aria Meter

Minimal setup

Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).

vp install @vizejs/ui

Add the public import below to <script setup lang="ts">. Components provide behavior without styles; the preview uses optional Paper styles.

import { Meter } from "@vizejs/ui/meter";

Or copy the source into your project with vize lib pull meter (see Source Distribution).

Try it

This is the basic example maintained with the component source, using the public package imports. The preview adds the optional Paper styles.

Open the interactive example · Styling these components

Copy the example

<!-- Storage usage meter labelled by visible text, with low and high thresholds and fallback text. -->
<script setup lang="ts">
import { useId } from "vue";

import { Meter } from "@vizejs/ui/meter";

const labelId = useId();
const usedGb = 42;
</script>

<template>
  <div>
    <span :id="labelId">Storage used</span>
    <Meter
      v-slot="{ percent }"
      :aria-labelledby="labelId"
      :value="usedGb"
      :min="0"
      :max="50"
      :low="25"
      :high="40"
      :optimum="10"
    >
      {{ percent }}% used
    </Meter>
    <span>{{ usedGb }} GB of 50 GB</span>
  </div>
</template>

API

Meter

Source: src/families/feedback/meter/meter.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned meter id. null and undefined select a deterministic fallback.
value number | null 0 Current value. Non-finite values are repaired to the normalized minimum.
min number 0 Lower bound.
max number 1 Upper bound. Values less than or equal to min are repaired to min + 1. If that addition rounds back to min, the collapsed finite range reports zero percent and invalid state.
low number | null null Optional low threshold.
high number | null null Optional high threshold.
optimum number | null null Optional optimum threshold.
ariaLabel string undefined Accessible name when no visible label or aria-labelledby supplies one.
ariaLabelledby string undefined Space-separated ids that label the meter.
ariaDescribedby string undefined Space-separated ids that describe the meter.

Slots

Slot Slot props Description
default MeterSlotState Optional fallback contents. Receives normalized Meter state for composition.

Exposed

Member Type Description
value number Current finite value clamped to the normalized min/max range.
min number Finite lower bound.
max number Finite upper bound. Equals min only when a repaired min + 1 rounds back to min; that collapsed range reports zero percent and invalid state.
low number | null Optional low threshold clamped to the normalized range.
high number | null Optional high threshold clamped to the normalized range.
optimum number | null Optional optimum threshold clamped to the normalized range.
percent number Completion percentage from 0 to 100.
range MeterRange Current threshold range.
optimal boolean Whether the current range contains the optimum threshold.
invalid boolean Whether raw inputs had to be repaired before reaching the native element.
state MeterState Stable state token for styling and tests.
element HTMLMeterElement | null Rendered native meter element.

Behavior

Normative state x input -> outcome table for meter.vue (@vizejs/ui/meter). Every row is proven by the named mounted-DOM, SSR, or compile-time test.

Surface Contract
Element Meter renders a native <meter> with deterministic id, optional ARIA labelling, and no custom focus behavior.
Range Values clamp to finite bounds; invalid max repairs to min + 1, with the precision exception below.
Thresholds Optional low, high, and optimum thresholds are clamped into range; reversed low/high input is sorted.
State Slot/expose/data state publishes value, bounds, thresholds, percent, range, optimum match, invalid repair, and token.
Styling No component CSS is emitted beyond a scoped empty block; data-vize-ui, part, and data-* are the contract.
SSR Server output is deterministic and contains only native meter attributes, data attributes, and slot text.
Packaging Root and subpath consumers retain only Meter plus shared deterministic-id support with zero CSS.
State x input Outcome
finite value inside thresholds Native <meter> receives the same numeric attributes and publishes data-range plus normalized percent.
optimum threshold in range data-optimal="true" and state="optimum" when the current value is in the same threshold range.
value below min or above max Value is clamped to the native range and invalid is reported for styling and diagnostics.
non-finite or reversed inputs Unsafe inputs are repaired before reaching the native element and data-invalid="true" is published.
omitted thresholds Threshold attributes are omitted while range state falls back to medium, except empty and full.

Percentages remain finite even when two valid finite bounds have a difference larger than Number.MAX_VALUE. The original attributes and thresholds remain unchanged; a signed range from -Number.MAX_VALUE to Number.MAX_VALUE has a midpoint of 50% and an upper endpoint of 100%. Only the overflowing percentage calculation scales both differences by one half.

When min + 1 rounds back to min, Meter preserves the authored scale rather than substituting unrelated bounds. Native <meter> permits equal bounds; this narrow normalization case publishes percent=0, invalid=true, and state="empty". Ordinary equal bounds such as min=2, max=2 still repair to 2..3.

The pure range tests in meter-state.test.ts, the mounted prop-update test in meter.test.ts, and isolated requests in meter-ssr.test.ts cover these cases. The meter-wide-range and meter-collapsed-range runtime fixtures also check native-generated SSR, Vapor mount, and hydration through the existing conformance gate. Existing bundle and tree-shaking budgets remain unchanged.