Pluggables framework

The Pluggables framework give you insertion points to push components to other components in an "out of tree" fashion, like React's <Portal> component, but with vitamins.

In almost any case, <Pluggable> is a better solution than a <Portal>. Some benefits include:

  • the <Pluggable> (the target destination) can pass parameters to the <Plug> (the inserted)

  • any <Plug> can be overridden, based on the id (you can't do that with <Portal>)

  • you can plug multiple Plugs into a <Pluggable> and you can control the order they appear

To understand how they work, it's useful to look at the architecture:

  • First, we need to wrap all of our React component tree in a <PluggablesProvider> (this needs to be done only once in Volto, and it's there in place already at App.jsx component level), so you don't have to do it:

<PluggablesProvider>
  ...
</PluggablesProvider>

This Provider acts like a centralized place where "insertion points" and "plugins to the insertion points" can be registered. It achieves that by using a dedicated React context.

Now, somewhere inside the children tree of <PluggablesProvider>, we can create some "insertion points":

<Pluggable name="left-column" />

Then we can plug things as children to the <Pluggable> with some <Plug> components:

<Plug pluggable="left-column" id="navigation">relevant nav stuff</Plug>

Declaring a <Plug> with the same id twice will make the second one (in terms of rendering order) replace the first one.

Internally, the <PluggablesProvider> keeps a record of Pluggables and Plug and this is achieved by having the <Pluggables> and <Plug> components register themselves with the Provider via React context.

Customize the rendering of plugs

You can customize the rendering of pluggables. The <Pluggable> component can take a function as a child and use that function to describe the rendering of pluggables.

<Pluggable name="block-toolbar">
{(pluggables) => pluggables.map((p) => (<>{p()}</>))}
</Pluggable>

Passing parameters from the Pluggable to the Plugs

You can also pass options to the Plugs, to enable inter-component communication:

<Pluggable name="block-toolbar" params={...blockProps} />

To use the passed params, you can do:

<Plug pluggable="block-toolbar" id="style">
{({options}) => {
  console.log(options);
  return <Button>Click me</Button>
}}
</Plug>