Context meter
Shows how much of the context window a conversation has used, and what is taking up the space.
Loading preview…
Install
- 1
Run this command in your Tailwind CSS project. It adds
components/ai/context-meter-ring.tsxand installs its dependencies.$ npx shadcn@latest add https://gradientdeck.com/ai-components/r/context-meter-ring.json
Usage & API
Example
import { ContextMeterRing } from "@/components/ai/context-meter-ring"
<ContextMeterRing
parts={[]}
limit={1}
/>Props ContextMeterRing
| Prop | Type & description | Required |
|---|---|---|
parts | ContextPart[] | Required |
limit | number | Required |
size | number | Optional |
defaultOpen | boolean | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
Ring exports ContextMeterRing. parts, limit, size and defaultOpen are the props. The svg is rotated so the arc starts at the top. A track circle sits behind the parts. Under the warning threshold, each part is a dash along the circumference, proportional to tokens over limit, and the dashes transition over 400 milliseconds. At or above 80 percent those arcs are replaced by one rounded sand stroke. The popover is 248 pixels wide, anchored above the button's right side. Rows use a two-pixel swatch in the part color. Free uses a neutral dot. The warning line is separated by a top border. Click toggles the tooltip. Hover and focus open it without a click, which is why a keyboard user can read it and then dismiss it with Escape. The demo starts defaultOpen and adds 2,400 tokens to Messages every 1.8 seconds until it wraps.
Example
import { ContextMeterBar } from "@/components/ai/context-meter-bar"
<ContextMeterBar
parts={[]}
limit={1}
/>Props ContextMeterBar
| Prop | Type & description | Required |
|---|---|---|
parts | ContextPart[] | Required |
limit | number | Required |
showLegend | boolean | Optional |
Dependencies
- React
- Tailwind CSS
- motion
Implementation notes
Bar exports ContextMeterBar. showLegend defaults to true. The track is 6 pixels tall. Each segment is a full-width span scaled on x and shifted by its start percent, so the motion is a transform and can spring when tokens change. Hairline gaps between segments are two-pixel masks that follow the same spring. The legend repeats the label, a swatch and the formatted token count, wrapping onto extra lines. It does not repeat Free. The warning recolors the segments but does not add the ring's sentence about summarizing older messages. If you need that sentence, put it next to the bar yourself when used divided by limit is at least 0.8. The demo header, including the message count of 38, is not derived from parts. Keep those numbers in agreement yourself. Messages in the demo climbs by 4,800 tokens on a 1.6 second interval and wraps after 150,000.
Choosing a layout
Put Ring in the composer toolbar, where a full legend will not fit. The demo sits it between an unwired Attach file button and Send message, and opens it by default so the breakdown is visible. Put Bar on a thread header or a side panel. The demo frames it under Refactor billing module and Sonnet 5.5, 38 messages. showLegend defaults to true. Turn it off when the track is a repeat of labels you already show elsewhere. The bar's own caption is the word Context, then the used count, a slash, and the limit.
Attachments tray has a different budget. Its context variant prices files you are about to send, can exclude one, and can narrow a PDF by page range. Context meter is the conversation you already have: system, tools, files, messages, or whatever labels you pass. It will not block Send. The ring does not know about the button beside it. If you need to stop a send when the window is full, do that in the parent, or use the attachments budget, which disables its own send when the total passes the limit.
What happens if the parts add up to more than the limit?
The painted share is clamped with Math.min(1, used / limit), so the arc and the bar do not run past the track. The numbers are not clamped. Ring still reads the raw used count in its button name and in the of tokens line. Bar's valuenow is the raw sum, even when it is above valuemax. Free uses Math.max(0, limit - used), so it shows 0 rather than a negative. Pass a limit that matches the model if you want the percent to mean what people think it means.
Can the meter summarize old messages for me when it passes 80 percent?
No. Ring only adds the sentence Older messages will be summarized soon, and Bar only changes color. Neither one drops messages, calls a model, or rewrites parts. The 80 percent check is used divided by limit, after the sum. If you do summarize, pass a smaller Messages part on the next render and the arc or the segments will ease to the new lengths.