# Char Limit Indicator

Char Limit Indicator [#char-limit-indicator]

The **Char Limit Indicator** is a compact character-count display: a radial progress ring (percentage of the limit consumed) paired with an `n/MAX` monospace counter. When `charCount` exceeds `maxLength`, the counter and ring switch to the error color and the ring shows a full circle.

The ring is a pure SVG implementation driven by shadcn/ui CSS variables (`text-primary`, `text-destructive`, `text-muted`) — no daisyUI, no canvas. It is self-contained: pass only `charCount` and `maxLength` and it derives the percentage internally, so it drops in beside any length-bounded textarea or [`PromptInput`](/docs/conversation/prompt-input).

**When to use it:** show how close a user is to a length limit (tweet box, prompt field, comment form) with an at-a-glance ring plus an exact count.

Preview [#preview]

```tsx
'use client';

import { useState } from 'react';
import { CharLimitIndicator } from '@/components/char-limit-indicator';

/**
 * Demo for the CharLimitIndicator, used by the docs live preview. A bound
 * textarea drives the ring + counter; type past the limit to see the error
 * state. Pure UI — no model download.
 */
export default function CharLimitIndicatorDemo() {
  const [value, setValue] = useState('Local-first AI runs entirely in your browser.');
  const maxLength = 80;

  return (
    <div className="flex w-full max-w-md flex-col gap-2">
      <textarea
        value={value}
        onChange={(e) => setValue(e.target.value)}
        rows={3}
        className="w-full resize-none rounded-md border border-input bg-transparent px-3 py-2 text-sm outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50"
        placeholder="Type to drive the ring…"
      />
      <div className="flex justify-end">
        <CharLimitIndicator charCount={value.length} maxLength={maxLength} />
      </div>
    </div>
  );
}
```

Installation [#installation]

```bash
npx shadcn@latest add @localmode/ui/input-controls/char-limit-indicator
```

Dependencies [#dependencies]

* **Data source:** renders the `charCount` / `maxLength` props you pass — works with any backend (a plain `value.length`, a tokenizer, or a token-usage hook). Recommended LocalMode producer: `useChat` usage / token counting (optional).
* `clsx` + `tailwind-merge` — via the shared `cn()` util (installed automatically as a registry dependency)

Files installed [#files-installed]

* `char-limit-indicator.tsx` — the component
* `lib/utils.ts` — the `cn()` helper (if not already present)

Props [#props]

**CharLimitIndicator**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `charCount` | `number` | — | **Required.** Current number of characters in the bound input. |
| `maxLength` | `number` | — | **Required.** Maximum allowed characters. The ring fills as `charCount` approaches it. |
| `size` | `number` | `28` | Diameter of the ring in pixels. |
| `strokeWidth` | `number` | `3` | Stroke width of the ring in pixels. |
| `ringOnly` | `boolean` | `false` | When true, render only the ring (hide the `n/MAX` counter). |

Examples [#examples]

Beside a textarea [#beside-a-textarea]

```tsx
import { useState } from 'react';
import { CharLimitIndicator } from '@/components/char-limit-indicator';

export function Composer() {
  const [value, setValue] = useState('');
  const maxLength = 280;

  return (
    <div className="flex flex-col gap-2">
      <textarea value={value} onChange={(e) => setValue(e.target.value)} />
      <div className="flex justify-end">
        <CharLimitIndicator charCount={value.length} maxLength={maxLength} />
      </div>
    </div>
  );
}
```

Ring only [#ring-only]

```tsx
<CharLimitIndicator charCount={value.length} maxLength={280} ringOnly />
```

Customization [#customization]

The ring colors come straight from shadcn/ui CSS variables — `text-primary` under the limit, `text-destructive` over it, `text-muted` for the track — so the indicator inherits your theme automatically. Tune `size` and `strokeWidth` for the ring geometry; because you own the file, you can swap the over-limit color or add a near-limit warning band by editing the `overLimit` branch in `char-limit-indicator.tsx`.