Skip to content

shadcn.io is not affiliated with official shadcn/ui

Components

Free

Context for Vue

How much of the model's context window is in use. For Vue with Ark UI, a Hover Card with a Progress bar on a Button, and no component of its own.

UI library: Ark UI

A small button says how much of the context window the conversation has used, and hovering it shows the tokens behind the number.

Use it near the message field in a chat that can run long, so the reader sees the window filling before the model starts forgetting the start of the thread. The button is a Button, the card a Hover Card and the bar a Progress, so there is no Context component to install in Vue. Keep the percentage in the button's label: a hover card doesn't open on a tap, so the card holds the detail, never the only number.

Preview width

Installation

Context is a pattern. The command adds the parts it's built from, Hover Card, Progress and Button, and the code to copy is the demo's.

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.

Anatomy

Context anatomy: hover card trigger, hover card content, progress
HoverCard
├── HoverCardTrigger (Button, the percentage)
└── HoverCardContent
    ├── Header (Context, used / limit)
    ├── Progress
    └── Rows (input, output, reasoning)

Usage

<script setup lang="ts">
import { Button } from "@/components/ui/button";
import {
  HoverCard, HoverCardContent, HoverCardTrigger,
} from "@/components/ui/hover-card";
import { Progress } from "@/components/ui/progress";
</script>
export function Context(props: { limit: number; used: number }) {
  const percent = Math.round((props.used / props.limit) * 100);

  return (
    <HoverCard closeDelay={100} openDelay={10}>
      <HoverCardTrigger asChild>
        <Button size="sm" variant="outline">
          {percent}% context
        </Button>
      </HoverCardTrigger>
      <HoverCardContent className="flex w-64 flex-col gap-3">
        <div className="flex items-center justify-between gap-3 text-sm">
          <span className="font-medium">Context</span>
          <span className="text-muted-foreground">
            {props.used} / {props.limit}
          </span>
        </div>
        <Progress aria-label="Context used" value={percent} />
      </HoverCardContent>
    </HoverCard>
  );
}

AI SDK

Read usage from the metadata on the agent's message. messageMetadata runs when the stream finishes.

app/api/chat/route.ts
return result.toUIMessageStreamResponse({
  messageMetadata: ({ part }) => {
    if (part.type === "finish") {
      return { usage: part.totalUsage };
    }
  },
});
const usage = message.metadata?.usage;
const used = (usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0);
const percent = Math.round((used / limit) * 100);

limit is the model's context window. The AI SDK does not send it, so set it from the model you use.

The metadata is the same on the messages of @ai-sdk/vue's Chat: read it from the agent's last message in chat.messages.

Migrating from AI SDK Elements

AI SDK Elements is for React. In Vue, start from the demo above: a Hover Card with a Progress, on a Button, is all there is to Context.

FAQ

What does installing Context add in Vue?

Hover Card, Progress and Button, the three parts it's built from. Context is a pattern, so no context file lands in your ui folder: copy the demo's code into your own component and pass it the usage from your chat. The command uses the shadcn-vue CLI.

Where do the numbers come from?

The model reports the tokens each turn used, and the AI SDK hands them over as usage in the message's metadata when the stream finishes. The limit is the model's context window, which the SDK doesn't send: set it from the model you use, and change it when the reader switches models.

Should I add up the usage of every message?

No. Each request sends the whole thread, so the latest turn's input tokens already count everything before it. Take the agent's last message, add its output tokens, and that is what the next request starts from. The demo adds input, output and reasoning for one turn.

Can the reader see the numbers without hovering?

The percentage, yes: it's the button's label. The card opens on hover and on keyboard focus, not on a tap, so on a phone it may never show. If the breakdown matters there, open it in a Popover instead.

What should happen when the window is nearly full?

Say so where the reader is already looking. Past a threshold, change the button's label or variant, and add a note to the thread that suggests a new chat or compacting the conversation. The bar alone is easy to miss.

How does a screen reader read Context?

The button's text is its name, so 8% context is read as is. Inside the card, the Progress has aria-label Context used and reads as a bar with its value. Treat the card as extra detail: what a screen reader must hear belongs in the button's label.

Is this the same as AI SDK Elements' Context?

It does the same job without a wrapper: Context was a Hover Card with usage parts and a cost estimate, and here it's a Hover Card with a Progress on a Button. The Migrating from AI SDK Elements section has a prompt that rebuilds the old file on these parts and keeps its exports.

API Reference

Context has no props of its own. The card is a Hover Card on a Button with variant outline and size sm, and the bar is a Progress with an aria-label.