# ContextRing

> How much of the context window is gone, in the space of a favicon: a donut that fills as the conversation grows, the compact count beside it, and an optional popover breaking the total down by what is holding it.

- Package: `fancy-ui-svelte` (Svelte 5 + Tailwind CSS v4)
- Category: AI Chat
- Tags: ai, chat, tokens, context, indicator
- Docs: https://fancy-ui.rama.app/docs/components/context-ring
- Source: https://github.com/RamaHerbin/fancy-ui/tree/main/src/lib/fancy-ui/context-ring

## Import

```svelte
<script lang="ts">
  import { ContextRing } from 'fancy-ui-svelte';
</script>
```

Setup (once per project): `npm install fancy-ui-svelte`, then add `@import "fancy-ui-svelte/tailwind.css";` after `@import "tailwindcss";` in your main CSS file. Full guide: https://fancy-ui.rama.app/llms.txt

React: `import { ContextRing } from 'fancy-ui-react';` (same prop names; `class` becomes `className`, snippets become `ReactNode`).

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `usage` (required) | `TokenUsageData` | — | Context-window consumption: tokens used, out of how many, and optionally the breakdown rows the popover lists |
| `size` | `number` | `28` | Outer diameter of the ring, in pixels; drives the viewBox and the radius |
| `strokeWidth` | `number` | `3` | Thickness of the track and the arc, in pixels; clamped to the radius so a thick ring cannot eat its own centre |
| `showLabel` | `boolean` | `true` | Whether the compact "12.4k / 200k" figure is shown beside the ring — exact under a thousand, one decimal under 100k, rounded above |
| `warnAt` | `number` | `0.75` | Fraction at which the ring leaves the quiet band and takes the running colour |
| `criticalAt` | `number` | `0.9` | Fraction at which the ring takes the error colour. Floored at warnAt, so a threshold set below the warning cannot create a band that never wins |
| `label` | `string` | `"Context usage"` | Accessible name for the meter, and — when expandable — for the button that contains it |
| `expandable` | `boolean` | `false` | Turns the ring into a button that toggles a popover listing usage.breakdown; closes on Escape, on a click outside, or on a second press |
| `sound` | `boolean` | `false` | Plays open/close on the breakdown popover, once the user has enabled sound |

## Examples

### Basic Usage

```svelte
<script lang="ts">
	import { ContextRing } from "fancy-ui-svelte";
	import type { TokenUsageData } from "fancy-ui-svelte";

	// Nothing is on a timer here: every ring is a fixed reading and the popover
	// only moves when you move it, so there is no rig to hold still for reduced
	// motion and no effect in this file at all.
	const comfortable: TokenUsageData = { used: 12_400, max: 200_000 };
	const warning: TokenUsageData = { used: 164_000, max: 200_000 };
	const critical: TokenUsageData = { used: 192_500, max: 200_000 };

	const detailed: TokenUsageData = {
		used: 84_300,
		max: 200_000,
		breakdown: [
			{ label: "System prompt", tokens: 1850 },
			{ label: "Transcript", tokens: 61_200 },
			{ label: "Tool results", tokens: 18_400 },
			{ label: "Attachments", tokens: 2850 },
		],
	};
</script>

<div class="flex w-full max-w-xl flex-col gap-6 p-6">
	<div class="flex flex-wrap items-center gap-8">
		<ContextRing usage={comfortable} />
		<ContextRing usage={warning} />
		<ContextRing usage={critical} />
	</div>

	<p class="text-muted-foreground text-xs">
		The band shifts at 75% and again at 90%, using the same run-status colours as the rest of the AI
		family. The arc's length says the same thing as its hue, so neither is load-bearing on its own.
	</p>

	<div class="border-border flex items-center gap-3 border-t pt-6">
		<ContextRing sound usage={detailed} size={34} strokeWidth={4} expandable />
		<span class="text-muted-foreground text-xs">
			Press the ring for the breakdown. Escape closes it.
		</span>
	</div>
</div>
```
