Wednesday, September 14, 2022
HomeProgrammingConstructing Interactive Figma Widgets | CSS-Tips

Constructing Interactive Figma Widgets | CSS-Tips


Figma has at all times inspired collaboration between builders and designers. It strives on an infinite treasury of community-made plugins. Want 3D components? There’s a plugin for that. Want summary SVGs? There’s a plugin for that, too.

That mentioned, the design a part of Figma has at all times been comparatively static — at all times working with unmovable rectangles linked to one another by way of predefined person interactions. However what if I instructed you that your designs may immediately come to life — that they could possibly be animated, interactive, and even stateful? Then, what would separate idea from implementation?

Figma introduced in June that it’s bringing JavaScript-powered widgets to the desk. Now, designers have can browse and implement logic-driven parts straight in Figma!

Say hiya to the Widgets API! You need to know what it’s and find out how to use it? That’s precisely what we’re going to do collectively on this publish.

Figma widgets open up tons of potentialities

Think about that you just’re working across the clock along with your associate to design a big restaurant software. You’re each already collaborating on the identical Figma board; each of you’re sharing the very same doc with adjustments taking place on the fly.

Absolutely, you already know that collaboration entails extra that simply the design course of:

  • venture administration,
  • internet hosting polls to assemble votes,
  • importing and visualizing mock knowledge,
  • and maybe even enjoying a multiplayer recreation to cool-off after many hours of labor.

We simply require one particular person to handle every thing and send-out hyperlinks to different members of the group. However oh, that’s not very environment friendly, is it?

Properly, that’s the place widgets come into play. We are able to conceivably do all of that — sure, every thing —with out ever leaving Figma.

Listed here are just some of the methods you may need to use widgets in Figma:

The listing goes on and on. As you possibly can inform, there’s already a plethora of widgets that you could freely use in your paperwork. In actual fact, you possibly can add Widgets straight to your board from the Widgets menu (Shift+I).

However we’re not right here to learn to use widgets, as a result of that’s simple. Allow us to do what we do finest: we’re gonna create our personal Figma widget! This one will probably be impressed by Chris Coyier’s design quotes web site. We’ll take the API, feed it into the widget, then show random design quotes straight in Figma.

Right here’s what we want

I don’t wish to be the bearer of unhealthy information, however as a way to develop widgets, you have to be on Home windows or Mac. Linux customers, I’m sorry, however you’re out of luck. (You would nonetheless use a VM if you wish to observe alongside.)

We’re gonna obtain the Figma Desktop software. The best approach to get began is by producing a widget template, straight from the app.

Let’s create a brand new board by opening the widgets menu (ShiftI), switching to the Improvement tab, and creating a brand new merchandise.

Following that, Figma will immediate you to call the brand new widget and determine whether or not it’s extra tailor-made in direction of design boards or FigJam boards too. The previous choice is enough for the needs of this text.

And the customization doesn’t finish right here; Figma may also provide the choice to start out with a pre-made counter widget or an iFrame-enabled various that additionally provides you entry to the Canvas and Fetch APIs (in addition to all different browser APIs). We’ll go together with the easy “Empty” choice, however we’ll ultimately modify it ourselves to utilize the Fetch API.

You’ll then be prompted to avoid wasting your new widget venture to a particular listing in your system. As soon as that’s executed, launch your terminal and direct it to that folder. Don’t run any instructions but — we’ll try this later and purposefully get an error with the objective of studying extra concerning the Widgets API.

Designing the widget

We’re pulling the design straight from Chris Coyier’s design quotes web site. So, let’s go there and dive into by firing up DevTools.

The 2 key shortcuts that I’m utilizing listed below are Ctrl+Shift+C (or Cmd+Shift+C) to toggle the “Decide factor” software, and Shift+Click on to alter the colour format to HEX code. We’re doing this to be taught concerning the colours, fonts, font weights and font sizes utilized in Chris’s web site. All this info is essential to construct a closely-resembling widget in Figma, which will probably be our subsequent step! You may seize the designed element and use it in your personal canvas.

