Polotno Docs
Interface

Workspace

Main React canvas component to render and interact with designs

Workspace is an essential part of Polotno. It is the main React component used to display drawings and interact with them. You can change canvas and its content programmatically using the Store API.

import { Workspace } from 'polotno/canvas/workspace';
import { createStore } from 'polotno/model/store';

const store = createStore({
  key: 'YOUR_API_KEY', // you can create it here: https://polotno.com/cabinet/
  // you can hide back-link on a paid license
  // but it will be good if you can keep it for Polotno project support
  showCredit: true,
});

const App = () => {
  return (
    <div style={{ height: '100vh' }}>
      <Workspace store={store} />
    </div>
  );
};

The Workspace will automatically take the full width and height of its parent, so you don't have to adjust its size manually. Set the size of the parent div with CSS.

Layout orientation

Control whether pages are stacked vertically (default) or horizontally in the workspace:

// Default vertical layout (pages stack top to bottom)
<Workspace store={store} layout="vertical" />

// Horizontal layout (pages arranged left to right)
<Workspace store={store} layout="horizontal" />

Use cases:

  • vertical (default): Standard multi-page documents, presentations, social media carousels
  • horizontal: Timeline-based designs, panoramic layouts, storyboards

Demo:

Switch between vertical and horizontal orientation in this live editor. The store renders three pages so you can evaluate the timeline spacing.

Customize page controls

You can customize page controls of your <Workspace /> component. Remove buttons, add your own, etc. You are in complete control over what is shown around the page.

<Workspace
  store={store}
  components={{
    PageControls: ({ width, height, xPadding, yPadding }) => (
      <div
        style={{
          position: 'absolute',
          top: yPadding + 'px',
          left: xPadding + 'px',
        }}
      >
        My controls here...
      </div>
    ),
  }}
/>

Hide page controls

Optionally, you can hide UI to add/remove/duplicate pages.

<Workspace store={store} components={{ PageControls: () => null }} />

Workspace styling

Optionally, change some styles of the workspace.

<Workspace
  store={store}
  backgroundColor="grey"
  pageBorderColor="black" // border around page
  activePageBorderColor="red" // border around active page (used when there are several pages)
  bleedColor="rgba(255, 0, 0, 0.2)" // color of the bleed area, toggled via store.toggleBleed()
  // optionally change default padding around page content
  // you can set it to 0 if you want full width and height of the canvas
  paddingX={50}
  paddingY={50}
  pageGap={50} // distance in pixels between pages, useful for multi-page layouts
  altCloneEnabled={true} // enable alt+drag to clone objects, default is true

  selectionRectFill="rgba(0, 161, 255, 0.3)"
  selectionRectStroke="rgb(0, 161, 255)"
  selectionRectStrokeWidth={1}

  snapGuideStroke="rgb(0, 161, 255)"
  snapGuideStrokeWidth={1}
  snapGuideDash={[4, 6]}
  
  transformLabelFill="rgb(0, 161, 255)"
  transformLabelTextFill="white"

  distanceGuideStroke="rgb(0, 161, 255)"
  distanceLabelFill="rgb(0, 161, 255)"
  distanceLabelTextFill="white"

  // ruler styling (see Canvas Rulers docs for details)
  rulerBackgroundColor="#f0f0f0"
  rulerTextColor="#333"
  rulerBorderColor="#ccc"
  rulerBorderSize={1}
  rulerTickColor="#999"
  rulerTickSize={8}

  // selection transformer (resize handles around selected element)
  // accepts Konva.TransformerConfig; omitted fields keep default values
  transformerStyle={{ anchorStroke: 'red', borderStroke: 'red' }}

  // hover/highlight rectangle around elements
  highlighterStyle={{ stroke: 'rgb(0, 161, 255)', strokeWidth: 2 }}

  // image crop transformers (inner = over cropped image, outer = source bounds)
  innerImageCropTransformerStyle={{ borderStroke: 'red' }}
  outerImageCropTransformerStyle={{ borderStroke: 'red' }}

  // dim overlay drawn around the canvas while an image is in crop mode
  cropOverlayFill="rgba(0,0,0,0.3)"

  // background + spinner color for image/video/gif elements while loading
  mediaLoadingStyle={{ fill: 'rgba(124, 173, 212, 0.8)', textFill: 'white' }}

  // background + text color for image/video/gif elements that failed to load
  mediaErrorStyle={{ fill: 'rgba(223, 102, 102, 0.8)', textFill: 'white' }}

  // stroke color for the (hidden) text overflow indicator path
  textOverflowIndicatorStyle={{ stroke: 'red' }}

  // Controls auto-scroll when the active page changes.                                                                
  // When a new page becomes active, the workspace scrolls to it only if                                               
  // the current scroll position is farther than this threshold from the page.                                         
  // Value is a fraction of the page size (0.5 = 50% of page height/width).                                            
  // Default 0.5. Increase to reduce scrolling. Use Infinity to disable completely.                                    
  scrollToPageThreshold={0.5}

// by default polotno will use checkerboard background for transparency, you can change it to any color you want
  transparencyBackgroundColor="grey" 

  // optionally set safe area for tooltip to avoid overlapping with other elements that you may place on top of the workspace
  tooltipSafeArea={{
    top: 100,
    right: 100,
    bottom: 100,
    left: 100,
  }}
/>

Deprecated. setTransformerStyle, setHighlighterStyle, setInnerImageCropTransformerStyle, and setOuterImageCropTransformerStyle from polotno/config do the same thing globally and still work for backwards compatibility, but prefer the per-<Workspace> props above. The setters will be removed in the next major.

Show only the current page in Workspace

Use the renderOnlyActivePage property to show only the active page.

<Workspace renderOnlyActivePage />

No pages UI

If your store has no pages, <Workspace /> will show a simple UI with a button to create a new page. You can overwrite this UI with your own.

<Workspace
  store={store}
  components={{
    NoPages: ({ store }) => <div>The project has no pages...</div>,
  }}
/>

Overwrite keyboard handler

If you don't like default keyboard shortcuts, you can overwrite them with your own.

import { handleHotkey } from 'polotno/canvas/hotkeys';

<Workspace
  store={store}
  onKeyDown={(e, store) => {
    if (e.key === 'Escape') {
      store.selectElements([]);
      return;
    }
    // optionally call the default handler
    handleHotkey(e, store);
  }}
/>;

On this page