# Key Value

> Small building blocks for detail panels: KeyValue (label/value list), Kbd (keyboard keys), Spinner, Collapsible.

Component · Foundations · Pro kit · [Live page](https://ui.twentyfirst.media/pro/components/KeyValue/)

Small building blocks for detail panels: `KeyValue` (label/value list), `Kbd` (keyboard keys), `Spinner`, `Collapsible`.

KeyValue: `items` ([label, value, mono] or {k, v, mono}), `dense`. Empty values show a dash.
Kbd: `keys` (array). Spinner: `size` ("lg"), `label`. Collapsible: `title`, `meta`, `defaultOpen` / `open` + `onOpenChange`, children.

- Keep keys short nouns; values that are codes, IDs or addresses use `mono`.
- Show a spinner only after ~300 ms; inside a button it replaces the icon.

## Example

```tsx
import * as React from "react";
import { Collapsible, Kbd, KeyValue, Spinner, StatusIndicator } from "@twentyfirstmedia/pro";

export default function Preview() {
  return (
    <div
      className="tf-grid"
      style={
        {
          "--cols": "1fr 1fr",
          gap: 16,
        } as React.CSSProperties
      }
    >
      <div
        className="tf-panel"
        style={{
          gap: 12,
        }}
      >
        <KeyValue
          items={[
            ["Server", "ax41-fsn1"],
            ["Address", "95.217.14.80", true],
            ["Kernel", "6.8.0-45"],
            ["Backups", <StatusIndicator status="ok" label="Nightly · 03:00" />],
            ["Notes", null],
          ]}
        />
      </div>
      <div
        className="tf-panel"
        style={{
          gap: 16,
        }}
      >
        <div className="tf-row">
          <span>Search</span>
          <Kbd keys={["⌘", "K"]} />
          <span>Approve</span>
          <Kbd keys={["A"]} />
          <Spinner />
          <Spinner size="lg" />
        </div>
        <Collapsible title="Advanced settings" meta="3 changed" defaultOpen>
          <KeyValue
            dense
            items={[
              ["Timeout", "30 s"],
              ["Retries", "3"],
            ]}
          />
        </Collapsible>
        <Collapsible title="Raw payload">Hidden until opened</Collapsible>
      </div>
    </div>
  );
}
```

## Props

### Collapsible

| Prop | Type | Notes |
| --- | --- | --- |
| `title` | `ReactNode` | Required |
| `meta?` | `ReactNode` |  |
| `defaultOpen?` | `boolean` |  |
| `open?` | `boolean` |  |
| `onOpenChange?` | `(open: boolean) => void` |  |
| `children?` | `ReactNode` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### Kbd

| Prop | Type | Notes |
| --- | --- | --- |
| `keys?` | `string[]` |  |
| `children?` | `ReactNode` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### KeyValue

| Prop | Type | Notes |
| --- | --- | --- |
| `items` | `KeyValueItem[]` | Required |
| `dense?` | `boolean` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### Spinner

| Prop | Type | Notes |
| --- | --- | --- |
| `size?` | `"lg"` |  |
| `label?` | `string` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### StatusIndicator

| Prop | Type | Notes |
| --- | --- | --- |
| `status` | `Status` | Required |
| `label?` | `ReactNode` |  |
| `size?` | `"sm"` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |
