# Attributes rail

A record's key/value facts as a definition list: label left, value right, hairline-separated. Long values wrap; rich values (a chip, a link) are fine. A value that isn't known shows as such, not as a blank.

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

## Install

```bash
npx candor-ui add attributes-rail
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/attributes-rail`.
It brings in: locale, utils.

## Example

```tsx
"use client"

import { AttributesRail } from "@/components/attributes-rail"

export default function Example() {
  return (
    <div className="max-w-sm rounded-xl border bg-card p-4">
      <p className="text-sm font-semibold">0142_add_region_to_projects</p>
      <AttributesRail
        className="mt-2"
        items={[
          { label: "Kind", value: "Migration" },
          { label: "Repository", value: <code className="font-mono text-xs">acme/api</code> },
          { label: "Applied to", value: "Staging" },
          { label: "Rows touched", value: "18,240" },
          { label: "Reversible", value: "Yes, with 0142_down" },
          { label: "Reviewed by", value: null },
        ]}
      />
    </div>
  )
}
```

## <AttributesRail>

Props:

- `items: { label: string; value: React.ReactNode | null }[]`: The facts, in order. A null, undefined or empty value shows as "Not known".
- `className?: string | undefined`

## Strings (`attributesRail`)

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

- `empty`: No attributes.
- `notKnown`: Not known

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