I received’t go into a lot element right here as this text’s essential matter is constructing widgets by writing code. However I can’t stress sufficient how necessary it’s to take excellent care of your widgets’ type… CSS-Tips already has a plethora of design-oriented Figma tutorials; you received’t remorse including them to your studying listing.

Creating the format for our widget

With design out of the way in which, it’s time to take our programming fingers out and begin constructing the gears of our widget.

It’s very attention-grabbing how Figma interprets its design constructing blocks to React-like parts. Body components with the auto-layout function, for instance, are represented because the <AutoLayout /> element in code. Along with that, we’ll be utilizing two extra parts: <Textual content /> and <SVG />.

Check out my Figma board… I’m exactly asking you to concentrate on the thing tree. It’s what we want to have the ability to translate our widget design to JSX code.

As you possibly can see, our design quotes widget calls for three parts to be imported. That’s a good variety of parts contemplating that the full API solely incorporates eight layer-based nodes. However as you’ll quickly see, these modules are greater than enough to craft every kind of layouts.

// code.tsx
const { widget } = figma;
const { AutoLayout, Textual content, SVG } = widget;

And with this, we now have all we have to go forward and construct the skeleton of our widget like we’d in React:

operate QuotesWidget() {
  const quote = `...`;
  const writer = `...`;

  return (
    <AutoLayout>
      <SVG />
      <AutoLayout>
        <Textual content>{quote}</Textual content>
        <Textual content>— {writer}</Textual content>
      </AutoLayout>
      <SVG />
    </AutoLayout>
  );
}

widget.register(QuotesWidget);

This code may be very complicated, to say the least. Proper now, we will’t inform the design layers aside. Fortunately, we’re capable of simply remedy this concern by way of using the title property.

<AutoLayout title={"Quote"}>
  <SVG title={"LeftQuotationMark"} />
  <AutoLayout title={"QuoteContent"}>
    <Textual content title={"QuoteText"}>{quote}</Textual content>
    <Textual content title={"QuoteAuthor"}>— {writer}</Textual content>
  </AutoLayout>
  <SVG title={"RightQuotationMark"} />
</AutoLayout>;

And, after all, we nonetheless can’t see our citation mark SVGs, so let’s work on fixing that. The <SVG/> element settle for a srcproperty that takes the supply code for an SVG factor. There isn’t a lot to say on this one, so let’s preserve it easy and soar straight again to code:

const leftQuotationSvgSrc = `<svg width="117" peak="103" viewBox="0 0 117 103" fill="none" xmlns="<http://www.w3.org/2000/svg>">
  // shortened for brevity
</svg>`;
const rightQuotationSvgSrc = `<svg width="118" peak="103" viewBox="0 0 118 103" fill="none" xmlns="<http://www.w3.org/2000/svg>">
// shortened for brevity
</svg>`;

operate QuotesWidget() {
  return (
    <SVG title={"LeftQuotationMark"} src={leftQuotationSvgSrc} />
    <SVG title={"RightQuotationMark"} src={rightQuotationSvgSrc} />
  );
}

I feel we will all agree that every thing is way clearer now! After we title issues, their goal immediately turns into rather more apparent to the readers of our code.

Previewing our widget in real-time

Figma provides a fantastic developer expertise when constructing widgets, together with (however not restricted to ) hot-reloading. With this function, we’re capable of code and preview adjustments to our widget in real-time.

Get began by opening the widgets menu (Shift+I), switching to the event tab and clicking or dragging your new widget to the board. Unable to find your widget? Don’t fear, simply click on on the three-dot menu and import your widget’s manifest.json file. Sure, that’s all it takes carry it again to existence!

Wait, did you get an error message on the backside of your display?

In that case, let’s examine. Click on on “Open console” and skim what it has to say. If the Open console button is gone, there’s another approach to open the debugging console. Click on on the Figma brand, soar to the widgets class and reveal the event menu.

