Skip to content

Panel Registry

The panel registry maps string component keys (used in openPanel() and serialized layouts) to React component constructors. There are two ways to populate it.

Pass a panels map to the WorkspaceClient constructor. This creates a scoped registry that lives on the client instance:

ts
const client = new WorkspaceClient({
  panels: {
    map:    { component: MapPanel,    defaultOptions: { title: 'Map', canClose: false } },
    editor: { component: EditorPanel, defaultOptions: { title: 'Editor' } },
    logs:   { component: LogsPanel },
  },
});

Each key is the componentKey argument to openPanel(id, componentKey). Keys must be stable — they are persisted inside saveLayout() JSON.

PanelDefinition

ts
interface PanelDefinition {
  // The library injects `panelId` as a prop automatically.
  // Components that don't declare it in their props can use `usePanelId()` instead.
  component: ComponentType<any>;
  defaultOptions?: PanelDefaultOptions;
}

PanelDefaultOptions

All fields are optional. They set the per-panel defaults; most can be overridden per-instance in openPanel.

OptionTypeDefaultDescription
titlestring | MessageDescriptorTab and window title.
iconReactNodeIcon shown in the tab and taskbar.
initialTarget'floating' | 'docked' | 'tabbed''docked'Initial placement when the panel is first opened.
favoritePosition{ x, y, width, height }Default floating bounds (position + size) when the panel is first floated. All four values accept numbers (px) or CSS strings ('50%').
canClosebooleantrueShow or hide the × close button.
canMinimizebooleantrueShow or hide the minimize button.
canDragbooleantrueAllow the tab to be dragged to a different leaf or position. When false, the panel cannot be floated via drag.
defaultAnchorFloatAnchor ('top-left' | 'top-right' | 'bottom-left' | 'bottom-right')— (unanchored)Every instance of this component opens pre-anchored to the given workspace corner when floated — see the anchor option in WorkspaceClient, which this is the per-component default for.
disableLivePreviewbooleanfalseDo not render a thumbnail preview when the panel is not the active tab.
renderHeaderActions(panelId: string) => ReactNodeInject React nodes into the panel tab header (e.g. export buttons).

Locked / pinned panel pattern

Set canDrag, canClose, and canMinimize all to false to create a panel the user cannot move, close, or hide — useful for a primary map or content area:

ts
const client = new WorkspaceClient({
  panels: {
    mainMap: {
      component: MapPanel,
      defaultOptions: {
        title:       'Map',
        canDrag:     false,
        canClose:    false,
        canMinimize: false,
      },
    },
  },
});

Imperative registration (advanced)

For dynamic panel types registered after construction, use client.registry.register():

ts
client.registry.register('live-chart', LiveChartComponent, {
  title: 'Live Chart',
  canClose: true,
});

Global singleton (legacy)

PanelRegistry (the global singleton) is still available for backward compatibility:

ts
import { PanelRegistry } from 'react-dockable-desktop';

PanelRegistry.register('map', MapPanel);

When no client prop is passed to the provider, the global singleton is used. For new projects, prefer the scoped WorkspaceClient approach.

Unregistered key warning

If openPanel('id', 'unknown-key') is called and 'unknown-key' is not in the registry, the panel renders a visual warning placeholder and emits console.warn:

[react-dockable-desktop] Panel "id" references component key "unknown-key"
which is not registered. Add it to the WorkspaceClient panels config:
  new WorkspaceClient({ panels: { "unknown-key": { component: YourComponent } } })

Released under the MIT License.