Meter

Displays a numeric measurement within a range.

Storage Used
x
import * as stylex from "@stylexjs/stylex"
import { Meter, MeterLabel, MeterValue } from "@/components/ui/meter"

const styles = stylex.create({ root: { width: "100%", maxWidth: "20rem" } })

export default function MeterDemo() {
  return (
    <Meter value={24} xstyle={styles.root}>
      <MeterLabel>Storage Used</MeterLabel>
      <MeterValue />
    </Meter>
  )
}

Installation

Install the following dependencies:

pnpm add @base-ui/react @stylexjs/stylex

Set up the token layer and the StyleX compiler. See Installation for state-styles.ts. Install Progress for the shared bar styles.

Copy and paste the following code into your project.

components/ui/meter.tsx
"use client"

import type { CSSProperties } from "react"
import { Meter as MeterPrimitive } from "@base-ui/react/meter"
import type { StyleXStyles } from "@stylexjs/stylex"

import { progressStyles } from "@/components/ui/progress"
import { stateStyles } from "@/lib/state-styles"

const meterStyles = {
  root: progressStyles.root,
  track: progressStyles.track,
  indicator: progressStyles.indicator,
  label: progressStyles.label,
  value: progressStyles.value,
}

type Overrides = { xstyle?: StyleXStyles; className?: string; style?: CSSProperties }

function Meter({
  xstyle,
  className,
  style,
  children,
  ...props
}: Omit<MeterPrimitive.Root.Props, "className" | "style"> & Overrides) {
  return (
    <MeterPrimitive.Root
      data-slot="meter"
      {...props}
      {...stateStyles(() => [meterStyles.root, xstyle], { className, style })}
    >
      {children}
      <MeterTrack>
        <MeterIndicator />
      </MeterTrack>
    </MeterPrimitive.Root>
  )
}

function MeterTrack({
  xstyle,
  className,
  style,
  ...props
}: Omit<MeterPrimitive.Track.Props, "className" | "style"> & Overrides) {
  return (
    <MeterPrimitive.Track
      data-slot="meter-track"
      {...props}
      {...stateStyles(() => [meterStyles.track, xstyle], { className, style })}
    />
  )
}

function MeterIndicator({
  xstyle,
  className,
  style,
  ...props
}: Omit<MeterPrimitive.Indicator.Props, "className" | "style"> & Overrides) {
  return (
    <MeterPrimitive.Indicator
      data-slot="meter-indicator"
      {...props}
      {...stateStyles(() => [meterStyles.indicator, xstyle], { className, style })}
    />
  )
}

function MeterLabel({
  xstyle,
  className,
  style,
  ...props
}: Omit<MeterPrimitive.Label.Props, "className" | "style"> & Overrides) {
  return (
    <MeterPrimitive.Label
      data-slot="meter-label"
      {...props}
      {...stateStyles(() => [meterStyles.label, xstyle], { className, style })}
    />
  )
}

function MeterValue({
  xstyle,
  className,
  style,
  ...props
}: Omit<MeterPrimitive.Value.Props, "className" | "style"> & Overrides) {
  return (
    <MeterPrimitive.Value
      data-slot="meter-value"
      {...props}
      {...stateStyles(() => [meterStyles.value, xstyle], { className, style })}
    />
  )
}

export { Meter, MeterTrack, MeterIndicator, MeterLabel, MeterValue, meterStyles }

Update the import paths to match your project setup.

Usage

import { Meter, MeterLabel, MeterValue } from "@/components/ui/meter"

;<Meter value={24}>
  <MeterLabel>Storage Used</MeterLabel>
  <MeterValue />
</Meter>

Give the meter a MeterLabel or an aria-label to name the measurement.

Anatomy

Meter renders MeterTrack and MeterIndicator after its children.

Meter
├── MeterLabel
├── MeterValue
└── MeterTrack
    └── MeterIndicator

API reference

Each part accepts its Base UI Meter props, including render, plus xstyle, className and real inline style.

Meter

PropTypeDefault
valuenumber—
minnumber0
maxnumber100
formatIntl.NumberFormatOptions—
localeIntl.LocalesArgumentruntime locale
getAriaValueText(formattedValue: string, value: number) => string—

Use format and locale to format the value. value must be a number; use Progress for indeterminate tasks.

MeterValue

PropTypeDefault
children(formattedValue: string, value: number) => ReactNode—

meterStyles

KeyWhat it is
rootWrapping label and value row
trackRounded groove
indicatorFilled bar and reduced-motion-aware width transition
labelLabel type
valueMuted, tabular number aligned to the end

Data attributes

AttributeOnEffect
data-slot="meter"rootTargets the measurement
data-slot="meter-track"trackTargets the groove
data-slot="meter-indicator"indicatorTargets the fill
data-slot="meter-label"labelTargets the label
data-slot="meter-value"valueTargets the number