Keyboard shortcut: Ctrl + K
Get started

Meter

VMeter shows a reading within a known range, such as disk usage, a battery level or the strength of a password. Its colour can say whether the reading is good, average or poor.

Usage

vue
Storage
<script setup lang="ts">
import { VMeter } from 'vectis-ui'
</script>

<template>
  <VMeter class="meter" :value="64" label="Storage" />
</template>

<style scoped>
.meter {
  max-inline-size: 20rem;
}
</style>

Examples

Regions

low, high and optimum follow the rules of the native <meter>. The part of the range holding optimum is good and painted in success, the part next to it is average in warning, and the far part is poor in danger. Without any of the three, the meter is in the accent colour.

vue
Humidity
CPU load
Battery
<script setup lang="ts">
import { VMeter } from 'vectis-ui'
</script>

<template>
  <div class="meters">
    <VMeter label="Humidity" :value="45" :low="30" :high="60" />
    <VMeter label="CPU load" :value="55" :low="30" :high="70" :optimum="0" />
    <VMeter label="Battery" :value="12" :low="20" :high="50" :optimum="100" />
  </div>
</template>

<style scoped>
.meters {
  display: grid;
  gap: var(--vectis-space-5);
  max-inline-size: 20rem;
}
</style>

Tones

tone fixes the colour whatever the region. color takes a colour of your own, and the track is derived from it.

vue
Accent
Neutral
Danger
Purple
<script setup lang="ts">
import { VMeter } from 'vectis-ui'
</script>

<template>
  <div class="meters">
    <VMeter label="Accent" :value="60" tone="accent" />
    <VMeter label="Neutral" :value="60" tone="neutral" />
    <VMeter label="Danger" :value="60" tone="danger" />
    <VMeter label="Purple" :value="60" color="#7c3aed" />
  </div>
</template>

<style scoped>
.meters {
  display: grid;
  gap: var(--vectis-space-5);
  max-inline-size: 20rem;
}
</style>

Value

The value is a percentage of the range by default. formatOptions formats the value itself for the current locale, and valueText replaces it with your own words. Screen readers read the same text.

vue
Humidity
Temperature
Storage
<script setup lang="ts">
import { VMeter } from 'vectis-ui'
</script>

<template>
  <div class="meters">
    <VMeter label="Humidity" :value="45" />
    <VMeter
      label="Temperature"
      :value="21.5"
      :min="-10"
      :max="40"
      :format-options="{ style: 'unit', unit: 'celsius' }"
    />
    <VMeter label="Storage" :value="7.2" :max="10" value-text="7.2 GB of 10 GB" />
  </div>
</template>

<style scoped>
.meters {
  display: grid;
  gap: var(--vectis-space-5);
  max-inline-size: 20rem;
}
</style>

Segments

segments splits the bar into equal parts. Colour alone does not tell the region apart: say it in valueText when it matters.

vue
Password strength
Battery
<script setup lang="ts">
import { computed, ref } from 'vue'
import { VButton, VMeter } from 'vectis-ui'

const strengths = ['Weak', 'Fair', 'Good', 'Strong']
const strength = ref(2)
const text = computed(() => strengths[strength.value - 1])
</script>

<template>
  <div class="meters">
    <VMeter
      label="Password strength"
      :value="strength"
      :max="4"
      :low="1.5"
      :high="2.5"
      :optimum="4"
      :segments="4"
      :value-text="text"
    />
    <div class="actions">
      <VButton variant="outline" size="sm" :disabled="strength <= 1" @click="strength--">
        Weaker
      </VButton>
      <VButton variant="outline" size="sm" :disabled="strength >= 4" @click="strength++">
        Stronger
      </VButton>
    </div>
    <VMeter label="Battery" :value="70" :low="20" :high="50" :optimum="100" :segments="5" />
  </div>
</template>

<style scoped>
.meters {
  display: grid;
  gap: var(--vectis-space-5);
  max-inline-size: 20rem;
}

.actions {
  display: flex;
  gap: var(--vectis-space-2);
}
</style>

Sizes

size sets the thickness of the bar, 4, 8 or 12 pixels. The meter takes the whole width of its container.

vue
Small
Medium
Large
<script setup lang="ts">
import { VMeter } from 'vectis-ui'
</script>

<template>
  <div class="meters">
    <VMeter size="sm" label="Small" :value="40" />
    <VMeter size="md" label="Medium" :value="40" />
    <VMeter size="lg" label="Large" :value="40" />
  </div>
</template>

<style scoped>
.meters {
  display: grid;
  gap: var(--vectis-space-5);
  max-inline-size: 20rem;
}
</style>

Hidden text

hideLabel and hideValue remove the text above the bar. Screen readers still hear the label and the value.

vue
Quota
<script setup lang="ts">
import { VMeter } from 'vectis-ui'
</script>

<template>
  <VMeter class="meter" label="Quota" :value="30" hide-label hide-value />
</template>

<style scoped>
.meter {
  max-inline-size: 20rem;
}
</style>

API

Props

PropTypeDefault
valuenumber0
Reading, brought back into the range.
minnumber0
Lower bound of the range.
maxnumber100
Upper bound of the range.
lownumbernone
Upper end of the low part of the range.
highnumbernone
Lower end of the high part of the range.
optimumnumbernone
Best value. Its part of the range is good, the next one average and the far one poor.
labelstringnone
What is measured, shown above the bar and naming it. Uses the dictionary by default; ARIA naming attributes take precedence.
hideLabelbooleanfalse
Hides the label visually. Screen readers still read it.
valueTextstringnone
Text replacing the formatted value, on screen and for screen readers.
formatOptionsIntl.NumberFormatOptionsnone
Intl.NumberFormat options formatting the value itself.
hideValuebooleanfalse
Hides the value visually. Screen readers still read it.
toneMeterTone'accent' | 'neutral' | 'success' | 'warning' | 'danger'none
Colour of the fill. Chosen from the region when low, high or optimum is set, accent otherwise.
colorstringnone
Custom CSS colour replacing the tone.
segmentsnumber1
Number of equal parts the bar is split into.
sizeMeterSize'sm' | 'md' | 'lg''md'
Thickness of the bar and size of the text.

CSS variables

TokenValue
--vectis-control-size-meter-thickness-sm0.25rem
--vectis-control-size-meter-thickness-md0.5rem
--vectis-control-size-meter-thickness-lg0.75rem
--vectis-control-size-meter-segment-gap0.125rem