Panel

A foundational background component for creating theme-aware panels with support for light and dark modes. The Panel component provides surface and accent background styles, semantic feedback colors, interactive states, and extensive customization options for building cards, sections, and container elements.

Background Styles

Panel supports multiple background styles to fit different design needs: surface (primary application background), sunken (recessed background for wells and sidebars), elevated (with shadow), and transparent (no background). Use the translucent prop to add a frosted glass effect.

Surface

Standard background — the primary surface color for the application.

Sunken

Recessed background used for wells, sidebars, or secondary areas.

Elevated

Raised appearance with a shadow, drawing attention to the panel.

Transparent

No background — inherits from its parent container.

Translucent

Frosted Glass Effect

This translucent panel has a frosted glass effect with backdrop blur. Notice how the colorful shapes behind it are visible but blurred.

---
import Panel from "../Panel.astro";
import { css } from "@pindoba/styled-system/css";
import { stack } from "@pindoba/styled-system/patterns";
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
  })}
>
  <!-- Surface -->
  <div>
    <h3>Surface</h3>
    <Panel background="surface" padding="lg">
      <p>
        Standard background — the primary surface color for the application.
      </p>
    </Panel>
  </div>

  <!-- Sunken -->
  <div>
    <h3>Sunken</h3>
    <Panel background="sunken" padding="lg">
      <p>Recessed background used for wells, sidebars, or secondary areas.</p>
    </Panel>
  </div>

  <!-- Elevated -->
  <div>
    <h3>Elevated</h3>
    <Panel background="elevated" padding="lg">
      <p>Raised appearance with a shadow, drawing attention to the panel.</p>
    </Panel>
  </div>

  <!-- Transparent -->
  <div>
    <h3>Transparent</h3>
    <Panel background="transparent" padding="lg" border="default">
      <p>No background — inherits from its parent container.</p>
    </Panel>
  </div>

  <!-- Translucent -->
  <div>
    <h3>Translucent</h3>
    <div
      class={css({
        position: "relative",
        padding: "md",
        borderRadius: "md",
        overflow: "hidden",
        background:
          "linear-gradient(135deg, token(colors.primary) 0%, token(colors.primary.surface) 50%, token(colors.primary) 100%)",
      })}
    >
      <!-- Decorative SVG shapes in background -->
      <svg
        class={css({
          position: "absolute",
          top: "0",
          left: "0",
          width: "full",
          height: "full",
        })}
        xmlns="http://www.w3.org/2000/svg"
      >
        <circle cx="20%" cy="30%" r="60" fill="var(--colors-primary-surface)"
        ></circle>
        <circle
          cx="80%"
          cy="60%"
          r="80"
          fill="var(--colors-primary-border-muted)"></circle>
        <rect
          x="40%"
          y="10%"
          width="100"
          height="100"
          fill="var(--colors-primary-border)"
          rx="15"></rect>
        <polygon
          points="70,20 90,60 50,60"
          fill="var(--colors-primary)"
          transform="translate(200, 80)"></polygon>
        <circle cx="60%" cy="80%" r="50" fill="var(--colors-primary-hover)"
        ></circle>
        <rect
          x="10%"
          y="70%"
          width="80"
          height="80"
          fill="var(--colors-primary-active)"
          rx="20"></rect>
      </svg>

      <Panel
        translucent
        padding="md"
        radius="xs"
        class={css({ position: "relative", zIndex: "1" })}
      >
        <p><strong>Frosted Glass Effect</strong></p>
        <p>
          This translucent panel has a frosted glass effect with backdrop blur.
          Notice how the colorful shapes behind it are visible but blurred.
        </p>
      </Panel>
    </div>
  </div>
</div>

Feedback Colors

Use semantic feedback colors to convey meaning and context. Panels default to a neutral (gray) color palette and support all background options (surface, sunken, elevated, transparent). Feedback colors (primary, success, warning, danger) support surface for a tinted background and accent for a full-color (500) background — the sunken option is not available for feedback colors per the color architecture.

Primary

Emphasis Primary

colorPalette.surface — palette-aware tinted background.

Emphasis Secondary

neutral.surface — always neutral regardless of feedback.

Accent

Full-color primary (500) background with contrast text.

Success

Emphasis Primary

colorPalette.surface — palette-aware tinted background.

