CentercodeDitto
DittoPorygonAPI

PropertyPanel

Persistent right-side editing panel for design tools

When to Use

A fixed-width side panel for editing selected items while keeping the main canvas visible.

Use When

  • • Editing block properties in a visual builder
  • • Inspecting selected items while canvas stays visible
  • • Need permanent side panel that doesn't overlay content

Skip When

  • • No persistent selection model (use overlay mode for forms)

Size Variants

Choose normal for compact properties, wide for rich editing controls.

SizeWidthUse Case
normal448pxSimple properties, minimal controls
wide512pxRich editing, multiple sections

Full Mode

Provide title, description, and children. Panel handles header, scrolling, and footer automatically.

Main Content Area

PropertyPanel stays visible while editing

Block Properties

Configure the selected block

Basic Settings

Advanced Options

Container Mode

Use subcomponents directly when you need full control over layout and structure.

Main Content Area

Custom Header

Content provides its own structure

In container mode, the panel is just a styled wrapper. Your content handles its own header, scrolling, and footer.

Empty State

Show when nothing is selected or when selection has no editable properties.

Show empty state:

Main Content Area

Properties

Basic Settings

This content shows when isEmpty is false

PropertyPanelFooter

Standardized footer with enforced button patterns. Uses action props instead of children for consistent styling and layout.

Layout Rules

1 action: [Primary 100%]

2 actions: [Secondary 50%][Primary 50%]

3 actions: [Delete 33%][Secondary 33%][Primary 33%]

Two-button layout (Secondary + Primary)

Most common pattern: Cancel and Save actions.

<PropertyPanelFooter
  secondaryAction={{ label: 'Cancel', onClick: handleCancel }}
  primaryAction={{ label: 'Save', onClick: handleSave }}
/>

Three-button layout (Delete + Secondary + Primary)

For editing existing items that can be deleted.

<PropertyPanelFooter
  deleteAction={{ label: 'Delete', onClick: handleDelete }}
  secondaryAction={{ label: 'Cancel', onClick: handleCancel }}
  primaryAction={{ label: 'Save', onClick: handleSave }}
/>

Primary only

Single action fills full width. Good for simple confirmations.

<PropertyPanelFooter
  primaryAction={{ label: 'Done', onClick: handleDone }}
/>

Loading states

Show loading spinners during async operations. Disabled states prevent interaction.

<PropertyPanelFooter
  deleteAction={{ label: 'Delete', onClick: handleDelete, loading: isDeleting }}
  secondaryAction={{ label: 'Cancel', onClick: handleCancel, disabled: isBusy }}
  primaryAction={{ label: 'Saving...', onClick: handleSave, loading: isSaving }}
/>

Form submission

Use formId to connect the primary button to a form element. No onClick needed.

<form id="my-form" onSubmit={handleSubmit}>
  {/* form fields */}
</form>

<PropertyPanelFooter
  secondaryAction={{ label: 'Cancel', onClick: handleCancel }}
  primaryAction={{ label: 'Submit', formId: 'my-form' }}
/>

Custom icons

Override default icons (trash for delete, floppy disk for primary) with custom ones.

import { faArrowRotateLeft, faCheck } from '@fortawesome/duotone-regular-svg-icons';

<PropertyPanelFooter
  secondaryAction={{ label: 'Reset', onClick: handleReset, icon: faArrowRotateLeft }}
  primaryAction={{ label: 'Apply', onClick: handleApply, icon: faCheck }}
/>

FooterAction Props

PropTypeDescription
labelstringButton text (required)
onClick() => voidClick handler (not needed if using formId)
iconIconDefinitionFontAwesome icon (defaults: trash/floppy disk)
loadingbooleanShow loading spinner
disabledbooleanDisable the button
formIdstringForm ID for submit (primaryAction only)

Sub-components

For container mode or custom layouts, use these building blocks directly.

ComponentPurpose
PropertyPanelHeaderPanel title and description area
PropertyPanelContentScrollable content wrapper with padding
PropertyPanelSectionGrouped fields with optional title
PropertyPanelFooterSticky footer with action button props

Props

PropTypeDefaultDescription
titlestring-Panel title text
descriptionstring-Panel description text
childrenReactNode-Panel content
footerReactNode-Footer content for actions
size'normal' | 'wide''wide'Panel width variant
emptyState{ title, description?, icon? }-Empty state configuration
isEmptybooleanfalseWhether to show empty state
classNamestring-Additional CSS classes