# Usage glance

One usage against its limit as one line, for a top bar's `end` or a page header: "$4.10 of $10", a thin bar, the period in your words ("November") and, with `href`, the usage's label as a link to the page that has the detail. Its levels are UsageMeters' (warning from 75 %, danger from 90 %, through `usageLevel`), so the glance and the meters never disagree, and a level past normal is said with an icon and words ("Nearing the limit"), never by colour alone.

Where the plan sets no limit there is no bar and no level, only the count, as UsageMeters has it. A figure that isn't known yet (`unknown`: the provider hasn't reported) says "Not known yet" and draws no bar: it is never shown as zero. When work has stopped because of the limit, say so with `paused` (true, or your reason): the glance never infers it from what's used, since being over a limit doesn't mean anything has stopped.

Pending usage, an estimate and how far a run may go past the limit need more room than a line: show them in UsageMeters or UsageRing on the page `href` opens.

- Registry name: `usage-glance` (`@candor/usage-glance`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/usage-glance

## Install

```bash
npx candor-ui add usage-glance
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/usage-glance`.
It brings in: bidi, link, locale, motion, ops, tokens, usage-level, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import { UsageGlance } from "@/components/candor/usage-glance"
import { TopBar } from "@/components/candor/top-bar"

export default function Example() {
  return (
    <div className="flex w-full flex-col gap-4">
      {/* In a top bar's end: the label links to the page with the detail (UsageMeters, UsageRing). */}
      <TopBar
        className="rounded-xl border"
        end={<UsageGlance usage={{ label: "Agent spend", used: 4.1, limit: 10, unit: "USD", usedText: "$4.10", limitText: "$10" }} period="November" href="#usage" />}
      />
      {/* From 75 % of the limit the level is said in words with an icon, not by colour alone. */}
      <UsageGlance usage={{ label: "Agent spend", used: 9.3, limit: 10, unit: "USD", usedText: "$9.30", limitText: "$10" }} period="November" />
      {/* Paused is your statement, with your reason: the glance never infers it from what's used. */}
      <UsageGlance usage={{ label: "Agent spend", used: 10, limit: 10, unit: "USD", usedText: "$10", limitText: "$10" }} period="November" paused="Agents stop at the limit" />
      {/* No limit: the count alone, no bar. */}
      <UsageGlance usage={{ label: "Agent runs", used: 412, limit: null, unit: "runs" }} period="this week" />
      {/* Not reported yet: said, never shown as zero. */}
      <UsageGlance usage={{ label: "Agent spend", used: 0, limit: 10, unit: "USD", limitText: "$10" }} period="November" unknown />
    </div>
  )
}
```

## <UsageGlance>

Props:

- `usage: Usage`: What's used, the limit (null when there is none) and the unit. `usedText` and `limitText` are shown as written.
- `period?: string | undefined`: The period the usage counts over, in your words: "November", "this week". Shown after the bar.
- `href?: string | undefined`: Where the usage's detail is in the app: the label becomes a link to it, through the app's router.
- `unknown?: boolean | undefined`: The figure isn't known yet (the provider hasn't reported): the glance says so, with no bar and no level, never zero.
- `paused?: boolean | string | undefined`: The app's own statement that work is paused (by the limit, or by a person): true, or the reason in your words ("Agents stop at the limit"). Drawn with an icon beside the figure. Never inferred from what's used.
- `className?: string | undefined`

## Strings (`usageGlance`)

The fixed words, English by default. Override any of them under `usageGlance` in `<LocaleProvider strings={{ usageGlance: { … } }}>`; the table is exported as `usageGlanceStrings`.

- `usedOfLimit`: {used} of {limit}
- `amount`: {value} {unit}
- `notKnown`: Not known yet
- `notKnownOfLimit`: Not known yet, of {limit}
- `warning`: Nearing the limit
- `danger`: Close to the limit
- `atLimit`: At the limit
- `overLimit`: Over the limit
- `paused`: Paused
- `pausedBecause`: Paused: {reason}

## Types from other items

The props above take these. Each is defined by another item; import it from the path shown.

### Usage

Import: `import type { Usage } from "@/lib/candor/ops"` (item `ops`, https://candor.themethodic.com/docs/ops.md)

```ts
{
  label: string;
  used: number;
  /** null when there's no limit (the plan sets none). */
  limit: number | null;
  unit: string;
  resetsAt?: string | undefined;
  note?: string | undefined;
  /**
   * Your own estimate of where it will end, in the same unit (a quote, a forecast), marked on the bar. It is shown as
   * given and labelled as an estimate; nothing is extrapolated.
   */
  estimate?: number | undefined;
  /** Words for the estimate marker ("My guess"); defaults to the `usageMeters.estimate` string. */
  estimateLabel?: string | undefined;
  /**
   * The figures as your server wrote them, shown as they are instead of Candor's number formatting (with the unit
   * left to you): `used` ("about $4"), `limit` ("$10") and `estimate`. The numbers still place the bar and markers.
   */
  usedText?: string | undefined;
  limitText?: string | undefined;
  estimateText?: string | undefined;
  /**
   * Work already done that your provider hasn't metered yet, in the same unit: it will count, but isn't in `used`.
   * Drawn after the used part of the bar, striped, and said in words ("about $1 not yet metered").
   */
  pending?: number | undefined;
  /** `pending` as your server wrote it ("about $1"), shown as written. */
  pendingText?: string | undefined;
  /**
   * How far past the limit this may still go, from your own figure (a provider that checks the limit between steps, a
   * run already under way), in the same unit. Said under the meter; the meter never works it out.
   */
  mayExceedBy?: number | undefined;
  /** `mayExceedBy` as your server wrote it, shown as written. */
  mayExceedByText?: string | undefined;
}
```

## Motion

- **fill** (fill): The used part of the bar moves from the old measured amount to the new one when it changes while the line is on screen. It draws its first amount in place, never from empty, and a limit or figure that isn't known shows no bar to move.

Set with `--cd-motion-usage-glance-<moment>-*` in your brand file; the families are in the design reference.

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider`: its fixed strings in `strings`, its nouns in `nouns`; entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
