# Degraded panel

Something couldn't be done. Says what went wrong, what is missing because of it, and offers a retry only when the caller can actually retry (Candor's DegradedPanel: a degraded state names what's missing, never just looks sad).

- Registry name: `degraded-panel` (`@candor/degraded-panel`)
- Tier: Free (MIT). No licence key needed.
- Docs: https://candor.themethodic.com/docs/degraded-panel

## Install

```bash
npx candor-ui add degraded-panel
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/degraded-panel`.
It brings in: button, locale, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import { DegradedPanel } from "@/components/degraded-panel"

export default function Example() {
  return (
    <DegradedPanel
      className="max-w-lg"
      reason="The order service didn’t answer in time."
      missing="Delivery dates for the last two orders"
      onRetry={() => {}}
    />
  )
}
```

## <DegradedPanel>

Props:

- `reason: React.ReactNode`: What went wrong, in a sentence.
- `missing?: React.ReactNode | undefined`: What the person won't see because of it.
- `onRetry?: (() => void) | undefined`: Shows a Try again button that calls this.
- `retrying?: boolean | undefined` (default `false`): Shows the retry as in progress.
- `variant?: "block" | "inline" | undefined` (default `"block"`): A boxed panel, or one line inside other content.
- `className?: string | undefined`

## Strings (`degradedPanel`)

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

- `missing`: Missing:
- `retry`: Retry
- `retrying`: Retrying

## 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` (fixed strings) and `TermsProvider` (nouns); entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
