Skip to main content

Canvas and widgets

<Canvas /> is a main component to display a scrollable canvas for the diagram with elements, links and additional widgets.

Getting the canvas instance

useCanvas() hook called from a canvas widget can be used to get the CanvasApi instance from a context to read or subscribe to the canvas state or perform viewport-related effects:

function MyWidget() {
const {canvas} = Reactodia.useCanvas();
// Use canvas here
}

Alternatively, with SharedCanvasState.findAnyCanvas() or SharedCanvasState.findAllCanvases() methods it is possible to get canvas instance outside the canvas component:

function NonWidgetComponent {
const {view} = React.useWorkspace();

const canvas = view.findAnyCanvas();
if (canvas) {
// Use canvas here (could be any if there are several of them)
}

for (const canvas of view.findAllCanvases()) {
// Use each canvas mounted in the workspace
}
}

Canvas widgets

Canvas widget is an instance of any React component type which is marked by defineCanvasWidget() function with metadata such as its attachment layer i.e. where the component should be displayed in relation to other canvas content.

There are multiple canvas layers to place widgets on, from top one to the bottom:

Layer nameCoordinate typeDescription
viewportclient (viewport)Topmost layer, does not scale or scroll with the diagram.
overElementspaperDisplayed over both elements and links, scales and scrolls with the diagram.
overLinkspaperDisplayed under elements but over links, scales and scrolls with the diagram.

Example: custom viewport widget

Result
Loading...
Live Editor
function CustomSelectAllWidget() {
  const {model} = Reactodia.useWorkspace();
  return (
    <Reactodia.ViewportDock dock='ne'>
      <button type='button'
        className='reactodia-btn reactodia-btn-default'
        onClick={() => model.setSelection([...model.elements])}>
        Select All
      </button>
    </Reactodia.ViewportDock>
  );
}

Reactodia.defineCanvasWidget(
  CustomSelectAllWidget,
  element => ({element, attachment: 'viewport'})
);

function Example() {
  const {defaultLayout} = Reactodia.useWorker(Layouts);

  const {onMount} = Reactodia.useLoadedWorkspace(async ({context, signal}) => {
    const {model, view, performLayout} = context;
    model.createElement('http://example.com/entity1');
    model.createElement('http://example.com/entity2');
    model.createLinks({
      sourceId: 'http://example.com/entity1',
      targetId: 'http://example.com/entity2',
      linkTypeId: 'http://example.com/connectedTo',
      properties: {},
    });
    await performLayout({signal});
  }, []);

  return (
    <div className='reactodia-live-editor'>
      <Reactodia.Workspace ref={onMount}
        defaultLayout={defaultLayout}>
        <Reactodia.DefaultWorkspace
          search={null}
          canvasWidgets={[<CustomSelectAllWidget key='select-all' />]}
        />
      </Reactodia.Workspace>
    </div>
  );
}

render(<Example />);

Styles

The component look can be customized using the following CSS properties (see design system for more information):

PropertyDescription
--reactodia-canvas-background-colorBackground color for the canvas.
--reactodia-canvas-box-shadowBox shadow for the UI components layered on top of the canvas.
--reactodia-canvas-overlay-colorSemi-transparent color to place over canvas content when displaying a modal on top.
--reactodia-canvas-underlay-colorSemi-transparent color to place under components for improved readability when they are placed on the canvas.
--reactodia-element-background-colorDefault background color for the graph elements displayed on the canvas.
--reactodia-link-stroke-colorDefault stroke color for the graph links displayed on the canvas.