Skip to main content
Question

Help Needed: Replicating Selected Figma Element in Frontend

  • November 27, 2024
  • 5 replies
  • 35 views

Eric_S

Hi everyone,

I’m working on replicating Figma elements in a React frontend. The goal is to replicate the exact position, size, and style of the selected element in Figma, using the data sent by the Figma plugin.

What I’ve Done

  • I’m receiving the data from the Figma then try to send it to frontend.
    const selection = figma.currentPage.selection;
    figma.ui.postMessage({ type: "selection-changed", selection});
  • In frontend, try to render with that data.
 useEffect(() => {
    window.onmessage = (event) => {
      const { type, selection} = event.data.pluginMessage;

      if (type === "selection-changed" && selection) {
        setElements(selection);
      }
    };

    return () => {
      window.onmessage = null;
    };
  }, []);

return (
    <div className="work-board">
      <div className="main-board">
        <div className="drop-board">
          {elements.length === 0 ? (
            <p>Select a frame or two to get started</p>
          ) : (
            elements.map((element) => renderVisualElement(element))
          )}
        </div>
...

But that is not rendering.

How can I fix this so that the selected Figma elements render exactly as they appear in Figma?

5 replies

tank666
  • 4856 replies
  • November 27, 2024

How are you trying to render the array of objects you receive in the UI?

figma.com

Eric_S
  • Author
  • 2 replies
  • November 27, 2024

I can implement this by exporting the element using the Figma API. However, the requirement is that we should be able to edit the design without affecting the Figma file. So, I need the data of the selected element in order to replicate it on the frontend and edit it there.

I tried the code below in the Figma plugin, but I’m still encountering an issue. Is there a way to retrieve the data and replicate it? Also, for images, is it possible to get the image URL or the raw data?

const selection = figma.currentPage.selection;

    const serializedSelection = await Promise.all(
      selection.map(async (node) => {
        const element: any = {
          id: node.id,
          name: node.name,
          type: node.type,
          x: node.x,
          y: node.y,
          width: node.width,
          height: node.height,
          visible: node.visible,
          rotation:
            node.type === "FRAME" || node.type === "GROUP"
              ? (node as FrameNode | GroupNode).rotation
              : undefined,
          opacity: "opacity" in node ? node.opacity : undefined,
        };

        // Handle TEXT node properties
        if (node.type === "TEXT") {
          element.characters = (node as TextNode).characters;
          element.fontSize = (node as TextNode).fontSize;
          element.fontName = (node as TextNode).fontName;
          element.textAlignHorizontal = (node as TextNode).textAlignHorizontal;
          element.textAlignVertical = (node as TextNode).textAlignVertical;
          element.lineHeight = (node as TextNode).lineHeight;
          element.letterSpacing = (node as TextNode).letterSpacing;
          element.fills = (node as TextNode).fills;
        }

        // Handle RECTANGLE (and other shapes) node properties
        if (node.type === "RECTANGLE") {
          element.fills = (node as RectangleNode).fills;
          element.strokes = (node as RectangleNode).strokes;
          element.strokeWeight = (node as RectangleNode).strokeWeight;
          element.strokeAlign = (node as RectangleNode).strokeAlign;
          element.cornerRadius =
            "cornerRadius" in node ? (node as RectangleNode).cornerRadius : 0;
          element.dashPattern = (node as RectangleNode).dashPattern;

          // Handle IMAGE fill if available
          const fills = (node as RectangleNode).fills;
          if (Array.isArray(fills) && fills.length > 0) {
            const imageFill = fills.find((fill) => fill.type === "IMAGE");
            if (imageFill) {
              const image = figma.getImageByHash(imageFill.imageHash);

...

tank666
  • 4856 replies
  • November 27, 2024

If you got all the required properties of the object and wrote a function to convert it to React elements, then everything should be fine.

As for the code snippet you provided, I would get all the properties using a recursive function using loops.

You can get the URLs of the images using the REST API. The raw data can be obtained using the exportAsync function I mentioned above.


Eric_S
  • Author
  • 2 replies
  • November 28, 2024

To use Figma API, I need fileId, right?
But, in Figma plugin, how can I get fileId?
figma.fileKey is returning undefined.


tank666
  • 4856 replies
  • November 29, 2024

If you mean REST API, then yes, some endpoints require a file key, including the GET image and GET image fills endpoints. But if you want to get JSON of the object, you can use exportAsync function from Plugin API.


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings