Deck
Browse the catalog

Build / Atoms

UsageMeter

  • atom
  • play-fn

Consumption against a plan cap.

Surfacing usage is how MeetCard triggers upgrades at the moment of realised value rather than by withholding features — the Solo connections cap is the primary case.

Renders a real role="meter" with its ARIA value attributes, and states the level in text, so the reading never depends on the bar's color.

import { UsageMeter } from '@meetcard/deck'

Example

<UsageMeter label="Connections" value={92} max={100} footer={<Button size="sm">Upgrade to Pro</Button>} />

Stories

Every preview below is the real component, rendered in this page from the same story Storybook runs. The width control resizes each preview's container; CSS media queries still follow the browser window, so breakpoint behaviour is worth checking in Storybook.

Default
Source
const Default = () => <div style={{ maxWidth: 360 }}>
    <UsageMeter label="Connections" value={42} max={100} />
</div>;

Nearing the Solo cap. Surfacing consumption is how MeetCard triggers an upgrade at the moment of realised value, rather than by withholding.

Approaching Limit
Source
const ApproachingLimit = () => <div style={{ maxWidth: 360 }}>
    <UsageMeter
        label="Connections"
        value={92}
        max={100}
        footer={<Button size="sm">Upgrade to Pro</Button>} />
</div>;

At the limit, with the way past it. Said in words, not only by a full bar.

Limit Reached
Source
const LimitReached = () => <div style={{ maxWidth: 360 }}>
    <UsageMeter
        label="Connections"
        value={100}
        max={100}
        footer={<Button size="sm">Upgrade to Pro</Button>} />
</div>;

Pro and Team are uncapped, so no meter is shown — this is the contrast.

Levels
Source
const Levels = () => <Stack gap={24} style={{ maxWidth: 360 }}>
    <UsageMeter label="Connections" max={100} value={18} />
    <UsageMeter label="Connections" max={100} value={86} />
    <UsageMeter label="Connections" max={100} value={100} />
</Stack>;

Overflow is clamped so the bar never exceeds its track.

Over Limit
Source
const OverLimit = () => <div style={{ maxWidth: 360 }}>
    <UsageMeter label="Connections" value={140} max={100} />
</div>;

Props

PropTypeDefaultDescription
labelrequiredReactNode——
maxrequirednumber——
valuerequirednumber——
footerReactNode—Shown beneath the bar — typically the upgrade nudge.
formatValue(value: number, max: number) => string(v, m) => `${v} of ${m}`Formats the "x of y" readout. Defaults to ${value} of ${max}.
warnAtnumber0.8Fraction (0–1) at which the meter warns. Defaults to 0.8.

Also accepts everything from Omit, so id, data-* and event handlers pass straight through.

Open in Storybookfor controls, the a11y panel and the interaction runner.