Emphasis Secondary

neutral.surface — always neutral regardless of feedback.

Accent

Full-color success (500) background with contrast text.

Warning

Emphasis Primary

colorPalette.surface — palette-aware tinted background.

Emphasis Secondary

neutral.surface — always neutral regardless of feedback.

Accent

Full-color warning (500) background with contrast text.

Danger

Emphasis Primary

colorPalette.surface — palette-aware tinted background.

Emphasis Secondary

neutral.surface — always neutral regardless of feedback.

Accent

Full-color danger (500) background with contrast text.

---
import Panel from "../Panel.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
    width: "100%",
  })}
>
  <!--
    Feedback colors: surface (tinted), emphasis primary (colorPalette.surface),
    emphasis secondary (neutral.surface), and accent: true (full 500 color).
    Sunken is not supported for feedback colors per the color architecture.
  -->
  <div>
    <h3>Primary</h3>
    <div class={stack({ gap: "md", direction: "column", width: "100%" })}>
      <Panel
        feedback="primary"
        emphasis="primary"
        padding="lg"
        border="default"
      >
        <p><strong>Emphasis Primary</strong></p>
        <p>colorPalette.surface — palette-aware tinted background.</p>
      </Panel>
      <Panel
        feedback="primary"
        emphasis="secondary"
        padding="lg"
        border="default"
      >
        <p><strong>Emphasis Secondary</strong></p>
        <p>neutral.surface — always neutral regardless of feedback.</p>
      </Panel>
      <Panel feedback="primary" background="surface" accent={true} padding="lg">
        <p><strong>Accent</strong></p>
        <p>Full-color primary (500) background with contrast text.</p>
      </Panel>
    </div>
  </div>

  <div>
    <h3>Success</h3>
    <div class={stack({ gap: "md", direction: "column", width: "100%" })}>
      <Panel
        feedback="success"
        emphasis="primary"
        padding="lg"
        border="default"
      >
        <p><strong>Emphasis Primary</strong></p>
        <p>colorPalette.surface — palette-aware tinted background.</p>
      </Panel>
      <Panel
        feedback="success"
        emphasis="secondary"
        padding="lg"
        border="default"
      >
        <p><strong>Emphasis Secondary</strong></p>
        <p>neutral.surface — always neutral regardless of feedback.</p>
      </Panel>
      <Panel feedback="success" background="surface" accent={true} padding="lg">
        <p><strong>Accent</strong></p>
        <p>Full-color success (500) background with contrast text.</p>
      </Panel>
    </div>
  </div>

  <div>
    <h3>Warning</h3>
    <div class={stack({ gap: "md", direction: "column", width: "100%" })}>
      <Panel
        feedback="warning"
        emphasis="primary"
        padding="lg"
        border="default"
      >
        <p><strong>Emphasis Primary</strong></p>
        <p>colorPalette.surface — palette-aware tinted background.</p>
      </Panel>
      <Panel
        feedback="warning"
        emphasis="secondary"
        padding="lg"
        border="default"
      >
        <p><strong>Emphasis Secondary</strong></p>
        <p>neutral.surface — always neutral regardless of feedback.</p>
      </Panel>
      <Panel feedback="warning" background="surface" accent={true} padding="lg">
        <p><strong>Accent</strong></p>
        <p>Full-color warning (500) background with contrast text.</p>
      </Panel>
    </div>
  </div>

  <div>
    <h3>Danger</h3>
    <div class={stack({ gap: "md", direction: "column", width: "100%" })}>
      <Panel feedback="danger" emphasis="primary" padding="lg" border="default">
        <p><strong>Emphasis Primary</strong></p>
        <p>colorPalette.surface — palette-aware tinted background.</p>
      </Panel>
      <Panel
        feedback="danger"
        emphasis="secondary"
        padding="lg"
        border="default"
      >
        <p><strong>Emphasis Secondary</strong></p>
        <p>neutral.surface — always neutral regardless of feedback.</p>
      </Panel>
      <Panel feedback="danger" background="surface" accent={true} padding="lg">
        <p><strong>Accent</strong></p>
        <p>Full-color danger (500) background with contrast text.</p>
      </Panel>
    </div>
  </div>
</div>

Border Styles

