# Usage level

How close a usage is to its limit, on the lines UsageMeters, UsageGlance, UsageRing and PortfolioCard all use, so no two of them disagree: the ratio of what's used to the limit, the level (warning from 75 %, danger from 90 %) and the level's colours. With no limit (null, or 0) there is nothing to read the figure against, so the ratio, the level and the tone are all null: nothing is drawn against a made-up cap. The same when the figure or the limit isn't a finite number. It reads the measured `used` only: an estimate, pending usage or a may-exceed figure never moves the level.

Safe to call on the server.

```ts
const { level, tone } = usageLevel({ used: 8.2, limit: 10 }) // "warning", { token: "cd-warning", … }
```

- Registry name: `usage-level` (`@candor/usage-level`)
- 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-level

## Install

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

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/usage-level`.
It brings in: ops, tokens.

## Functions

### usageLevel

```ts
usageLevel(usage: Pick<Usage, "used" | "limit">)
```

## Values

### usageLevelThresholds

The share of the limit at which a usage reaches each level.

```ts
const usageLevelThresholds: {
  readonly warning: 0.75;
  readonly danger: 0.9;
}
```

### usageLevelTones

Each level's colours.

```ts
const usageLevelTones: Record<UsageLevelName, UsageLevelTone>
```

## Types

### UsageLevelName

How close a usage is to its limit: under 75 % normal, from 75 % warning, from 90 % danger.

```ts
"normal" | "warning" | "danger"
```

### UsageLevelTone

A level's colours, as UsageMeters draws them.

```ts
{
  /** The theme variable that fills the used part of a bar or ring: `primary`, `cd-warning` or `destructive`. Read it as `var(--${token})`. */
  token: "primary" | "cd-warning" | "destructive";
  /** The class for words in the level's colour, readable on the card. */
  text: "text-accent-text" | "text-warning-text" | "text-destructive-text";
}
```

### UsageLevel

What `usageLevel` works out from a usage and its limit.

```ts
{
  /** What is used over the limit (1 is at the limit, above 1 past it); null when there is no limit to read it against. */
  ratio: number | null;
  /** The level from the ratio; null when there is no limit. */
  level: UsageLevelName | null;
  /** The level's colours; null when there is no limit, so nothing is drawn in a level's colour. */
  tone: UsageLevelTone | null;
}
```

## 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;
}
```

## 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`.