That error is probably going on account of the truth that we haven’t compiled our TypeScript to JavaScript but. We are able to try this within the command line by operating npm set up and npm run watch. (or yarn and yarn watch ). No errors this time!

Yet one more impediment you may hit is that the widget fails to re-render any time the code is modified. We are able to simply power our widget to replace utilizing the next context menu command: Widgets → Re-render widget.

Styling the widget

Because it at present stands, the seems to be of our widgets are nonetheless fairly removed from our ultimate objective.

So how will we type Figma parts from code? Perhaps with CSS like we’d do in a React venture? Destructive. With Figma widgets, all the styling occurs by way of a set of well-documented props. Fortunate for us, this stuff are named nearly identically to their counterparts in Figma.

We’ll get began by configuring our two <AutoLayout /> parts. As you possibly can see within the infographic above, prop names are fairly descriptive of their goal. This makes it simple for us to leap straight into code and begin making some adjustments. I received’t be displaying the entire code once more, so please depend on the element names to information you the place the snippets belongs.

<AutoLayout
  title={"Quote"}
  course={"horizontal"}
  verticalAlignItems={"begin"}
  horizontalAlignItems={"middle"}
  spacing={54}
  padding={{
    horizontal: 61,
    vertical: 47,
  }}
>
  <AutoLayout
    title={"QuoteContent"}
    course={"vertical"}
    verticalAlignItems={"finish"}
    horizontalAlignItems={"begin"}
    spacing={10}
    padding={{
      horizontal: 0,
      vertical: 0,
    }}
  ></AutoLayout>
</AutoLayout>;

We simply made lots of progress! Let’s save and soar again to Figma to see how our widget seems to be like. Bear in mind how Figma reloads widgets mechanically upon new adjustments?

But it surely’s not fairly there but. We should additionally add a background coloration to the basis element:

<AutoLayout title={"Quote"} fill={"#ffffff"}>

Once more, check out your Figma board and see how adjustments might be mirrored nearly instantly again into the widget.

Let’s transfer alongside this information and magnificence the <Textual content> parts.

After having a look on the Widgets API documentation, it’s once more clear that property names are nearly equivalent to their counterparts within the Figma app, as might be seen within the infographic above. We’ll even be utilizing values from the final part the place we inspected Chris’ web site.

<Textual content title={'QuoteText'}
  fontFamily={'Lora'}
  fontSize={36}
  width={700}
  fill={'#545454'}
  fontWeight={'regular'}
>{quote}</Textual content>

<Textual content title={'QuoteAuthor'}
  fontFamily={'Raleway'}
  fontSize={26}
  width={700}
  fill={'#16B6DF'}
  fontWeight={'daring'}
  textCase={'higher'}
>— {writer}</Textual content>

Including state to the widget

Oour widget at present shows the identical quote, however we need to pull from your complete pool of quotes at random. We should add state to our widget, which all React builders know is a variable whose change triggers the re-rendering of our element.

With Figma, state is created with the useSyncedState hook; it’s just about React’s useState, however it requires programmers to specify a distinctive key. This requirement stems from the truth that Figma should sync our widget’s state throughout all shoppers that could be viewing the identical design board, however by way of completely different computer systems.

const { useSyncedState } = widget;

operate QuotesWidget() {
  const [quote, setQuote] = useSyncedState("quote-text", "");
  const [author, setAuthor] = useSyncedState("quote-author", "");
}

That’s all of the change that we want for now. Within the subsequent part, we’ll determine find out how to fetch knowledge from the Web. Spoiler Alert: it’s not so simple as it appears.

Fetching knowledge from the community

Recall when Figma gave us the selection to start out with an iFrame-enabled widget. Though we didn’t go together with that choice, we should nonetheless implement a few of its options. Let me clarify why we will’t merely name fetch() inside our widget code.

If you use a widget, you’re operating JavaScript code by yourself laptop that’s written by another person. Whereas all widgets are totally reviewed by the Figma workers, it’s nonetheless an enormous safety gap as everyone knows how a lot injury might be created by even one line of JavaScript.

