# Frame

Group raised panels inside a shared frame.

Frame with header, panel and footer

[Complete TSX file](/examples/frame/default.tsx)

```tsx
"use client";

import {
  Frame,
  FrameDescription,
  FrameFooter,
  FrameHeader,
  FramePanel,
  FrameTitle,
} from "@/siteplane/components/frame";

export default function Example() {
  return (
    <Frame className="w-full max-w-md">
      <FrameHeader>
        <FrameTitle>Plan</FrameTitle>
        <FrameDescription>Your subscription and renewal date.</FrameDescription>
      </FrameHeader>
      <FramePanel>
        <FrameTitle>
          <h3>Pro plan</h3>
        </FrameTitle>
        <FrameDescription>
          $20 per month, renews on October 1, 2026.
        </FrameDescription>
      </FramePanel>
      <FrameFooter>
        <FrameDescription>
          Plan changes take effect on your next billing date.
        </FrameDescription>
      </FrameFooter>
    </Frame>
  );
}
```

## Installation

Complete [one-time setup](/docs/installation/) first.

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/frame
```

With npm: `npx shadcn@4.18.0 add @siteplane/frame`. [Registry JSON](/registry/frame.json) lists source files and dependencies.

For this page’s examples, also install:

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/separator
```

## Usage

```tsx
import { Frame, FramePanel } from "@/siteplane/components/frame";

<Frame>
  <FramePanel>Content</FramePanel>
</Frame>;
```

## Composition

```text
Frame
├── FrameHeader
│   ├── FrameTitle
│   └── FrameDescription
├── FramePanel
└── FrameFooter
```

## Separated panels

Place several `FramePanel` parts directly inside `Frame`; adjacent panels are spaced apart automatically.

Frame with separated panels

[Complete TSX file](/examples/frame/sections.tsx)

```tsx
"use client";

import {
  Frame,
  FrameDescription,
  FrameHeader,
  FramePanel,
  FrameTitle,
} from "@/siteplane/components/frame";

export default function Example() {
  return (
    <Frame className="w-full max-w-md">
      <FrameHeader>
        <FrameTitle>Workspace usage</FrameTitle>
        <FrameDescription>Current billing period.</FrameDescription>
      </FrameHeader>
      <FramePanel>
        <FrameTitle>
          <h3>Members</h3>
        </FrameTitle>
        <FrameDescription>12 of 20 seats in use.</FrameDescription>
      </FramePanel>
      <FramePanel>
        <FrameTitle>
          <h3>Storage</h3>
        </FrameTitle>
        <FrameDescription>4.2 GB of 10 GB used.</FrameDescription>
      </FramePanel>
    </Frame>
  );
}
```

## Stacked sections

To stack sections inside one panel, remove the panel padding and divide the sections with a `Separator`.

Frame with stacked sections

[Complete TSX file](/examples/frame/settings-panel.tsx)

```tsx
"use client";

import {
  Frame,
  FrameDescription,
  FrameHeader,
  FramePanel,
  FrameTitle,
} from "@/siteplane/components/frame";
import { Separator } from "@/siteplane/components/separator";

export default function Example() {
  return (
    <Frame className="w-full max-w-md">
      <FrameHeader>
        <FrameTitle>Payment details</FrameTitle>
        <FrameDescription>Used for your monthly invoices.</FrameDescription>
      </FrameHeader>
      <FramePanel className="p-0">
        <div className="p-5">
          <FrameTitle>
            <h3>Payment method</h3>
          </FrameTitle>
          <FrameDescription>
            Card ending in 4242, expires 08/2028.
          </FrameDescription>
        </div>
        <Separator />
        <div className="p-5">
          <FrameTitle>
            <h3>Billing contact</h3>
          </FrameTitle>
          <FrameDescription>
            Invoices are sent to billing@example.com.
          </FrameDescription>
        </div>
      </FramePanel>
    </Frame>
  );
}
```

## API reference

All parts accept native attributes, refs, children and string className. `Frame` is a div with a muted background, rounded corners and padding; `FramePanel` is a padded card surface with the same edge as [Card](/docs/components/card/#edge-and-background); `FrameHeader`, `FrameTitle`, `FrameDescription` and `FrameFooter` render div, so a page with many frames adds no landmarks. There are no owned size, variant or state props. Use native headings within the title where needed; FrameTitle does not create one.

[Read the installed source](/source/frame).

## Usage notes

Frame owns presentation only. Use [Card](/docs/components/card/) for a card with its own header, content and actions, or CardFrame for cards joined within a surrounding surface.

A panel is lighter than the muted frame around it. It draws the same hairline as a Card and adds no border or shadow of its own.
