Drag corner to resize plugin window

Is there documentation on how to drag and resize the plugin UI window, like Figma Tokens does it?
Screen Shot 2022-06-09 at 9.13.43 am

It’s not a native feature, some plugins do it via cursor movement tracking and constantly sending updates to the Figma backend to then call figma.ui.resize() to increase/decrease the window size. You might be able to find helper libraries for this on google, I haven’t searched.

1 Like

you can use this react component
which will place an SVG on the bottom right side of the plugin

import React, { useRef } from 'react';

const ResizableCorner = () => {
  const cornerRef = useRef(null);

  const resizeWindow = (e) => {
    const size = {
      w: Math.max(50, Math.floor(e.clientX + 5)),
      h: Math.max(50, Math.floor(e.clientY + 5))
    };
    // Using window.postMessage here; adjust accordingly for your app context
    parent.postMessage({ pluginMessage: { type: 'resize', size: size }}, '*');
    // window.parent.postMessage({ pluginMessage: { type: 'resize', size: { w: width, h: height } } }, '*');

  };

  const handlePointerDown = (e) => {
    const corner = cornerRef.current;
    corner.onpointermove = resizeWindow;
    corner.setPointerCapture(e.pointerId);
    // console.log('handlePointerDown')
  };

  const handlePointerUp = (e) => {
    const corner = cornerRef.current;
    corner.onpointermove = null;
    corner.releasePointerCapture(e.pointerId);
    // console.log('handlePointerUp', corner, corner.releasePointerCapture(e.pointerId))

  };

  return (
    <div style={{ height: '100%', padding: '16px', boxSizing: 'border-box', fontFamily: 'sans-serif', fontSize: '12px', margin: '0' }}>
      <svg
        ref={cornerRef}
        id="corner"
        width="16"
        height="16"
        viewBox="0 0 16 16"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
        style={{ position: 'absolute', right: '1px', bottom: '2px', cursor: 'nwse-resize' }}
        onPointerDown={handlePointerDown}
        onPointerUp={handlePointerUp}
      >
        <path d="M16 0V16H0L16 0Z" fill="white" />
        <path d="M6.22577 16H3L16 3V6.22576L6.22577 16Z" fill="#8C8C8C" />
        <path d="M11.8602 16H8.63441L16 8.63441V11.8602L11.8602 16Z" fill="#8C8C8C" />
      </svg>
    </div>
  );
};

export default ResizableCorner;

and you can add this code to the plugin.ts file

const pluginDefaultHieght = 580;
const pluginDefaultWidth = 360;
const pluginMaxHieght = 1200;

figma.showUI(__html__,{width: pluginDefaultWidth, height: pluginDefaultHieght});
//Restore previous size when reopen the plugin
figma.clientStorage.getAsync('size').then(size => {
 	if(size) figma.ui.resize(size.w,size.h);
}).catch(err=>{});

figma.ui.onmessage = async (pluginMessage) => {
	switch (pluginMessage.type) {
		case "resize":
                        // if you need to set some limitation
			if (pluginMessage.size.h > pluginMaxHieght) {
				pluginMessage.size.h = pluginMaxHieght
			} else if (pluginMessage.size.h < pluginDefaultHieght ) {
				pluginMessage.size.h = pluginDefaultHieght
			}
                        figma.ui.resize(pluginMessage.size.w,pluginMessage.size.h);
			figma.clientStorage.setAsync('size', pluginMessage.size).catch(err=>{console.log(err)});

			break;
		}

2 Likes

In order to use the above code in my plugin I had to adjust the markup slightly by removing the div and adding zIndex. But then it worked perfectly. Thanks @Mohamed_Salem! :pray:

return (
      <svg
        ref={cornerRef}
        id="corner"
        width="16"
        height="16"
        viewBox="0 0 16 16"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
        style={{ position: 'absolute', right: '1px', bottom: '2px', cursor: 'nwse-resize', zIndex: 100001 }}
        onPointerDown={handlePointerDown}
        onPointerUp={handlePointerUp}
      >
        <path d="M16 0V16H0L16 0Z" fill="#FFF" />
        <path d="M6.22577 16H3L16 3V6.22576L6.22577 16Z" fill="#8C8C8C" />
        <path d="M11.8602 16H8.63441L16 8.63441V11.8602L11.8602 16Z" fill="#8C8C8C" />
      </svg>
  );
1 Like