Skip to content
SettingsRate limit bannerMenu

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.

Send a few messages: the banner counts down what is left, then pauses sending with a live countdown.

Installation

$ pnpm dlx shadcn@latest add https://chatcn.dev/r/rate-limit-banner.json

Usage

tsx
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

PropTypeNotes
state"approaching" | "reached"
remaining, unitnumber, stringFor approaching. Unit defaults to messages
resetsAtnumber | Date | stringDrives the countdown
model, fallbackModel, onSwitchModelUse {fallbackModel}
actionReactNodeThe upgrade slot
onDismiss() => voidApproaching only
onReset() => voidOnce, at zero
variant"docked" | "inline"Default docked

Accessibility

  • The banner is a status region. 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.