# Meter

Displays a numeric measurement within a range.

```tsx
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

1. Install the following dependencies:

   ```bash
   npm install @base-ui/react @stylexjs/stylex
   ```

2. Set up the token layer and the StyleX compiler. See
   [Installation](https://carbon.style/docs/installation) for `state-styles.ts`. Install
   [Progress](https://carbon.style/docs/components/progress) for the shared bar styles.

3. Copy and paste the following code into your project.

   ```tsx title="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 }
   ```

4. Update the import paths to match your project setup.

## Usage

```tsx
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.

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

## API reference

Each part accepts its [Base UI Meter props](https://base-ui.com/react/components/meter),
including `render`, plus `xstyle`, `className` and real inline `style`.

### Meter

| Prop               | Type                                                | Default        |
| ------------------ | --------------------------------------------------- | -------------- |
| `value`            | `number`                                            | —              |
| `min`              | `number`                                            | `0`            |
| `max`              | `number`                                            | `100`          |
| `format`           | `Intl.NumberFormatOptions`                          | —              |
| `locale`           | `Intl.LocalesArgument`                              | runtime locale |
| `getAriaValueText` | `(formattedValue: string, value: number) => string` | —              |

Use `format` and `locale` to format the value. `value` must be a number;
use [Progress](https://carbon.style/docs/components/progress) for indeterminate tasks.

### MeterValue

| Prop       | Type                                                   | Default |
| ---------- | ------------------------------------------------------ | ------- |
| `children` | `(formattedValue: string, value: number) => ReactNode` | —       |

### meterStyles

| Key         | What it is                                           |
| ----------- | ---------------------------------------------------- |
| `root`      | Wrapping label and value row                         |
| `track`     | Rounded groove                                       |
| `indicator` | Filled bar and reduced-motion-aware width transition |
| `label`     | Label type                                           |
| `value`     | Muted, tabular number aligned to the end             |

### Data attributes

| Attribute                     | On        | Effect                  |
| ----------------------------- | --------- | ----------------------- |
| `data-slot="meter"`           | root      | Targets the measurement |
| `data-slot="meter-track"`     | track     | Targets the groove      |
| `data-slot="meter-indicator"` | indicator | Targets the fill        |
| `data-slot="meter-label"`     | label     | Targets the label       |
| `data-slot="meter-value"`     | value     | Targets the number      |
