Polotno Docs
Side panel

Custom images panel

Load images from your API into a custom SidePanel section

How to load custom photos in the side panel?

Using the customization API, you can add a new section to the Side Panel to display images from any remote API or your own backend.

You can write a custom panel that loads images from an API:

import React from 'react';
import { observer } from 'mobx-react-lite';
import { InputGroup } from '@blueprintjs/core';
import { SectionTab } from 'polotno/side-panel';
import { ImagesGrid } from 'polotno/side-panel/images-grid';
import { getImageSize } from 'polotno/utils/image';
import MdPhotoLibrary from '@meronex/icons/md/MdPhotoLibrary';

export const PhotosPanel = observer(({ store }) => {
  const [images, setImages] = React.useState<Array<{ url: string }>>([]);

  async function loadImages() {
    // implement your API requests here
    setImages([]);

    // emulate network request
    await new Promise((resolve) => setTimeout(resolve, 3000));

    // demo data; in a real app use an API response
    setImages([
      { url: './carlos-lindner-zvZ-HASOA74-unsplash.jpg' },
      { url: './guillaume-de-germain-TQWJ4rQnUHQ-unsplash.jpg' },
    ]);
  }

  React.useEffect(() => {
    loadImages();
  }, []);

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
      <InputGroup
        leftIcon="search"
        placeholder="Search..."
        onChange={() => {
          loadImages();
        }}
        style={{ marginBottom: 20 }}
      />
      <p>Demo images:</p>
      {/* you can create your own custom component here */}
      {/* but we will use built-in grid component */}
      <ImagesGrid
        images={images}
        getPreview={(image) => image.url}
        onSelect={async (image, pos, element, event) => {
          // image - an item from your array
          // pos - relative mouse position on drop. undefined if user just clicked
          // element - model from your store if image was dropped on an element
          // event - can contain additional data
          const { width, height } = await getImageSize(image.url);
          store.activePage?.addElement({
            type: 'image',
            src: image.url,
            width,
            height,
            x: pos?.x || 0,
            y: pos?.y || 0,
          });
        }}
        rowsNumber={2}
        isLoading={!images.length}
        loadMore={false}
      />
    </div>
  );
});

// define the new custom section
export const CustomPhotos = {
  name: 'photos',
  Tab: (props) => (
    <SectionTab name="Photos" {...props}>
      <MdPhotoLibrary />
    </SectionTab>
  ),
  Panel: PhotosPanel,
};

Live demo