Choose between different border styles to control the visual weight of panel borders. Use border="none" for no border, border="default" for a standard border, border="bold" for stronger emphasis using a bolder color, or border="muted" for subtle visual separation. Borders use box-shadow so they are layout-neutral — they do not affect element dimensions and compose automatically with elevation shadows.

None

No Border

Use border="none" for no border.

Default

Default Border

Standard border using the neutral border token.

Bold

Bold Border

Stronger border weight for greater visual emphasis.

Muted

Muted Border

Lighter border for subtle visual separation.

Border Styles with Feedback Colors

Primary with Default Border

Success with Default Border

Warning with Bold Border

Danger with Muted Border

---
import Panel from "../Panel.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
    width: "full",
  })}
>
  <!-- No Border -->
  <div>
    <h3>None</h3>
    <Panel background="surface" padding="lg" border="none">
      <p><strong>No Border</strong></p>
      <p>Use <code>border="none"</code> for no border.</p>
    </Panel>
  </div>

  <!-- Default Border -->
  <div>
    <h3>Default</h3>
    <Panel background="surface" padding="lg" border="default">
      <p><strong>Default Border</strong></p>
      <p>Standard border using the neutral border token.</p>
    </Panel>
  </div>

  <!-- Bold Border -->
  <div>
    <h3>Bold</h3>
    <Panel background="surface" padding="lg" border="bold">
      <p><strong>Bold Border</strong></p>
      <p>Stronger border weight for greater visual emphasis.</p>
    </Panel>
  </div>

  <!-- Muted Border -->
  <div>
    <h3>Muted</h3>
    <Panel background="surface" padding="lg" border="muted">
      <p><strong>Muted Border</strong></p>
      <p>Lighter border for subtle visual separation.</p>
    </Panel>
  </div>

  <!-- Bordered with Feedback Colors -->
  <div>
    <h3>Border Styles with Feedback Colors</h3>
    <div class={stack({ gap: "md", direction: "column" })}>
      <Panel feedback="primary" padding="md" border="default">
        <p><strong>Primary with Default Border</strong></p>
      </Panel>
      <Panel feedback="success" padding="md" border="default">
        <p><strong>Success with Default Border</strong></p>
      </Panel>
      <Panel feedback="warning" padding="md" border="bold">
        <p><strong>Warning with Bold Border</strong></p>
      </Panel>
      <Panel feedback="danger" padding="md" border="muted">
        <p><strong>Danger with Muted Border</strong></p>
      </Panel>
    </div>
  </div>
</div>

Interactive Panels

Enable interactive hover states for clickable panels using the interactive prop. Elevated panels lift with enhanced shadows. Accent panels transition through the colorPalette hover and active tokens.

Surface

Click me!

This panel has hover effects. Clicked 0 times.

Elevated

Elevated

Hover to see the enhanced shadow.

Translucent

Frosted Glass with Hover

Hover to see the interactive state.

Feedback Colors

Primary

Primary Surface Panel

Hover to see the tinted surface interactive state.

Primary Emphasis Secondary Panel

neutral.surface — always neutral regardless of feedback.

Primary Accent Panel

Full-color accent background with contrast text.

Success

Success Surface Panel

Hover to see the tinted surface interactive state.

Success Emphasis Secondary Panel

neutral.surface — always neutral regardless of feedback.

Success Accent Panel

Full-color accent background with contrast text.

Warning

Warning Surface Panel

Hover to see the tinted surface interactive state.

Warning Emphasis Secondary Panel

neutral.surface — always neutral regardless of feedback.

Warning Accent Panel

Full-color accent background with contrast text.

Danger

Danger Surface Panel

Hover to see the tinted surface interactive state.

Danger Emphasis Secondary Panel

neutral.surface — always neutral regardless of feedback.

Danger Accent Panel

Full-color accent background with contrast text.

---
import Panel from "../Panel.astro";
import { stack } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
    width: "full",
  })}
