Installation
Complete project setup with react/base, then install these components:
pnpm exec frontfriend download hover-card button progress -f react --primitive base Input and output counts come from message usage data. Set the limit from your selected model. The percent is clamped to 0–100, and a zero or invalid limit displays unavailable. The example uses fixed counts.
Usage
Complete example
import {
HoverCard,
HoverCardTrigger,
HoverCardContent,
} from "@/components/ui/hover-card";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import * as React from "react";
export default function AiContextExample() {
const [open, setOpen] = React.useState(false);
const valid =
Number.isFinite(128000) &&
128000 > 0 &&
Number.isFinite(10660);
const percent = valid
? Math.min(
100,
Math.max(
0,
Math.round((10660 / 128000) * 100),
),
)
: 0;
const input = valid
? Math.max(0, Math.round((10660 * 8420) / 10660))
: 0;
const output = valid
? Math.max(0, Math.round((10660 * 1260) / 10660))
: 0;
const rows = [
{ label: "Input", value: input },
{ label: "Output", value: output },
{
label: "Reasoning",
value: valid ? Math.max(0, 10660 - input - output) : 0,
},
];
return (
<div
style={{
width: "100%",
maxWidth: 560,
minWidth: 0,
marginInline: "auto",
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: 16,
paddingBlock: 16,
fontSize: "var(--text-sm)",
lineHeight: 1.5,
}}
>
<HoverCard open={open} onOpenChange={setOpen}>
<HoverCardTrigger asChild delay={10} closeDelay={100}>
<Button
variant="outline"
size="sm"
onFocus={() => setOpen(true)}
onClick={() => setOpen(true)}
>
{valid ? `${percent}% context` : "Context unavailable"}
</Button>
</HoverCardTrigger>
<HoverCardContent>
<div style={{ display: "grid", gap: 12, fontSize: "var(--text-sm)" }}>
<strong>Context window</strong>
<p>
{valid
? `${Math.max(0, 10660).toLocaleString()} / ${Number(128000).toLocaleString()} tokens`
: "Set a valid token limit."}
</p>
<Progress value={percent} aria-label="Context used" />
<dl style={{ display: "grid", gap: 6 }}>
{rows.map((row) => (
<div
key={row.label}
style={{
display: "flex",
justifyContent: "space-between",
gap: 16,
}}
>
<dt>{row.label}</dt>
<dd>{row.value.toLocaleString()}</dd>
</div>
))}
</dl>
</div>
</HoverCardContent>
</HoverCard>
</div>
);
} Components and API
This composition has no separate component API. Use the APIs for its installed components.
| Component | Target reference |
|---|---|
hover-card | Base UI API |
button | Base UI API |
progress | Base UI API |