73 / 122 · Observability
Quota
How much is left, when it comes back, and the way to get more.
18 messages leftresets in 3h 12m
32 of 50 used
Installation
npx shadcn@latest add "@assistant-ui/elements-quota-banner"
Usage
import { QuotaBanner } from "@/components/elements/quota-banner";
<QuotaBanner used={47} limit={50} unit="messages" resetsIn="3h 12m" upgradeLabel="Upgrade" />Props
used*numberHow much has been consumed.
limit*numberThe allowance. The banner turns amber at 90 percent.
unit*stringWhat is being counted: messages, runs, credits.
resetsIn*stringPre-formatted time until the window rolls over.
upgradeLabel*stringLabel for the way out.
onUpgrade() => voidCalled from the upgrade action.
classNamestringExtra classes merged onto the root.
Source
quota-banner.tsx"use client";
import { cn } from "@/lib/utils";
import { inkButton, mono, paper } from "./surfaces";
export function QuotaBanner({
used,
limit,
unit,
resetsIn,
upgradeLabel,
onUpgrade,
className,
}: {
used: number;
limit: number;
unit: string;
resetsIn: string;
upgradeLabel: string;
onUpgrade?: () => void;
className?: string;
}) {
const left = Math.max(0, limit - used);
const ratio = limit === 0 ? 0 : used / limit;
const tight = ratio >= 0.9;
return (
<div
className={cn(
paper,
"flex w-full max-w-sm flex-col gap-2.5 rounded-2xl p-3.5",
className,
)}
>
<div className="flex items-baseline gap-2">
<span
className={cn(
"text-[13.5px] font-medium",
tight && "text-amber-700 dark:text-amber-400",
)}
>
{left} {unit} left
</span>
<span className={cn(mono, "text-foreground/30 ms-auto tabular-nums")}>
resets in {resetsIn}
</span>
</div>
<span className="bg-foreground/[0.06] h-1 w-full overflow-hidden rounded-full">
<span
className={cn(
"block h-full rounded-full transition-[width] duration-500 motion-reduce:transition-none",
tight ? "bg-amber-500" : "bg-foreground/40",
)}
style={{ width: `${Math.min(100, ratio * 100)}%` }}
/>
</span>
<div className="flex items-center gap-2">
<span className={cn(mono, "text-foreground/30 tabular-nums")}>
{used} of {limit} used
</span>
<button
type="button"
onClick={onUpgrade}
className={cn(
inkButton,
"ms-auto flex h-7 items-center rounded-full px-3 text-xs font-medium",
)}
>
{upgradeLabel}
</button>
</div>
</div>
);
}