>
  <!-- Interactive Surface Panel -->
  <div>
    <h3>Surface</h3>
    <Panel
      background="surface"
      padding="lg"
      interactive
      id="surface-panel"
      style="cursor: pointer;"
    >
      <p><strong>Click me!</strong></p>
      <p>
        This panel has hover effects. Clicked <span id="click-count">0</span> times.
      </p>
    </Panel>
  </div>

  <!-- Interactive Elevated Panel -->
  <div>
    <h3>Elevated</h3>
    <Panel
      background="elevated"
      padding="lg"
      interactive
      style="cursor: pointer;"
      onclick="console.log('Elevated panel clicked')"
    >
      <p><strong>Elevated</strong></p>
      <p>Hover to see the enhanced shadow.</p>
    </Panel>
  </div>

  <!-- Interactive Translucent Panel -->
  <div>
    <h3>Translucent</h3>
    <div
      class={css({
        position: "relative",
        padding: "md",
        borderRadius: "md",
        overflow: "hidden",
        background:
          "linear-gradient(135deg, token(colors.primary) 0%, token(colors.primary.surface) 50%, token(colors.primary) 100%)",
      })}
    >
      <!-- Decorative SVG shapes in background -->
      <svg
        class={css({
          position: "absolute",
          top: "0",
          left: "0",
          width: "full",
          height: "full",
        })}
        xmlns="http://www.w3.org/2000/svg"
      >
        <circle cx="20%" cy="30%" r="60" fill="var(--colors-primary-surface)"
        ></circle>
        <circle
          cx="80%"
          cy="60%"
          r="80"
          fill="var(--colors-primary-border-muted)"></circle>
        <rect
          x="40%"
          y="10%"
          width="100"
          height="100"
          fill="var(--colors-primary-border)"
          rx="15"></rect>
        <polygon
          points="70,20 90,60 50,60"
          fill="var(--colors-primary)"
          transform="translate(200, 80)"></polygon>
        <circle cx="60%" cy="80%" r="50" fill="var(--colors-primary-hover)"
        ></circle>
        <rect
          x="10%"
          y="70%"
          width="80"
          height="80"
          fill="var(--colors-primary-active)"
          rx="20"></rect>
      </svg>

      <Panel
        translucent
        padding="md"
        radius="xs"
        interactive
        class={css({ position: "relative", zIndex: "1", cursor: "pointer" })}
        onclick="console.log('Translucent panel clicked')"
      >
        <p><strong>Frosted Glass with Hover</strong></p>
        <p>Hover to see the interactive state.</p>
      </Panel>
    </div>
  </div>

  <!-- Interactive Feedback Panel -->
  <div>
    <h3>Feedback Colors</h3>
    <div class={stack({ gap: "xl", direction: "column" })}>
      <!-- Primary -->
      <div>
        <h4>Primary</h4>
        <div class={stack({ gap: "md", direction: "column" })}>
          <Panel
            feedback="primary"
            background="surface"
            padding="lg"
            interactive
            border="default"
            style="cursor: pointer;"
            onclick="console.log('Primary action triggered')"
          >
            <p><strong>Primary Surface Panel</strong></p>
            <p>Hover to see the tinted surface interactive state.</p>
          </Panel>
          <Panel
            feedback="primary"
            emphasis="secondary"
            padding="lg"
            interactive
            border="default"
            style="cursor: pointer;"
            onclick="console.log('Primary emphasis secondary action')"
          >
            <p><strong>Primary Emphasis Secondary Panel</strong></p>
            <p>neutral.surface — always neutral regardless of feedback.</p>
          </Panel>
          <Panel
            feedback="primary"
            background="surface"
            accent={true}
            padding="lg"
            interactive
            style="cursor: pointer;"
            onclick="console.log('Primary accent action')"
          >
            <p><strong>Primary Accent Panel</strong></p>
            <p>Full-color accent background with contrast text.</p>
          </Panel>
        </div>
      </div>

      <!-- Success -->
      <div>
        <h4>Success</h4>
        <div class={stack({ gap: "md", direction: "column" })}>
          <Panel
            feedback="success"
            background="surface"
            padding="lg"
            interactive
            border="default"
            style="cursor: pointer;"
            onclick="console.log('Success action triggered')"
          >
            <p><strong>Success Surface Panel</strong></p>
            <p>Hover to see the tinted surface interactive state.</p>
          </Panel>
          <Panel
            feedback="success"
            emphasis="secondary"
            padding="lg"
            interactive
            border="default"
            style="cursor: pointer;"
            onclick="console.log('Success emphasis secondary action')"
          >
            <p><strong>Success Emphasis Secondary Panel</strong></p>
            <p>neutral.surface — always neutral regardless of feedback.</p>
          </Panel>
          <Panel
            feedback="success"
            background="surface"
            accent={true}
            padding="lg"
            interactive
            style="cursor: pointer;"
            onclick="console.log('Success accent action')"
          >
            <p><strong>Success Accent Panel</strong></p>
            <p>Full-color accent background with contrast text.</p>
          </Panel>
        </div>
      </div>

      <!-- Warning -->
      <div>
        <h4>Warning</h4>
        <div class={stack({ gap: "md", direction: "column" })}>
          <Panel
            feedback="warning"
            background="surface"
            padding="lg"
            interactive
            border="default"
            style="cursor: pointer;"
            onclick="console.log('Warning action triggered')"
          >
            <p><strong>Warning Surface Panel</strong></p>
            <p>Hover to see the tinted surface interactive state.</p>
          </Panel>
          <Panel
            feedback="warning"
            emphasis="secondary"
            padding="lg"
            interactive
            border="default"
            style="cursor: pointer;"
            onclick="console.log('Warning emphasis secondary action')"
          >
            <p><strong>Warning Emphasis Secondary Panel</strong></p>
            <p>neutral.surface — always neutral regardless of feedback.</p>
          </Panel>
          <Panel
            feedback="warning"
            background="surface"
            accent={true}
            padding="lg"
            interactive
            style="cursor: pointer;"
            onclick="console.log('Warning accent action')"
          >
            <p><strong>Warning Accent Panel</strong></p>
            <p>Full-color accent background with contrast text.</p>
          </Panel>
        </div>
      </div>

      <!-- Danger -->
      <div>
        <h4>Danger</h4>
        <div class={stack({ gap: "md", direction: "column" })}>
          <Panel
            feedback="danger"
            background="surface"
            padding="lg"
            interactive
            border="default"
            style="cursor: pointer;"
            onclick="console.log('Danger action triggered')"
          >
            <p><strong>Danger Surface Panel</strong></p>
            <p>Hover to see the tinted surface interactive state.</p>
          </Panel>
          <Panel
            feedback="danger"
            emphasis="secondary"
            padding="lg"
            interactive
            border="default"
            style="cursor: pointer;"
            onclick="console.log('Danger emphasis secondary action')"
          >
            <p><strong>Danger Emphasis Secondary Panel</strong></p>
            <p>neutral.surface — always neutral regardless of feedback.</p>
          </Panel>
          <Panel
            feedback="danger"
            background="surface"
            accent={true}
            padding="lg"
            interactive
            style="cursor: pointer;"
            onclick="console.log('Danger accent action')"
          >
            <p><strong>Danger Accent Panel</strong></p>
            <p>Full-color accent background with contrast text.</p>
          </Panel>
        </div>
      </div>
    </div>
  </div>
