Docs menu

Declaring a Panel

This page is for people building on OpenX. Every panel in the workspace is declared once and registered with the workspace's panel registry. The workspace draws whatever the registry holds, so a panel you add appears, docks, closes and comes back like the built-in ones.

The declaration

A panel's declaration (PanelDeclaration, exported from @o-industrial/common/atomic/dock) holds:

FieldWhat it is
IdThe panel's stable id. It is kept in saved layouts, so it never changes once shipped.
TitleThe name a person reads in the panel's title bar and in menus.
RenderDraws the panel's content.
DrawsOwnHeadertrue when the content draws its own title bar; otherwise the workspace draws one.
MinimumSizeThe smallest width and height the panel may be resized to, in pixels.
DefaultPlacementWhere it starts in the Default layout: the side, its order there, and its starting size.
FloatingSizeThe size a floating copy of the panel opens at.
CollapseWhat collapsing does: pause keeps its state and stops its live work; unmount lets it go.
EmptyStateWhat the panel says when it has nothing to show. See below.
RestorePathHow a person brings the panel back after closing it, in words.

Two panels with the same Id are refused when the second one is registered.

The engine under the dock

The dock is drawn by dockview-core, the free core of the open-source dockview library, pinned to one exact version. It loads only in the browser, after the page arrives: until it does, the page draws a plain version of the same layout. The drag feel, the Move to menu, the layout tree and the panel registry are OpenX's own, built on top of it in @o-industrial/common/atomic/dock. A panel's declaration never names the engine, so your panel does not change if the engine does.

The empty-state sentence

When a panel has nothing to show, it says what will appear there and how to get it, instead of sitting blank. You declare this once, in EmptyState:

FieldWhat it is
SentenceOne sentence: what will appear in the panel, and how a person gets it there.
DocsHrefOptional. A docs page that explains more: an https: link, or a site path that starts with /.
ActionOptional. One next step, drawn as a button beside the sentence: a Label and a Command to run.

Write the sentence for someone who has never used the product. Say what the panel will hold and the one thing that fills it, for example: "Nothing is on the canvas yet. Add your first node from the Node Bank."

What the registry refuses

The registry checks the empty state when the panel is registered, and refuses the panel, naming it, when:

  • the panel has no sentence at all: no EmptyState, or an EmptyState with no Sentence, or a Sentence that is not text. Every panel declares one; there is no exemption;
  • the sentence is empty or only spaces;
  • the docs link is anything other than an https: link or a site path (a javascript: or plain http: link is refused, and so is a path starting with //);
  • the action has no label, or names a command the workspace does not run. The workspace tells the registry which commands it runs when it creates it (new PanelRegistry({ Commands })).

A refused panel is not registered; the panels around it are not affected.

Drawing it

Your panel decides when it is empty: the Live Stream knows it has received nothing, the Inspector knows no node is selected. For that case, return PanelEmptyStateNotice. It reads your panel's declared sentence and draws it the same way every panel does, with a Read more link that opens your docs page in a new tab, and your action's button.

import { PanelEmptyStateNotice } from '@o-industrial/common/atomic/dock';

if (rows.length === 0) {
  return <PanelEmptyStateNotice State={connected ? 'empty' : 'loading'} />;
}

Pass the panel's data state as State:

StateWhat is drawn
loadingA loading notice, never the empty sentence. Pass Message for your own words.
errorAn error notice, for data that could not be reached or a dropped connection.
emptyYour declared sentence, with its link and its button.
readyNothing: the panel has data to show.

Only say empty once you know the data really is empty, so the sentence never flashes up while the data is still on its way. A filter that hides every row is not an empty panel: say that in the panel's own words ("No impulses match the current filters.").

On this page