Rate limit banner
Docks above the composer when a limit is near or reached: how many are left and until when, then a live countdown and a model that still has room.
On this page
Send a few messages: the banner counts down what is left, then pauses sending with a live countdown.
Installation
Usage
import { RateLimitBanner } from "@/components/ui/chatcn/rate-limit-banner"
<RateLimitBanner
state="reached"
model="Opus 4.1"
resetsAt={limit.resetsAt}
fallbackModel="Sonnet 4.5"
onSwitchModel={() => setModel("sonnet-4-5")}
onReset={() => refetchLimits()}
/>
<PromptInput disabled={reached}>…</PromptInput>The docked variant tucks under the composer's top edge so the two read as one object. When the countdown ends the banner says the limit has reset and calls onReset.
Examples
States
Approaching, reached with a countdown, and reset.
Props
| Prop | Type | Notes |
|---|---|---|
state | "approaching" | "reached" | |
remaining, unit | number, string | For approaching. Unit defaults to messages |
resetsAt | number | Date | string | Drives the countdown |
model, fallbackModel, onSwitchModel | Use {fallbackModel} | |
action | ReactNode | The upgrade slot |
onDismiss | () => void | Approaching only |
onReset | () => void | Once, at zero |
variant | "docked" | "inline" | Default docked |
Accessibility
- The banner is a
statusregion. The countdown clock is hidden from screen readers; the text says the wall clock time instead, so nothing is announced each second. - Pair it with a disabled composer whose placeholder says why sending is paused.
Motion
- The banner rises 4 px and fades in over 200 ms. The icon swaps with the blur crossfade between states.
- The countdown updates in place in tabular mono figures: no layout shift, no animation per tick.