</div>

<script>
  const panel = document.getElementById("surface-panel");
  const countEl = document.getElementById("click-count");
  if (panel && countEl) {
    let count = 0;
    panel.addEventListener("click", () => {
      count++;
      countEl.textContent = String(count);
    });
  }
</script>

Padding

Control the internal spacing of a panel using the padding prop. Panels default to md padding.

No padding

Small padding

Medium padding (default)

Large padding

---
import Panel from "../Panel.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "md", direction: "column", width: "full" })}>
  <Panel background="elevated" padding="none" border="default">
    <p>No padding</p>
  </Panel>
  <Panel background="elevated" padding="sm" border="default">
    <p>Small padding</p>
  </Panel>
  <Panel background="elevated" padding="md" border="default">
    <p>Medium padding (default)</p>
  </Panel>
  <Panel background="elevated" padding="lg" border="default">
    <p>Large padding</p>
  </Panel>
</div>

Border Radius

Control corner rounding with the radius prop. Ranges from none to full.

No border radius

Small border radius

Medium border radius

Large border radius

Extra large border radius (default)

Full border radius

---
import Panel from "../Panel.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "md", direction: "column", width: "full" })}>
  <Panel background="sunken" padding="md" radius="none" border="bold">
    <p>No border radius</p>
  </Panel>
  <Panel background="sunken" padding="md" radius="sm" border="bold">
    <p>Small border radius</p>
  </Panel>
  <Panel background="sunken" padding="md" radius="md" border="bold">
    <p>Medium border radius</p>
  </Panel>
  <Panel background="sunken" padding="md" radius="lg" border="bold">
    <p>Large border radius</p>
  </Panel>
  <Panel background="sunken" padding="md" radius="xl" border="bold">
    <p>Extra large border radius (default)</p>
  </Panel>
  <Panel background="sunken" padding="md" radius="full" border="bold">
    <p>Full border radius</p>
  </Panel>
