Skip to content
Entangle UI v0.13.0

PanelSurface

A structured panel container using a compound component pattern with PanelSurface, PanelSurface.Header, PanelSurface.Body, and PanelSurface.Footer. Provides consistent chrome (border, background, header/footer sizing) for editor panels, tool windows, property inspectors, and sidebar sections.

Live Preview

import { PanelSurface } from 'entangle-ui';
<PanelSurface>
<PanelSurface.Header>Properties</PanelSurface.Header>
<PanelSurface.Body padding={8}>Panel content goes here</PanelSurface.Body>
</PanelSurface>

A typical panel consists of a Header, Body, and optionally a Footer. All sub-components are accessed as static properties of PanelSurface.

<PanelSurface>
<PanelSurface.Header>Panel Title</PanelSurface.Header>
<PanelSurface.Body padding={12}>
<p>Main content area</p>
</PanelSurface.Body>
<PanelSurface.Footer>
<Button size="sm">Apply</Button>
</PanelSurface.Footer>
</PanelSurface>

The size prop on the root PanelSurface controls the visual density of the header and footer chrome. It is shared via context to all sub-components.

<PanelSurface size="sm">
<PanelSurface.Header>Compact Panel</PanelSurface.Header>
<PanelSurface.Body>Content</PanelSurface.Body>
</PanelSurface>
<PanelSurface size="md">
<PanelSurface.Header>Standard Panel</PanelSurface.Header>
<PanelSurface.Body>Content</PanelSurface.Body>
</PanelSurface>
<PanelSurface size="lg">
<PanelSurface.Header>Spacious Panel</PanelSurface.Header>
<PanelSurface.Body>Content</PanelSurface.Body>
</PanelSurface>

| Size | Use case | | ---- | ------------------------------------------ | | sm | Compact tool windows and inline panels | | md | Standard property panels (default) | | lg | Prominent settings or configuration panels |

The bordered prop controls whether the panel has a visible border.

{
/* With border (default) */
}
<PanelSurface bordered>
<PanelSurface.Header>Bordered Panel</PanelSurface.Header>
<PanelSurface.Body>Content</PanelSurface.Body>
</PanelSurface>;
{
/* Without border */
}
<PanelSurface bordered={false}>
<PanelSurface.Header>Borderless Panel</PanelSurface.Header>
<PanelSurface.Body>Content</PanelSurface.Body>
</PanelSurface>;

Override the default panel background with any CSS color or gradient value.

<PanelSurface background="linear-gradient(180deg, #2f3442 0%, #1b202a 100%)">
<PanelSurface.Header>Gradient Panel</PanelSurface.Header>
<PanelSurface.Body>Content with gradient background</PanelSurface.Body>
</PanelSurface>

The PanelSurface.Header supports an actions slot for interactive elements positioned on the right side of the header.

<PanelSurface>
<PanelSurface.Header
actions={
<>
<IconButton icon={<SettingsIcon />} size="sm" />
<IconButton icon={<CloseIcon />} size="sm" />
</>
}
>
Inspector
</PanelSurface.Header>
<PanelSurface.Body padding={8}>Inspector content...</PanelSurface.Body>
</PanelSurface>

Enable scrolling for the body content when it overflows its container.

<PanelSurface style={{ height: '400px' }}>
<PanelSurface.Header>Scrollable Panel</PanelSurface.Header>
<PanelSurface.Body scroll padding={8}>
<div style={{ height: '800px' }}>
Long content that scrolls within the body...
</div>
</PanelSurface.Body>
</PanelSurface>

When scroll is false (the default), body overflow is hidden.

Control the inner padding of the body area. Accepts numbers (treated as pixels) or CSS strings.

<PanelSurface.Body padding={16}>
Content with 16px padding
</PanelSurface.Body>
<PanelSurface.Body padding="1rem 0.5rem">
Content with custom padding
</PanelSurface.Body>
<PanelSurface size="md" bordered>
<PanelSurface.Header
actions={<IconButton icon={<CloseIcon />} size="sm" variant="ghost" />}
>
Transform
</PanelSurface.Header>
<PanelSurface.Body scroll padding={8}>
<Stack spacing={2}>
<NumberInput label="Position X" value={0} />
<NumberInput label="Position Y" value={0} />
<NumberInput label="Position Z" value={0} />
<NumberInput label="Rotation" value={0} />
<NumberInput label="Scale" value={1} />
</Stack>
</PanelSurface.Body>
<PanelSurface.Footer>
<Button size="sm" variant="ghost">
Reset
</Button>
</PanelSurface.Footer>
</PanelSurface>
Prop Type Default Description
children ReactNode — Panel content. Typically PanelSurface.Header, PanelSurface.Body, and optionally PanelSurface.Footer.
size 'sm' | 'md' | 'lg' 'md' Visual density for header and footer chrome. Shared via context to sub-components.
bordered boolean true Whether to show a border around the panel.
background string — Custom background color or gradient. Defaults to the theme secondary background.
className string — Additional CSS class names.
style CSSProperties — Inline styles.
testId string — Test identifier for automated testing.
ref Ref<HTMLDivElement> — Ref to the root div element.
Prop Type Default Description
children ReactNode — Header content such as a title or label.
actions ReactNode — Action elements rendered on the right side of the header (e.g. icon buttons).
className string — Additional CSS class names.
style CSSProperties — Inline styles.
testId string — Test identifier for automated testing.
ref Ref<HTMLDivElement> — Ref to the header div element.
Prop Type Default Description
children ReactNode — Main panel content.
scroll boolean false Enables automatic overflow scrolling for the body area.
padding number | string 0 Inner padding of the body area. Numbers are treated as pixels.
className string — Additional CSS class names.
style CSSProperties — Inline styles.
testId string — Test identifier for automated testing.
ref Ref<HTMLDivElement> — Ref to the body div element.
Prop Type Default Description
children ReactNode — Footer content such as action buttons.
className string — Additional CSS class names.
style CSSProperties — Inline styles.
testId string — Test identifier for automated testing.
ref Ref<HTMLDivElement> — Ref to the footer div element.

All sub-components also accept standard HTML <div> attributes.

  • Renders semantic <div> elements for structural layout
  • Header content is wrapped in a <span> for text styling; actions are grouped separately
  • The component provides no implicit ARIA roles — add role and aria-label as needed for specific use cases (e.g. role="complementary" for a sidebar panel)
  • Use descriptive header text that clearly identifies the panel purpose for screen reader users