<!-- Protocore Design System — Panel -->
# Panel

- **Category:** Layout (`layout`)
- **Slug:** `layout/panel`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { Panel } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/layout/panel

> A dense bordered console surface with an optional labelled header row and hairline-divided sub-sections.

## When to use it

`Panel` is the **console** surface: dense, bordered, mono-labelled, radius-0 — for operator UIs, config readouts, and dashboards where information density matters more than warmth. Reach for `Card` instead on marketing and content surfaces, where the tone is softer and the header carries a sans title/subtitle. Panel's header is a mono uppercase micro-label plus an actions slot; Card's is a titled block. Use `Panel.Section` to carve the body into labelled bands rather than dropping in bare `Divider`s — the sections handle the seams for you.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `actions` | `ReactNode` | no | — | Actions slot pinned to the right of the header row (e.g. buttons). |
| `children` | `ReactNode` | no | — | Panel body content. |
| `className` | `string` | no | — | — |
| `label` | `ReactNode` | no | — | Optional mono UPPERCASE label rendered in the header row over a bottom hairline. |
| `style` | `CSSProperties` | no | — | — |

## Examples

### Basics

A `Panel` is a hairline-bordered surface. Give it a `label` for a mono uppercase header row over a bottom hairline, and put content in the body.

```tsx
import { Panel, Text } from "@protocore/pds";

export default function PanelBasics() {
  return (
    <div style={{ maxWidth: 420 }}>
      <Panel label="Node status">
        <Text mono size="sm">
          height ....... 8,241,003
        </Text>
        <Text mono size="sm">
          peers ........ 1,284
        </Text>
        <Text mono size="sm">
          version ...... v2.4.1
        </Text>
      </Panel>
    </div>
  );
}
```

### Sections and actions

Pin controls to the header via `actions`, and divide the body into labelled `Panel.Section`s — consecutive sections separate with a hairline.

```tsx
import { Panel, Button, Text } from "@protocore/pds";

export default function PanelSectionsActions() {
  return (
    <div style={{ maxWidth: 420 }}>
      <Panel
        label="Deploy · relay-eu"
        actions={
          <Button variant="ghost" size="sm">
            Restart
          </Button>
        }
      >
        <Panel.Section label="Image">
          <Text mono size="sm">
            registry.protocore.io/relay:2.4.1
          </Text>
        </Panel.Section>
        <Panel.Section label="Resources">
          <Text mono size="sm">
            2 vCPU · 4 GiB · eu-central-1
          </Text>
        </Panel.Section>
      </Panel>
    </div>
  );
}
```

## Do & don't

**Do**

- Use Panel for operator and console surfaces where density is the point.
- Split the body into Panel.Sections rather than hand-placing dividers.
- Keep the label a short mono uppercase micro-heading.

**Don't**

- Use Panel where a warmer Card is the right register (marketing, content).
- Add manual Dividers between Panel.Sections — they already separate.
- Put long sans prose in a Panel; its idiom is dense, mono, tabular.

## Accessibility

**Notes**

- Renders a `<section>`; its header label is visible text, not an accessible name — add `aria-label`/`aria-labelledby` if the region should be a named landmark.
- Actions in the header are ordinary controls and follow normal focus order.

## Related

`card`, `section`, `sidebar`, `divider`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