</div>

Nesting

Padding and radius tokens share the same numeric scale, enabling proportional nesting: the outer panel’s radius should equal the inner panel’s radius plus the padding (outer = inner + padding). With the defaults (radius="xl" and padding="md"), inner panels naturally want radius="xs" — making xs the natural base radius for components nested inside a panel.

xl − md = xs

2xl − md = sm

3xl − md = md

4xl − md = lg

5xl − md = xl

6xl − md = 2xl

7xl − md = 3xl

---
import Panel from "../Panel.astro";
import { stack, grid } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
---

<div class={stack({ gap: "xl", direction: "column", width: "full" })}>
  <!-- xl − md = xs (default) -->
  <Panel padding="md" radius="xl" border="bold">
    <Panel background="sunken" padding="md" radius="xs" border="bold">
      <p class={css({ fontSize: "sm", color: "fg.subtle" })}>xl − md = xs</p>
    </Panel>
  </Panel>

  <!-- 2xl − md = sm -->
  <Panel padding="md" radius="2xl" border="bold">
    <Panel background="sunken" padding="md" radius="sm" border="bold">
      <p class={css({ fontSize: "sm", color: "fg.subtle" })}>2xl − md = sm</p>
    </Panel>
  </Panel>

  <!-- 3xl − md = md -->
  <Panel padding="md" radius="3xl" border="bold">
    <Panel background="sunken" padding="md" radius="md" border="bold">
      <p class={css({ fontSize: "sm", color: "fg.subtle" })}>3xl − md = md</p>
    </Panel>
  </Panel>

  <!-- Compact grid: 4 per row -->
  <div class={grid({ columns: 2, gap: "md" })}>
    <Panel padding="md" radius="4xl" border="bold">
      <Panel background="sunken" padding="sm" radius="lg" border="bold">
        <p class={css({ fontSize: "sm", color: "fg.subtle" })}>4xl − md = lg</p>
      </Panel>
    </Panel>

    <Panel padding="md" radius="5xl" border="bold">
      <Panel background="sunken" padding="sm" radius="xl" border="bold">
        <p class={css({ fontSize: "sm", color: "fg.subtle" })}>5xl − md = xl</p>
      </Panel>
    </Panel>

    <Panel padding="md" radius="6xl" border="bold">
      <Panel background="sunken" padding="sm" radius="2xl" border="bold">
        <p class={css({ fontSize: "sm", color: "fg.subtle" })}>
          6xl − md = 2xl
        </p>
      </Panel>
    </Panel>

    <Panel padding="md" radius="7xl" border="bold">
      <Panel background="sunken" padding="sm" radius="3xl" border="bold">
        <p class={css({ fontSize: "sm", color: "fg.subtle" })}>
          7xl − md = 3xl
        </p>
      </Panel>
    </Panel>
  </div>
</div>

Custom Styling

The passThrough prop provides two escape hatches for advanced customization: style accepts any Panda CSS SystemStyleObject applied directly to the panel root, and props forwards arbitrary HTML attributes. Use style for layout overrides like maxWidth or responsive constraints, and props for accessibility attributes like role, aria-label, or aria-live.

Custom Width

Centered with Max Width

Use passThrough.root.style to apply Panda CSS styles directly to the panel root — here constraining width and centering the panel.

Panel as Card

Delete workspace

This action cannot be undone. All data will be permanently removed.

Accessible Alert

---
import Panel from "../Panel.astro";
import Button from "@pindoba/astro-button";
import { css } from "@pindoba/styled-system/css";
import { stack, flex } from "@pindoba/styled-system/patterns";
---

<div
  class={stack({
    gap: "xl",
    direction: "column",
  })}
