jengacore components · @jengacore/meter
Meter
Share of a limit with the alert threshold marked and the percentage as text.
42%
86%
99%
Install
terminal
npx shadcn@latest add @jengacore/meterWithout the namespace configured: npx shadcn@latest add https://ui.jengacore.com/r/<new-york-v4|base-nova>/meter.json
Registry dependencies
Source
components/jc/meter.tsx
import * as React from "react"
import { cn } from "@/lib/utils"
/**
* Share of a limit (net debit cap used), with the alert threshold marked.
* Green below the threshold, amber from it, red from `danger`. Always show the percentage as text too
* (`showValue`), so the state never depends on colour.
*/
export function Meter({
percent,
threshold = 80,
danger = 95,
label,
showValue = false,
className,
}: {
percent: number
threshold?: number
danger?: number
label: string
showValue?: boolean
className?: string
}) {
const clamped = Math.max(0, Math.min(percent, 100))
const tone = percent >= danger ? "bg-destructive" : percent >= threshold ? "bg-warning" : "bg-primary"
const bar = (
<div
role="meter"
aria-label={label}
aria-valuenow={Math.round(percent)}
aria-valuemin={0}
aria-valuemax={100}
className={cn("relative h-1.5 flex-1 overflow-hidden rounded-full bg-muted contrast:outline contrast:outline-input", !showValue && className)}
>
<i className={cn("absolute inset-y-0 left-0 origin-left animate-fill rounded-full", tone)} style={{ width: `${clamped}%` }} />
<span className="absolute inset-y-0 w-0.5 bg-foreground/40" style={{ left: `${threshold}%` }} aria-hidden />
</div>
)
if (!showValue) return bar
return (
<div data-slot="meter" className={cn("flex items-center gap-2.5", className)}>
{bar}
<span className="w-10 text-right font-mono text-xs tabular-nums text-muted-foreground">{Math.round(percent)}%</span>
</div>
)
}