Consequently, Figma can not merely eval() any widget code written by nameless programmers. Lengthy story quick, the group determined that one of the best answer was operating third-party code in a closely-guarded sandbox atmosphere. And as you might need guessed, browser APIs are unavailable in such an atmosphere.

However don’t fret, Figma’s answer to this second drawback is <iframe>s. Any HTML code that we write in a file, ideally referred to as ui.html, can have entry to all browser APIs. You may be questioning how we will set off this code from the widget, however we’ll look into that later. Proper now, let’s soar again into code:

// manifest.json
{
  "ui": "ui.html"
}
<!-- ui.html -->
<script>
window.onmessage = async (occasion) => {
  if (occasion.knowledge.pluginMessage.sort === 'networkRequest') {
    // TODO: fetch knowledge from the server

    window.mother or father.postMessage({
      pluginMessage: {
        // TODO: return fetched knowledge
      }
    }, '*')
  }
}
</script>

That’s the final template for widget-to-iframe communication. Let’s use it to fetch knowledge from the server:

<!-- ui.html -->
<script>
window.onmessage = async (occasion) => {
  if (occasion.knowledge.pluginMessage.sort === 'networkRequest') {
    // Get random quantity from 0 to 100
    const randomPage = Math.spherical(Math.random() * 100)

    // Get a random quote from the Design Quotes API
    const res = await fetch(`https://quotesondesign.com/wp-json/wp/v2/posts/?orderby=rand&per_page=1&web page=${randomPage}&_fields=title,yoast_head_json`)
    const knowledge = await res.json()

    // Extract writer title and quote content material from response
    const authorName = knowledge[0].title.rendered
    const quoteContent = knowledge[0].yoast_head_json.og_description

    window.mother or father.postMessage({
      pluginMessage: {
        authorName,
        quoteContent
      }
    }, '*')
  }
}
</script>

We’re leaving out error-handling to maintain this easy and to-the-point. Let’s soar again into the widget code and see how we entry features outlined within the <iframe>:

operate fetchData() {
  return new Promise<void>(resolve => {
    figma.showUI(__html__, {seen: false})
    figma.ui.postMessage({sort: 'networkRequest'})

    figma.ui.onmessage = async ({authorName, quoteContent}) => {
      setAuthor(authorName)
      setQuote(quoteContent)

      resolve()
    }
  })
}

As you possibly can see, we’re first telling Figma to reveal entry to our hidden <iframe> and to set off an occasion with the title "networkRequest". We’re dealing with this occasion within the ui.html file by checking occasion.knowledge.pluginMessage.sort === 'networkRequest', after which posting knowledge again to the widget.

However nothing is going on but… We nonetheless haven’t referred to as the fetchData() operate. If we name it straight within the element operate, the next error happens within the console:

Can't use showUI throughout widget rendering.

Figma is telling us to not name showUI straight within the operate physique… So, the place ought to we put it? The reply to that’s one new hook and one new operate: useEffect and waitForTask. You may have already got familiarity with useEffect in case you’re a React developer, however we’re gonna use it right here to fetch knowledge from the server when the widget element mounts.

const { useEffect, waitForTask } = widget;

operate QuotesWidget() {
  useEffect(() => {
    waitForTask(fetchData());
  });
}

However this can end in yet one more “error” the place our widget will preserve re-rendering with a brand new quote, perpetually. This occurs as a result of useEffect, by definition, triggers once more each time the widget’s state adjustments, nay once we name fetchData. And whereas there’s a way to solely name useEffect as soon as in React, it doesn’t work on Figma’s implementation. From Figma’s docs:

Due to How Widgets Run, useEffect ought to deal with being referred to as a number of occasions with the identical state.

Fortunately, there’s a easy workaround that we will reap the benefits of and name useEffect solely as soon as when the element first mounts, and it’s by checking whether or not or not the state’s values are nonetheless empty:

operate QuotesWidget() {
  useEffect(() => {
    if (!writer.size & !quote.size) {
      waitForTask(fetchData());
    }
  });
}

