Particular.Tech
Data displayui

Usage meter

Usage against a quota with warning and critical thresholds.

Compute58 / 191 CU-hrs

Resets November 1.

x
Bandwidth86 / 100 GB
x
Function invocations998K / 1000K
x

Installation

npx shadcn@latest add @particular/usage-meter
npm dependencies
  • @base-ui/react@^1.8.0
  • cn@^0.4.0

Source

ui/usage-meter.tsx
"use client"

import * as React from "react"
import { Progress as ProgressPrimitive } from "@base-ui/react/progress"
import { cn } from "cn"

type UsageLevel = "normal" | "warning" | "critical"

function usageLevel(
  value: number,
  limit: number,
  thresholds: { warning: number; critical: number } = { warning: 0.8, critical: 0.95 }
): UsageLevel {
  const ratio = limit > 0 ? value / limit : 0
  if (ratio >= thresholds.critical) return "critical"
  if (ratio >= thresholds.warning) return "warning"
  return "normal"
}

const defaultFormat = (n: number) => new Intl.NumberFormat("en-US", { maximumFractionDigits: 1 }).format(n)

function UsageMeter({
  label,
  description,
  value,
  limit,
  unit,
  format = defaultFormat,
  thresholds,
  className,
  ...props
}: Omit<React.ComponentProps<"div">, "children"> & {
  label: React.ReactNode
  description?: React.ReactNode
  value: number
  limit: number
  unit?: string
  format?: (value: number) => string
  thresholds?: { warning: number; critical: number }
}) {
  const level = usageLevel(value, limit, thresholds)
  const percent = limit > 0 ? Math.min(100, (value / limit) * 100) : 0
  const suffix = unit ? ` ${unit}` : ""

  return (
    <ProgressPrimitive.Root
      value={Math.min(value, limit)}
      max={limit}
      data-slot="usage-meter"
      data-level={level}
      className={cn("group/usage flex flex-col gap-2", className)}
      {...props}
    >
      <div className="flex items-baseline justify-between gap-3 text-sm">
        <ProgressPrimitive.Label className="font-medium">{label}</ProgressPrimitive.Label>
        <span className="font-mono text-xs text-muted-foreground tabular-nums">
          <span className="text-foreground group-data-[level=critical]/usage:text-destructive group-data-[level=warning]/usage:text-warning">
            {format(value)}
          </span>
          {` / ${format(limit)}${suffix}`}
        </span>
      </div>
      <ProgressPrimitive.Track className="h-1.5 w-full overflow-hidden rounded-full bg-muted">
        <ProgressPrimitive.Indicator
          className="h-full rounded-full bg-foreground transition-all group-data-[level=critical]/usage:bg-destructive group-data-[level=warning]/usage:bg-warning"
          style={{ width: `${percent}%` }}
        />
      </ProgressPrimitive.Track>
      {description && <p className="text-xs text-muted-foreground">{description}</p>}
    </ProgressPrimitive.Root>
  )
}

export { UsageMeter, usageLevel, type UsageLevel }