TokenMeter
How much of the context window a conversation is using.
Use when you are building a chat UI against a model with a context limit. A client that doesn't show this works fine at first, then fails: every turn resends the full history, the request only grows, and eventually the provider rejects it for exceeding the limit. This component shows that growth before the request gets rejected.
Quick Start
Basic Usage
<r-token-meter limit="65536" used="12800"></r-token-meter>const meter = document.createElement('r-token-meter');
meter.limit = 65536;
meter.used = 41200; // context the next request will carry
meter.spent = 128431; // tokens billed across the conversation, optional
composer.append(meter);The bar fills to used / limit and escalates through three levels: ok, warn (from 80%
of the limit) and over. level is reflected onto the host, so the page can react to the
same escalation the bar shows:
r-token-meter[level='warn'] ~ .composer-hint {
display: block;
}used and spent are different numbers
used: what the next request will carry, the history, not the whole conversation. This is the number the limit applies to, and the one the bar draws.spent: what has been billed across the conversation so far. It only ever grows, and it is not bounded by the window.
Truncating a transcript lowers used and leaves spent alone. Showing only one of them
answers only one of the two questions a user has ("will the next message fit?" and "what has
this cost me?").
Without a limit
With limit unset or zero the bar disappears and only the counts remain, useful while the
window size is unknown.
Relabelling
<r-token-meter label="上下文" limit="65536" used="41200"></r-token-meter>
<!-- label="" leaves only the counts -->API Reference
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
limit |
limit |
number |
0 |
Context window size in tokens. Zero or absent hides the bar. |
used |
used |
number |
0 |
Tokens the next request will carry. |
spent |
spent |
number |
0 |
Tokens billed across the conversation so far. |
label |
label |
string |
'Context' |
Prefix for the readout; '' leaves only the counts. |
level |
level |
'ok' | 'warn' | 'over' |
derived | How full the window is. Set by the element: writing it is overwritten on the next update. |
sheet |
sheet |
string |
'' |
CSS injected into the shadow root. |
Counts are formatted for quick reading: exact below a thousand (847 is short enough to read
exactly), abbreviated above (41.2k, 128k); the third digit of 128,431 doesn't change what
a reader does with it.
Parts
| Part | Element |
|---|---|
meter |
The whole element |
track |
The bar's background |
fill |
The filled portion |
text |
The label and counts |
Accessibility
The element always carries a title stating the numbers, so colour is never the only
carrier of the warning: the bar going amber is a second signal, not the only one. Keep it
that way if you restyle the levels.
Styling
<r-token-meter> exposes 9 CSS custom properties of its own, plus the semantic tokens it reads
from the theme. Set one anywhere it inherits from: :root, a wrapper, or the element:
r-token-meter {
--ran-token-meter-fill-background: var(--ran-color-bg-subtle);
}Parts: fill · meter · text · track
The full list is in style tokens; which token to reach for is the design system.
Best Practices
- Update
usedfrom the same place you build the request, not from a rendering pass: the number people trust is the one the next request will actually send. - Escalate around the meter, not inside it. At
level="over"the useful UI is a suggestion (summarise, start a new thread), and that belongs to the app. - Don't animate the fill on a theme change: see design guidelines.