You may run right into a scary “reminiscence entry out of bounds” error. It’s fairly widespread to see in plugin and widget growth. Simply restart Figma and it received’t be there anymore.

You might need seen that generally, the quote textual content incorporates bizarre characters.

These are Unicode characters and we should correctly format them in code:

<!-- ui.html -->
<script>
window.onmessage = async (occasion) => {
  // ...
  const quoteContent = decodeEntities(knowledge[0].yoast_head_json.og_description);
};

// <https://stackoverflow.com/a/9609450>
var decodeEntities = (operate () {
  // this prevents any overhead from creating the thing every time
  var factor = doc.createElement("div");

  operate decodeHTMLEntities(str) {
    if (str && typeof str === "string") '[^']*')*>/gim, "");
      factor.innerHTML = str;
      str = factor.textContent;
      factor.textContent = "";
    

    return str;
  }

  return decodeHTMLEntities;
})();
</script>

And voilà, our widget fetched a model new design quote each single time it’s added to the design board.

Whereas our widget fetches a recent quote upon instantiation, it could be rather more sensible if we may do that course of once more however with out deleting it. This part will probably be quick as the answer is sort of outstanding. With property menus, we will add interactivity to our widget with a single name to the usePropertyMenu hook.

Credit score: Figma Docs.
const { usePropertyMenu } = widget;

operate QuotesWidget() {
  usePropertyMenu(
    [
      {
        itemType: "action",
        propertyName: "generate",
	tooltip: "Generate",
        icon: `<svg width="22" height="15" viewBox="0 0 22 15" fill="none" xmlns="<http://www.w3.org/2000/svg>">
          <!-- Shortened for brevity -->
        </svg>`,
      },
    ],
    () => fetchData()
  );
}

With one easy hook we’re capable of create a button that seems close to our widget when it’s chosen. That was the final piece that we wanted so as to add as a way to full this venture.

Publishing our widget to the general public

There’s not a lot use in constructing a widget if, effectively, nobody makes use of it. And whereas Figma grants organizations with the choice to launch personal widgets for inner use, it’s rather more widespread to launch these little applications to the world.

Figma has a fragile widget assessment course of which will take up 5 to 10 enterprise days. And whereas the design quotes widget we constructed collectively is already within the widget library, I’ll nonetheless reveal the way it received there. Please don’t try to re-publish this widget once more as that can solely end in elimination. However in case you gave it some important alterations, go forward and share your personal widget with the group!

Get began by clicking the widgets menu (Shift+I) and switching to the Improvement tab to view our widget. Click on on the three-dots menu and press Publish.

Figma will immediate you to enter some particulars about your widget, akin to a title, description, and a few tags. We’ll additionally want a 128×128 icon picture and a 1920×960 banner picture.

After importing all these belongings, we nonetheless want a screenshot of our widget. Shut the publishing modal (don’t fear, you received’t lose your knowledge) and right-click on the widget to disclose an attention-grabbing context menu. Discover the Copy/Paste asclass and choose Copy as PNG.

With that executed, let’s return to the publishing modal and paste the widget’s screenshot:

Scroll down and at last publish your modal. Rejoice! 🎉

Figma will attain out to you in a few days concerning the standing of your modal’s assessment. Within the case of a rejection, you’ll be given the alternative to make adjustments and submit once more.

Conclusion

We simply constructed a Figma widget from scratch! There are lots of issues not lined right here, akin to click on occasionsenter varieties, and rather more. You may dig into the total supply code for the widget in this GitHub repo.

To those that aspire to take their Figma expertise to higher ranges, I counsel exploring the Widgets group and utilizing what catches your eye as inspiration. Hold constructing extra widgets, preserve sharpening your React expertise, and earlier than you even understand it, you’ll be educating me find out how to do all this.

Additional sources

I needed to consult with a lot of documentation whereas I used to be making this widget. I assumed I’d share what I discovered to assist probably the most.

Construct extra widgets:

Study widgets in higher depth:

Widgets vs. plugins

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments