zazzy
Blocks

Usage quota banner

A dismissible banner that warns when a metered quota nears its plan limit, using the usage and flags surfaces.

A dismissible banner that appears when one of the org's metered quotas is at or near its plan limit — a nudge to upgrade before work is blocked. It renders nothing while loading, when no quota is near its cap, or after dismissal. The threshold defaults to 80% of a finite limit; uncapped metrics never trigger it.

Requires: usage, flags

Preview

You're close to a plan limit

  • API calls: 9200 / 10000
"use client";import { useState } from "react";import { Button } from "@/components/ui/button";import { cn } from "@/lib/utils";import { useQuotaStatus } from "./use-quota-status";/** * A dismissible banner that appears when one of the org's metered quotas is at or * near its plan limit — a nudge to upgrade before work is blocked. Renders nothing * while loading, when no quota is near its cap, or after dismissal. The threshold * defaults to 80% of a finite limit; uncapped metrics never trigger it. */export function QuotaBanner({ className }: { className?: string }) {  const [dismissed, setDismissed] = useState(false);  const { isPending, breaches } = useQuotaStatus();  if (isPending || dismissed || breaches.length === 0) return null;  const critical = breaches.some((breach) => breach.severity === "critical");  return (    <div      role="status"      className={cn(        "flex items-start justify-between gap-4 rounded-md border px-4 py-3 text-sm",        critical          ? "border-destructive/50 text-destructive"          : "border-border text-foreground",        className,      )}    >      <div className="flex flex-col gap-1">        <p className="font-medium">          {critical            ? "You've hit a plan limit"            : "You're close to a plan limit"}        </p>        <ul className="text-muted-foreground">          {breaches.map((breach) => (            <li key={breach.key}>              {breach.description}: {breach.used} / {breach.limit}            </li>          ))}        </ul>      </div>      <Button        variant="secondary"        size="sm"        onClick={() => setDismissed(true)}        aria-label="Dismiss"      >        Dismiss      </Button>    </div>  );}

Offline preview

The docs site has no backend, so the preview seeds one representative metric at 92% of its cap — that's what surfaces the warning state. In an app the data comes from the usage router.

Install

npx create-saas-starter add quota-banner

Run it from your app's root. add only writes new files — wiring is up to you:

import { QuotaBanner } from "@/components/blocks/quota-banner/quota-banner";

On this page