>
  <!-- Custom Width via PassThrough -->
  <div>
    <h3>Custom Width</h3>
    <Panel
      background="elevated"
      padding="lg"
      passThrough={{
        root: {
          style: css.raw({
            maxWidth: "480px",
            margin: "0 auto",
          }),
        },
      }}
    >
      <p><strong>Centered with Max Width</strong></p>
      <p>
        Use <code>passThrough.root.style</code> to apply Panda CSS styles directly
        to the panel root — here constraining width and centering the panel.
      </p>
    </Panel>
  </div>

  <!-- Panel as Card with Action -->
  <div>
    <h3>Panel as Card</h3>
    <Panel background="elevated" padding="lg" border="default">
      <div class={stack({ gap: "md" })}>
        <div>
          <h4 class={css({ margin: "0", marginBottom: "2xs" })}>
            Delete workspace
          </h4>
          <p class={css({ margin: "0", color: "fg.subtle", fontSize: "md" })}>
            This action cannot be undone. All data will be permanently removed.
          </p>
        </div>
        <div class={flex({ gap: "sm", justify: "flex-end" })}>
          <Button emphasis="secondary" background="sunken">Cancel</Button>
          <Button emphasis="primary" feedback="danger">Delete</Button>
        </div>
      </div>
    </Panel>
  </div>

  <!-- Panel with ARIA Attributes -->
  <div>
    <h3>Accessible Alert</h3>
    <Panel
      background="surface"
      feedback="warning"
      padding="lg"
      border="default"
      passThrough={{
        root: {
          props: {
            role: "alert",
            "aria-live": "polite",
            "aria-label": "Session expiry warning",
          },
        },
      }}
    >
      <p><strong>Your session expires in 5 minutes</strong></p>
      <p>
        Use <code>passThrough.root.props</code> to set HTML attributes — here
        <code>role="alert"</code> and <code>aria-live="polite"</code> for screen reader
        announcements.
      </p>
    </Panel>
  </div>
</div>

Props

Prop
background
background

Visual background style of the panel. Neutral feedback supports all options; accent colors only support surface, elevated, and transparent (sunken is not available for accent colors).

Type "surface" | "sunken" | "elevated" | "transparent"
Default "surface"
Required No
accent
accent

Use the full-color (500) accent background from the current feedback color with contrast text. When false (default), accent feedback colors use a tinted surface background instead.

Type boolean
Default false
Required No
emphasis
emphasis

Controls the visual weight of the panel background. primary uses colorPalette.surface — a palette-aware tinted background that responds to the feedback color. secondary uses neutral.surface — always neutral regardless of feedback, providing a consistent low-emphasis container.

Type "primary" | "secondary"
Default undefined
Required No
translucent
translucent

Apply a frosted glass effect with backdrop blur. Works with surface and elevated backgrounds.

Type boolean
Default false
Required No
feedback
feedback

Semantic feedback color scheme. When omitted, the panel uses the neutral (gray) color palette. Providing a feedback color (primary, success, warning, danger) applies the corresponding color tokens.

Type "primary" | "success" | "warning" | "danger"
Default undefined
Required No
padding
padding

Internal padding size. Accepts the full spacing scale from none to 11xl.

Type "none" | "5xs" | "4xs" | "3xs" | "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | "6xl" | "7xl" | "8xl" | "9xl" | "10xl" | "11xl"
Default "md"
Required No
radius
radius

Border radius size. Accepts the full spacing scale from none to 11xl, plus full for fully rounded corners.

Type "none" | "5xs" | "4xs" | "3xs" | "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | "6xl" | "7xl" | "8xl" | "9xl" | "10xl" | "11xl" | "full"
Default "xl"
Required No
border
border

Box-shadow ring border. none: no border. default: standard border. bold: stronger emphasis using a bolder color. muted: subtle separation. Uses box-shadow so it does not affect layout dimensions and composes with elevation shadows.

Type "none" | "default" | "bold" | "muted"
Default "none"
Required No
interactive
interactive

Enable hover and active effects with cursor pointer. Elevated panels gain a lift effect on hover.

Type boolean
Default false
Required No
passThrough
passThrough

Custom styling and props for panel elements

Type { root?: { style?: SystemStyleObject; props?: HTMLAttributes<HTMLDivElement> & Record<string, unknown> } }
Default undefined
Required No
...rest
...rest

Standard HTML div attributes

Type HTMLAttributes<HTMLDivElement>
Default -
Required No