import { ContextDisplaySample } from "@/components/docs/samples/context-display";
This component requires server-side setup to [forward token usage metadata](#forward-token-usage-from-your-route-handler). Without it, ContextDisplay will show 0 usage and no breakdown data.Getting Started#
Add context-display#
<InstallCommand shadcn={["context-display"]} />
This adds a /components/assistant-ui/context-display.tsx file to your project.
Forward token usage from your route handler#
Use messageMetadata in your Next.js route to attach usage from finish and modelId from finish-step:
import { streamText, convertToModelMessages } from "ai";
export async function POST(req: Request) {
const { messages, config } = await req.json();
const result = streamText({
model: getModel(config?.modelName),
messages: await convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse({
messageMetadata: ({ part }) => {
if (part.type === "finish") {
return {
usage: part.totalUsage,
};
}
if (part.type === "finish-step") {
return {
modelId: part.response.modelId,
};
}
return undefined;
},
});
}
Use in your application#
Pick a variant and place it in your thread footer, composer, or sidebar. Pass modelContextWindow with your model's token limit.
import { ContextDisplay } from "@/components/assistant-ui/context-display";
const ThreadFooter: FC = () => {
return (
<div className="flex items-center justify-end px-3 py-1.5">
<ContextDisplay.Bar modelContextWindow={128000} />
</div>
);
};
Variants#
Three preset variants are available, each wrapping the shared tooltip popover:
// SVG donut ring (default, compact)
<ContextDisplay.Ring modelContextWindow={128000} />
// Horizontal progress bar with label
<ContextDisplay.Bar modelContextWindow={128000} />
// Minimal monospace text
<ContextDisplay.Text modelContextWindow={128000} />
All presets accept className for styling overrides and side to control tooltip placement ("top", "bottom", "left", "right").
Composable API#
For custom visualizations, use the building blocks directly:
import { ContextDisplay } from "@/components/assistant-ui/context-display";
<ContextDisplay.Root modelContextWindow={128000}>
<ContextDisplay.Trigger aria-label="Context usage">
<MyCustomGauge />
</ContextDisplay.Trigger>
<ContextDisplay.Content side="top" />
</ContextDisplay.Root>
| Component | Description |
|---|---|
Root | Uses provided usage when supplied, otherwise fetches token usage internally; provides shared context and wraps children in a tooltip |
Trigger | Button that opens the tooltip on hover |
Content | Tooltip popover with the token breakdown (Usage %, Input, Cached, Output, Reasoning, Total) |
API Reference#
Preset Props#
All preset variants (Ring, Bar, Text) share the same props:
| Prop | Type | Default | Description |
|---|---|---|---|
modelContextWindow | number | — | Maximum token limit of the current model (required) |
className | string | — | Additional class names on the trigger button |
side | "top" | "bottom" | "left" | "right" | "top" | Tooltip placement |
usage | ThreadTokenUsage | — | Optional externally-provided usage data (skips internal usage fetch when provided) |
Color Thresholds#
Ring and Bar share the same severity colors:
| Level | Threshold | Ring | Bar |
|---|---|---|---|
| Low | < 65% | stroke-emerald-500 | bg-emerald-500 |
| Warning | 65% – 85% | stroke-amber-500 | bg-amber-500 |
| Critical | > 85% | stroke-red-500 | bg-red-500 |
Text displays numeric values only — no severity color.
Related#
- Message Timing — Streaming performance stats (TTFT, tok/s)
- Thread — The thread component where ContextDisplay is typically placed