Data displayui
Usage meter
Usage against a quota with warning and critical thresholds.
Compute58 / 191 CU-hrs
Resets November 1.
Bandwidth86 / 100 GB
Function invocations998K / 1000K
Installation
npx shadcn@latest add @particular/usage-meternpm dependencies
- @base-ui/react@^1.8.0
- cn@^0.4.0
Source
"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 }