Dev Mode and Custom Plugins in Figma
How can web developers and designers work together in Figma? Live from the Figma offices in San Francisco, Jake Albaugh will teach us how Dev Mode improves the design handoff, and how the Figma plugins API enables more powerful customization.
Links & Resources
Full Transcript
Click to toggle the visibility of the transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hello, everyone, and welcome to another episode of "Learn with Jason." Today we're coming to you live from the Figma studios here in San Francisco. I'm with Jake Allbaugh. Jake, how are you doing?
JAKE: I'm doing quite well, thanks for having me, or should I say, thanks for me having you. [Laughter]
JASON: I'm super excited to be here. One, I've never seen the Figma offices, they're very cool. You get to see this wall, everyone, but believe me, the rest of the walls are also very cool. Jake, for folks who aren't familiar with you and your work, do you want to give us a little background on who you are and what you do?
JAKE: Great. I'm Jake, I've been in the web industry since about 2010. I went to school for design but then transitioned to front end web development, spent three years working at CodePen refuse that community is like responsible for my career.
JASON: Yes.
JAKE: But did software engineering, then two, two and a half years ago, I tell stories internally and externally, evolving the Figma product as it becomes something developers are getting more out of.
JASON: We talked yesterday about the idea of being a creative engineer, a creative coder. You've just been kind of rattling off these amazing ideas about interesting projects, fun ways to just play with code. And it was fun, it's always nice to connect with a kindred spirit that way.
JAKE: Absolutely.
JASON: So today we're going to talk about specifically about Figma.
JAKE: Yep.
JASON: More specifically, we'll talk about how to use code to sort of manipulate Figma.
JAKE: Yep.
JASON: Which I'll be honest with you, I didn't know that was an option for me. I had seen there were custom Figma plug-s in, I had seen that -- there was like an image tracer or stuff that I had gotten, and it just never crossed my mind that like I could build one of those.
JAKE: Yeah, it's kind of cool. The story of Figma is that it was actually built on the web, right, as a tool itself. And so our sensibility platform, the plug-in API makes use of things on the web that you'll be familiar with already. It's very cool.
JASON: I do love that. That's a whole other story, one of these days I should track somebody from Figma down just to talk about the whole bit on the web in general, because that story is fascinating. But so let's talk a little bit about like what -- I guess maybe we just set the stage with Figma in general. Because I think Figma has seemingly -- it felt like it came out of nowhere, I feel like the whole world was Photoshop, then we were on Sketch, and then it just sort of like, wow, we're on Figma. And I think a strong part of that story is because Figma bet on the web, it's a web native experience, it's collaborative.
JAKE: Multiplayer.
JASON: You had a multiplayer thing, it was huge. As a developer, how does Figma fit into the story for us? I feel like this is --
JAKE: Yeah. So my background specifically is in web development, right? So I think my orientation towards product development is going to be web-forward. I think one of the things I've actually learned here in this role is just like, how vast the developer experience actually is, and like how many different types of disciplines there are and expectations there are from a design tool, right, when it thinks about design patterns that should relate to code, depending on the what you're coding for, what types of products you're building, there's just like a range of things. So Figma kind of seems to be a tool that can be used by everyone, built on the web, but not exclusively for the web, right? But at the same time that's a huge part of our DNA. And so, you know, we have this ability, I think, in my last role I was working for a company doing design systems, front-end engineering, component library buildout stuff. That was my first experience with Figma as a product, collaborating with designers on the design assistance team. I think at that time we had a lot less features than we do today. But there was still like this aha moment with Figma because it's like, oh, these designers are talking about like variance at the time was kind of the big thing, and the way that variance and components modelled similar patterns to what I was working on, TypeScript, component libraries. It was this opportunity, wow, we could use the same name for a variant and actually, in terms of like when I build out this component for my engineering team and they go to implement something that's in Figma, it says the same thing. Like, that in and of itself, like it doesn't have to say the same thing. So you have to be communicating. But like at that pattern level and the mental model we have for our UI and the way that the stuff is constructed, Figma was like this moment where I was kind of like, as a developer, this is really compelling to me, seeing this from a design perspective, like how the design perspective is actually really aligned with what we're doing.
JASON: Right.
JAKE: Since I've come over here, we've announced Dev Mode. Developers come to Figma to consume a design so that they can go build it in their IDA of choice or however they want to go do that. But they have to come to Figma, and they've been coming to Figma. A third of our users are develop remembers right? Not spending the same amount of time, but they're a huge portion of people touching our product. So we kind of embrace that with Dev Mode. How do we create a room in the designer's home, so to speak, for the developer to leave a toothbrush, put the poster on the wall.
JASON: Clear out a drawer for us.
JAKE: Exactly. That's what we announced last year, we're continuing to smooth out that surface so it feels less like developers are entering a design tool and more like a developer tool, so they can do what they need to do. Since then we've been rolling out more features to bridge those gaps, meet developers where they're at. Variables is another release on the design side which allows you to start using the same token naming and that sort of thing. We also have the ability to make a code gen plug-in, an org can build private plug-ins.
JASON: I'm going to interrupt you there to talk about how cool that is. We have the ability as developers to get code out of Figma that we wrote.
JAKE: Yes.
JASON: This is the stuff, which I started to see what Figma was unlocking, that's when I was like, oh, yeah.
JAKE: Exactly.
JASON: So the thing that I think is really cool, when I was at Netlify, for example, they had a design system team, they were working really hard at building out good tokens, good reusable bits, and all of those were designed in Figma with the variants, and we could go look at our design library, and then we had this sort of chicken and egg problem where we had the code and that was in Storybook and we had the designs and those were in Figma. And then somebody, which at the time we just had a design engineer, who was just sort of making sure they stayed in sync.
JAKE: Exactly.
JASON: What's exciting about what you're saying is effectively we have the ability now to have a sort of sync between the two.
JAKE: Yes. And we're trying to do as much as we can. What that sync looks like is also very relative and subjective for different people.
JASON: Right.
JAKE: We have a lot of default code generation, for example, right? That's the default code generation for styles, and like we do some CSS code gen and those sort of things natively inside of Figma. If you're a developer, at the same time you have your own patterns, your own mental model for this stuff. Extensibility is the way to go about bringing that into Figma. Figma can't guess that for you, right? You need to actually have some of that coming from that brain, so to speak, that person who is bridging that gap for the entire team, to be able to actually specify exactly what you need. So yeah, opportunities for that.
JASON: So today what I would love to look into is, like I'm aware of plug-ins, I've seen some of the custom code gen stuff you've done, I've seen some of the really head-bendy stuff I'm seeing from Raji with the shaders and stuff like that.
JAKE: Absolutely.
JASON: All of that, I see it but I don't understand it. I would love to get from where I am now, which is I know they exist and they're cool, to I know how they work and I can maybe build one.
JAKE: Perfect.
JASON: If I want to do that, what's our process?
JAKE: So the way to think about this is we have the Figma canvas, right? Where we're drawing rectangles in Figma.
JASON: Should I show --
JAKE: Let's hop over and actually do this.
JASON: So I'm going to take your screen and I'm going to use this better layout here.
JAKE: Wonderful, that layout is tremendous.
JASON: Isn't that great?
JAKE: So yeah, this is kind of the Figma canvas. This is where we can go ahead and just be like, drawing shapes. So there's a plug-in API that can perform all of these actions that you can do with your hands, right?
JASON: Right.
JAKE: So we have an API to learn for that stuff. But we also, when you talk about Raji building shaders and doing various textures and things like that, we also have plug-in UIs which are essentially I-frames that open up inside of Figma.
JASON: So I can make any website I want.
JAKE: Any website you want can communicate through post message through the canvas. You can do anything you could do with HTML canvas and like draw whatever image you want, and then send it to Figma and put it inside of Figma. If you start to figure out the APIs available to you in a browser, there are some caveats in there. If you want to do things that require SSL and that sort of thing, you have to host it externally, that's also possible, you can do that too. But you basically are given a web browser to play in, and then to send whatever information you want to Figma and do whatever you want with the plug-in API inside of Figma.
JASON: That immediately makes me feel more confident, because I know how to build a website, right? And I know what post message is. And so it just turns into an API at that point.
JAKE: Plug-ins inside of Figma, right, for the longest time have primarily been enabling designers. And so they've been this cool thing where the APIs are actually supremely accessible for web developers and stuff. But we haven't really had the use cases to like even care that that exists, unless you're someone that's close to a design team and you see an opportunity to enable your designers, or maybe you're a designer/developer and you want to build a plug-in. Those are the people who have been, oh, that's amazing. But for folks that -- that this would really resonate with, they haven't always had use cases for that. So the more developer stories we're telling inside of Figma, now these APIs have an opportunity to be like, yeah, we've been doing this for a while, and you see use cases for what you can do with this.
JASON: Okay. All right, so --
JAKE: You want to do this?
JASON: Yes, and I have a pitch for what I would like to do. A thing I always like to do in Figma is mock up a UI. Part of that is I need dummy data. But I want it to be as close to real as title because title lengths are different, images have different colors. I want to make sure it looks good with actual data and not my carefully curated dummy data. Can we build a plug-in that will hit my "Learn with Jason" API, pull in episode data and auto populate, maybe we can build a component that I would use and then we just auto populate that?
JAKE: Yeah. Absolutely, let's do it.
JASON: So we do the do-si-do.
JAKE: How familiar are you with designing in Figma?
JASON: I'm pretty comfortable with it.
JAKE: What's our schema in terms of the data we're getting?
JASON: We're going to get a title, an image. It's a JSON blog?
JAKE: A Jason JSON blog?
JASON: Exactly. Let's go with schedule, that's a little bit shorter. This is the standard data that we get. So we have -- and I would say probably what we need is like the title, we can pull the guest name, we have their image if we need it, we have the -- I have like a shortcut for generating the image of the episode as well. And then we have a description up here.
JAKE: So we want to make a line item with some of this information, wrap it in a component? What I think we should do is map those values to component properties.
JASON: Yeah, yeah. Okay.
JAKE: Then we can build a plug-in that creates instances of this component and then files it with the JSON stuff.
JASON: Okay. I'm going to do the most rudimentary setup here.
JAKE: Wonderful, we love to see it.
JASON: This would be our episode image, then we would have our title. Then this title goes here. Then we have our description. And this one I would want to be like one of these. Then maybe we make this one a little bigger. So we'll go with like 24 for that.
JAKE: Yep.
JASON: Maybe do like a 16 for that. This will be our image, this will be our title, this will be our description. Maybe that's good enough.
JAKE: Let's start with that, great. Select the frame. Then it's command option K, I believe.
JASON: Command option K.
JAKE: Yeah. We can rename it whatever we want to call this thing.
JASON: We'll call this episode preview.
JAKE: Okay. So we've got a component. Now let's do text properties for these two things. If you click this, and then you go to the text node, then click this little -- and then we can name that headline or title, exactly. And then we'll do that for the description too. Property. And let's like take a beat, let's create an instance of this so we can see what component properties are. I think that's -- so the way that this works is we've created an instance, right, of this component. And so this gives us kind of like a -- if you're familiar with like components in code, we have props, essentially, and the ability to fill that stuff. We don't just have text props. We also have variants where you select from a drop-down, we have properties to toggle visibility modes and so forth.
JASON: One of the things I'll always do, I start designing and realize I want to change stuff, and then I start to realize that oh, my God, I have to go and tweak all of these things to make this work. But here, you can see that like I tweaked the parent component. This updated, but it didn't change my text. So it's like, this is so nice.
JAKE: This is how we think about it, right? We think about these patterns in this way. Now, we named this prop title and this prop description. If that's a line with our developers thinking about that exact same information, when my full stack engineer comes to consume this design, it has the exact same property name as it actually ends up having in our react component library, whatever it is. There's opportunities there. It doesn't always align. But you can drive that kind of alignment, which is great.
JASON: Yeah. There was a question on how you make something into a component. So anything in Figma, if you click it, there's this button here. And that will create a component. Or you can hit command option K. So -- apparently I accidentally tapped it. No, that's a component. And then when you look over -- is it here in assets?
JAKE: Yeah, libraries. We can publish -- this is actually a different -- that's a different library.
JASON: Oh, gotcha.
JAKE: Which is something that I created in this team. But yeah, you then, from this file -- this file is kind of your definition of your component library. And you can publish that to your team. And those publishes can almost be versions. Like you can stage a bunch of changes, then publish a big update.
JASON: Oh, nice.
JAKE: Any file that's using that can choose to pull that information in when they're ready for it and all their designs will update to the latest and that sort of thing.
JASON: That's cool. That's something I know was a little bit painful in Figma in the past, every time you open, there's a new version of this component, it would always be the tiniest thing.
JAKE: You have the ability to do that at whatever schedule you want, right?
JASON: Got it.
JAKE: So we have a component instance. Do we have any more questions or are we good?
JASON: Vinnie giving extra insights there. There's a bunch of cool ways that we can --
JAKE: Tons of different entry points.
JASON: So we've got the very basics of an episode preview component.
JAKE: Essentially we'll write a plug-in that makes a request, gets data, then does what we just did where we created an instance. It will create an instance off of this component, probably, for now. And one thing we can even do is say, you select the component before you run the plug-in, and it will use your current selection to know which thing to like -- we can do all sorts of stuff like that too. Let's start the bare bones of the plug-in. If you switch to VS code, I created the two files we need. We need a manifest to describe the plug-in to Figma. Then we need a code.js file, we can maim it whatever we want, that will be our primary, we can be compiling this with TypeScript, we can do whatever we want. Let's start with the manifest. If you switch to Ark, I have a tab, if you move over here to the left, there's an API reference. So this is the plug-in API reference. I don't know if you want to command L to show the url so people see it. Figma.com is where you can start accessing this. Click off and go to plug-in manifest. This is kind of like the documentation for this manifest. I just copy the whole thing. Copy it and we'll start from there.
JASON: We'll call this LWJ.
JAKE: We need a unique ID, so we can publish it to the community. Change one of those numbers or something, just so we have a unique one. The API is still version 1. Main is telling Figma what our primary like code file is for the canvas plug-in API, like the stuff that's happening inside of Figma. Then we also have a UI field, which is where you can begin to say, this is the file where, you know, when it opens the UI. Delete that for now, because let's start without a UI for the time being. Document access. This is a new API, we started dynamic page loading, which allows you to open a file without having to load every page in the file. Figma files can have many pages, sometimes. We have some API changes where everything is async now because of various reasons, like, you know, finding nodes in the file and stuff, has to all be async because of dynamic page loading. Then this last little bit, network access is basically telling Figma we're not making any web requests. But we are going to be making web requests. So put an asterisk instead of none, because we will be making web requests from this thing. And then this is displayed on the community for published plug-ins, so that customers or users know, either like an allow listed like series of domains.
JASON: This one is going to be able to use network requests.
JAKE: Exactly. It allows you to specify exactly which ones it does. We're just doing a wild card which would kind of be a red flag for other folks, not matter for others.
JASON: If I wanted to put in a real domain, do you put the protocol in?
JAKE: Let's do this correctly. Go to the docs in Ark, command K, do allow domains. Let's click on network access, right? So the documentation for network access is here. We should have some examples. None, asterisk, you can do wild card stuff.
JASON: Okay. Why don't we just do this. So we'll do a "Learn with Jason" dot dev.
JAKE: Perfect, you're just doing things the right way. I this for now let's add another field under main. It's camel case editor type. And it's an array of strings. And we're going to say just Figma for now. In quotes. We also have fig jam or whiteboarding tool, you can do Dev Mode specifically we can flag too. For now we'll just leave this. So let's save this. I don't have auto save in VS code, do you use auto save?
JASON: No.
JAKE: Perfect. This should be everything we need to begin to do some stuff. And let's do Figma.notify as a function.
JASON: Like capital Figma?
JAKE: I'm sorry, lower case Figma, it's kind of on the window if we want to think of it that way, parentheses, hello world or something. We just want to send a message.
JASON: In terms of a minimum viable plug-in, you need a manifest and you need at least something in here.
JAKE: Yep. We're going to run this plug-in in development mode which will read directly from our file system instead of from the Figma community.
JASON: Excellent.
JAKE: If you go over to Figma and you click that little guy right there.
JASON: This one?
JAKE: Yeah. Plug-ins, instead of recents and saved, we have my eclipse plug-in, we should look at that in a second, hit development, and then plus. We're going to import plug-in from manifest. It's in jalbaugh projects and then LWJ manifest, boom, open. Invalid for --
JASON: Oh, okay, fine. New docs lied to me.
JAKE: That might have been an update after the fact. Let's try it again.
JASON: We're going to go into this one.
JAKE: We have to re-import.
JASON: This one, this one, this one, and there it goes.
JAKE: Hey. So this is now, if you just do that, hello world down at the bottom.
JASON: Yeah, look at this, you all! This is great, this is exactly what I want. Because here's the other thing that always kind of gets me about plug-in dev for a lot of things. The startup is so challenging. You've got to get the docker image, you have to set up some kind of local server, or you've got to deploy it to a network addressable instance. The fact I'm running off a local file here, this is a killer feature because it makes me actually want to build one of these [laughs]. Jake if you were running Figma in the web browser, you can't do this.
JASON: This is because we're running the desktop, if you're a plug-in developer you'll want the desktop app, it's an electron app around the Figma browser so it's effectively the same experience.
JAKE: Exactly. We have more functionality because we're actually on the machine for stuff like this.
JASON: Very cool.
JAKE: So hit cancel because we're still running. Let's go back to VS code and add a line. We can probably close manifest if we want to at this point. Add a line and it will be Figma.close plug-in and that's the function, it's camel case. Sweet. It's going to notify, close the plug-in, and no longer have a spinner. Quickest way to run this now is, click out of here, command P, and we've got our own little thing, just write LWJ.
JASON: Oh, beautiful.
JAKE: Sweet. This is running. So let's talk about -- what would the next step be?
JASON: So the next step I think for me would be let's figure out how to grab this instance and do it without worrying about the other stuff. Can I have my plug-in find this component and create a new instance?
JAKE: Yeah, let's actually -- instead of working with the selection like I was hinting at earlier, it actually might be a better example if we find it. Let's do it.
JASON: Okay.
JAKE: So we're going to do, before we close the plug-in, right, let's actually create -- let's create an async function so that we can start using async and awake, let's say it's called run or initialize or whatever we want to call it. And then inside of here, put Figma close plug-in as kind of like the last thing we'll do after -- that's how we'll exit this function. Let's call run somewhere at the top, call run somewhere. Great. So now we have all the async away goodies we can muster. So let's do Figma.current page -- yeah, we'll do it this way.
JASON: Like so?
JAKE: Yeah. Dot find all with criteria. And then inside of here you're going to do an open, Ark is an object, it's going to be types, array, string, upper case component, all upper case. Okay. Let's save and see if Jake knows what he's talking about. Command option I, let's open up the JavaScript console here. Because it's the web. And let's try running this and see if we get an error. Okay. We didn't get an error, that means we got something. So top of the code.js file, pro tip, have you ever done this? I used to do it in CodePen, top of my pen console dot clear.
JASON: I have actually never done this.
JAKE: Super helpful, especially in development.
JASON: Hey, look at that. Okay.
JAKE: Let's actually log the -- let's log -- let's store this in a variable and log the variable and see what happens. I can't believe I got that off the dome. No script here, by the way. We have a rough idea what we're doing but we did not -- hey, check it out.
JASON: Now we got a component mode.
JAKE: It's got getters. The only attribute we're actually getting is the ID. So yeah, there's a ton of stuff available to us on here. How are we doing on chat?
JASON: We're doing great on chat. If you all need --
JAKE: Thanks, Linda.
JASON: Good memory here. There's a question about the command line interface. So we have a ton that we want to get through in this, but we will -- yeah, our plan is to go like as far as we can and then come back and enhance things. But yes. And then the recording for this will be available on YouTube immediately after we go offline. If you head over to the "Learn with Jason" YouTube, the recording of this and every episode of "Learn with Jason" is right there under the Live tab. So we've got our component node. We have an ID. Now --
JAKE: And I guess it's worth saying, an instance is an instance node, right? So we have two nodes in our canvas right now. It only found the component because we're filtering just for component. So let's just -- do we want to like run with the assumption that there's never going to be another component in here? Or we should probably do a filter.
JASON: Yeah, let's be responsible.
JAKE: At the end of this we can do a dot filter, I guess, just do see arrow function or something. Do see.name.
JASON: Do we get the name in here?
JAKE: We do, it is in there.
JASON: See.name.
JAKE: Just get rid of your curlies. See that, name equals --
JASON: What did we call it, episode preview.
JAKE: Yeah. We should still see the same thing.
JASON: There we go. We have our component node.
JAKE: Wonderful. Grab index zero.
JASON: What's at? I always just do braces zero. This is some new JavaScript index.
JAKE: Let's see if our JavaScript run time allows --
JASON: It works.
JAKE: Wonderful. "Learn with Jason." I'm learning with Jason.
JASON: We're learning together.
JAKE: We're learning together. Sweet. We know we have our component. We can write, I don't know, if component, do the stuff. Why don't we create another async function and do an awake on that.
JASON: We'll get rid of this and say, if there is not a component, then we will Figma notify busted and then I guess we would close there.
JAKE: We can do that.
JASON: Immediate bail. Otherwise --
JAKE: Await amazing function we haven't created yet. Good call, we'll do it in one function.
JASON: We can make another function.
JAKE: Let's just keep going. This is fine. We'll do this later. These are the things that are so arbitrary that we won't waste time thinking about it. This is a good idea, I like this. Let's do stuff. So -- oh, boy. Let's create an instance. So the best way to like figure out the best way to do any of this stuff is to go back to our docs, command K and fuzzy search, create instance. Yeah. So what is this method on? If we scroll up, we'll see this is a method on a component. So component.create instance is a function.
JASON: I would say new component.
JAKE: Instance.
JASON: Good, good. Equals component create instance.
JAKE: Yep. And that is going to just spit it out, like immediately. We don't have to like append child or anything like that. So these create actions --
JASON: This is us telling Figma, make an instance of this.
JAKE: Exactly.
JASON: This isn't creating one in memory so then I have to --
JAKE: No. We do have append methods to order things on the canvas layer-wise in the same way you would move things around in an HTML document or something. But our create instance just implicitly adds a node to the canvas. And then you can move it around and do whatever you want with it. If we actually just hit save and run, let's see what that does. You have an instance in here already, correct?
JASON: I do.
JAKE: Let's delete it and see what happens.
JASON: I'm going to zoom out so we can see --
JAKE: How are we doing on time?
JASON: We're killing on time. Whoa, there we go!
JAKE: I'm going to get some water, always dehydrating. That's an inside joke from another livestream. ABH. Sweet. So --
JASON: I mean, we did it. Okay. So this is how much -- sorry. This is how much code we've written.
JAKE: We're guarding for error handling stuff.
JASON: Yeah. So in 25-ish lines of code, and I mean, a lot of this is not even really necessary. 20 lines of code, call it, we have a really simple canvas manipulation. That's really, really nice.
JAKE: Yeah.
JASON: Is this one of these magic things that now that I have my new instance, I can start messing with properties?
JAKE: Yeah. Why don't you go back to the docs. Our docs are pretty intuitive. Click on instance node. Now we're on the instance node documentation. In here we should be able to get the main component async, main component is old, that's the document nonsense. It's now an async function. We're in between node where we're moving to this async world.
JASON: Set properties. This is gorgeous. We're going to go with new instance.
JAKE: Also if we were using TypeScript which we shouldn't set up right now, we get plug-in typings.
JASON: I didn't want to type new anymore.
JAKE: That's great.
JASON: Our properties were title.
JAKE: It was upper case, though, right? Or capitalized?
JASON: Was it? It was indeed. Okay. So let's get back in here. Good memory. I would have learned that by breaking it. Let's see. This came from a plug-in.
JAKE: Huzzah. I've said huzzah twice now.
JASON: That's the limit, any more than that and you have to leave.
JAKE: It's like a reverse "Beetlejuice."
JASON: We're going to see the title and description show this data.
JAKE: It should happen instantaneously. Perfect. We got an error. Let's look.
JASON: Could not find a component property with name description.
JAKE: Yeah, so let's make -- is there a misspell? Because I would assume we would get it for title.
JASON: Maybe it alphabetized them.
JAKE: With name description? Oh, property names aren't the name we wrote in Figma. They're the name we wrote in Figma plus some unique information.
JASON: Oh, okay.
JAKE: So we actually want to go -- okay. We actually want to get the name of the property off the main component.
JASON: Okay.
JAKE: Let's actually see what that is. Hold on, hold on. Can we go back to the docs?
JASON: Component properties?
JAKE: Property name corresponds to the names from the parent component property definitions. Suffixed with a pound and a unique ID. Okay. Let's go to -- let's do component property definitions. Let's search for that really quick with command K.
Oh, okay. I just want to make sure we can enter into this the right way. These are supported on components, component sets. Let's keep scrolling down here. So we're going to get this, right? And see that pound? That is the actual name of the thing.
JASON: Got it.
JAKE: What we want to do -- this will actually be kind of fun, because we want to -- we'll do like a does name match, this name starts with. So let's get the component property definition. So this is the definition of all the properties on the main component, right? That's not going to be available on the instance. It's going to be on the main one. Yep. And that I believe, definitions is just an attribute.
JASON: It's just an attribute. Okay.
JAKE: Then do we want to do like a reduce situation or how -- what format do we want these names to come back as?
JASON: These will come back as an object.
JAKE: Object.keys?
JASON: Yeah, let's do our -- all props, the ones we want to set, we'll do all props -- let's see.
JAKE: Object.keys all props.
JASON: Object.keys all props. Then we're going to filter. And then we'll say that's our key. And so we'll say return key starts with --
JAKE: Title or description.
JASON: Title or key starts with description.
JAKE: Let's look at those props.
JASON: Then what we should get --
JAKE: I mean -- okay.
JASON: -- is those two things.
JAKE: Let's see if this works.
JASON: How would we do this?
JAKE: If we did a reduce, reduced to an object, we could say title, colon --
JASON: Oh, I see what you're saying, let's do that.
JAKE: How do you think about that first -- what do you call that?
JASON: I call it the accumulator because that's what they've always put it in. Then we can do an if it starts with one of these or one of these --
JAKE: Or if starts with title, then --
JASON: Yeah, that's probably better.
JAKE: Sorry. Back seat driving.
JASON: This is exactly what you're here for, to keep me from falling down rabbit holes.
JAKE: Listen, if I was coding, I would be doing the same thing.
JASON: The accumulator title is going to be --
JAKE: Equals K.
JASON: K. And otherwise. We could probably code this down to make this a little better. But then we've got our props. Then we need to return accumulator. Okay. We've got our object. I'm pretty sure I wrote a reducer right the first try.
JAKE: I think you did, using TypeScript.
JASON: We'll do one of these and we'll wrap that like so.
JAKE: Do you always refer to the braces quotes, or would you ever write dot description dot title here? I'm just curious.
JASON: I don't know. I -- so -- I would do a dot. For some reason when it's capitalized, it starts to feel like, oh, it might have spaces, it might have something else.
JAKE: I mean, I also kind of -- yeah, I think of that as a class typically, too. This is a problem we get in Figma all the time, Figma people doing designs are going to use proper casing and we never do that. Oh, my goodness.
JASON: But we're much closer. Now is not defined, which means I did what? Oh, right, it's props.
JAKE: It's props. MRV dog got that.
JASON: Here to bail me out. Hey, look at that go. But I think I just spotted a problem. It's only creating one instance. Oh, it's stacking them.
JAKE: It's stacking them.
JASON: So we need to move them around.
JAKE: How many did we create? Oh, we've been running this, so many times. We can always just write instance.remove while we're deving. Then we can't even see it, never mind. We can do a set time out.
JASON: That sounds like --
JAKE: We need to write an awake function that will wait two seconds before it prematurely closes.
JASON: You can see the pieces are set, that's good.
JAKE: So now we need data.
JASON: So now we need data, so let's get data.
JAKE: We can do that without even opening an I-frame which is kind of wild. We have fetch. This environment we're working in isn't a full -- like it's a Figma JavaScript environment. But we do have fetch support, and it's fairly similar. We should make sure, because all of our Intelisense is -- wow, you know your little rest situation there, don't you?
JASON: This one should be pretty straightforward, we don't need anything magic here.
JAKE: I want to make sure we have the exact same structure. Let's run it and see if we get an error. Console dot -- oh, my goodness. Yeah, okay, we got it, beautiful.
JASON: So we got all that. This is our JSON, so then I'm going to get schedule will be awaits res JSON.
JAKE: One of our schedulers was working on that, thanks James.
JASON: We got data. There's our data.
JAKE: In an older version of our plug-in API, we didn't have that ability. This actually speeds up what you can do inside here, you don't need to create another HTML file, it's pretty rad.
JASON: So now, observe.
JAKE: Yeah. Now you can just -- I don't even have to teach you how to do this part.
JASON: Because we're just writing JavaScript, friends, this is perfect. I can do episode.title, then I have episode.description. Not that description.
JAKE: Yeah, let's do this. You've got an image thumbnail too?
JASON: I do. Look at that. My component's not right, but --
JAKE: That's why we're doing this.
JASON: Yo, this is cool. Now I can do something like -- we'll make this wrap. And then that makes this wrap. So then that breaks. We'll have to do some stuff.
JAKE: Click it right here. Click the title. And then scroll up. Instead of being static, click on -- no, we don't want to set it to a variable. We should be able to have it fill the parent -- I'm sorry.
JASON: Don't we need to make this a layout if we want that to work?
JAKE: We haven't done anything, have we? You know what you're doing.
JASON: We want it to go down. Did this already fix it? It already fixed it.
JAKE: Fill parent with as the width. Click fixed.
JASON: Oh, look at this.
JAKE: Kind of like flex grow.
JASON: Gorgeous. I didn't know this one was there. Oh, my goodness. I did not know that worked.
JAKE: That's great.
JASON: All right. But now, look, look. We have our component. And because we used the auto layout, we can have it expand to whatever size. All right. Let me swap this. Actually what do we do next? Because there's several things I want to do and we have -- that's it, everybody go home. We got like 40-ish minutes.
Okay. I think the first thing, we've got a hack for images that I think is actually pretty good, I think we can get these images in there too.
JASON: Let's do the code gen first.
JAKE: This is related, though. Let's write to plug-in data on the instance. So plug-ins can store information on any node inside of Figma, whether it's the page, a component, a rectangle, whatever. So just -- yeah, the image url is going to be --
JASON: I'm just going to have to do it the way that I do it. Dev, then what is it, it's going to be the episode.slug.
JAKE: We code very similarly, it's really nice to be like, yeah, that's how I would do it.
JASON: I think that works. Let me double-check that that's actually the right thing. Console.lorg.
JAKE: Console.lorg.
JASON: We get one of those, one of these, we open this -- whoa, what buttons am I pushing?
JAKE: Command T inside of Figma.
JASON: That is correct.
JAKE: That is huge.
JASON: I can shrink that down if we need to.
JAKE: If we have time we can talk about how we would actually draw this image inside of Figma. But we're not going to worry about that right now. But we do want to be able to access this later when we do things like generate code for this instance, right? So instance.set plug-in data. And you can almost think of this, it's actually two arg. The first arg is the key, we'll call it image as a string, we can literally put the image url.
JASON: That's easier than what I was doing.
JAKE: Let's make sure that doesn't throw an error. So now --
JASON: All good?
JAKE: Click on this. I was going to quickly have us access this but we can't because we're not in the plug-in. It's scoped to the plug-in so only the plug-in can read it. This stuff is private so the plug-in as access to read and write it. We'll find out whether or not this is going to work later. So we're storing it -- here. And then we'll know. Yeah. Do we have it or do we not.
JASON: We got it.
JAKE: Sweet. Now we can reference this any time that node is selected with a plug-in, right?
JASON: Wonderful.
JAKE: Cool.
JASON: Okay. Thens for us to build this out, then, I want like -- the way I would mark this up, I'll just pseudocode some stuff here.
JAKE: You'll just write a string or something?
JASON: Yeah, I would set it up as an article, that article would have a -- we'll call it an image. The source would be our image. Then our alt which will be the title. We'll make it one of these, that would be the title. Then we'll have our description. So that's going to be our baseline target. Let's assume this is what came out of my design system.
JAKE: Yeah.
JASON: And so --
JAKE: Let's render the HTML. Let's see the environment for showing code. If you just save this, because this isn't going to break. Now, let's switch to Figma. And let's enter Dev Mode. Shift D or click that.
JASON: Shift D. Boom.
JAKE: Just click this, scroll down to CSS. Here's what we get, right? We get some information kind of about -- because right now we have the parent selected. So we see CSS just on the parent. We got a gap, line items, flex direction, padding, all of that.
JASON: That will get us that layout.
JAKE: Yes. If those things are bound to variables, we would see CSS custom properties and all that sort of thing. But what we want to do is like not show the CSS because in this world, the CSS has already been written, right?
JASON: Right, we want it to be an article class, episode preview or whatever.
JAKE: Yes. And then eventually a react instance, something like that. But let's start with HTML. So our plug-in can also, if you click on CSS here, you can run plug-ins here.
JASON: Oh, okay.
JAKE: We're going to make our plug-in work in this little panel now. If you click off of this, and let's go back here, and we got to go back to the manifest. Yep. We're going to add, after Figma, do comma dev, and then we also need -- I think it's capabilities beneath a new attribute, capabilities array code gen. Let's verify that I got the right stuff. Let's go back to the docs. Code gen. Capabilities code gen. Cool. Let's click on that really quick. Did you see VS code is also a capability? Did you see that VS code is a capability? We'll get to that later. Because we're doing a code gen plug-in, we also have to define some code gen languages. Let's just do an array with one of these. So it will be a code gen languages, camel case, array, and the g is lower.
JASON: No, it's not.
JAKE: At Figma, code gen is. Label can be whatever you want. And actually so can value.
JASON: So we need label. And it's going to be -- we're going to call it design system.
JAKE: You could also have the HTML and have the same code gen plug-in run in react or HTML.
JASON: I got you, I got you. So then the value --
JAKE: Was it a value? Yeah, value, I'm sorry.
JASON: It would be like that?
JAKE: Yeah. The value is what we get in a callback so we can detect which lank we're running.
JASON: Okay.
JAKE: Great. This should be everything we need now. Let's go back to Figma and make sure it exists. If you go to CSS development.
JASON: Hey.
JAKE: It's there. It's not doing anything so it's not running yet. What we want to do, we need to conditionally detect whether or not we're running in code gen mode or in design mode. How are we doing on chat?
JASON: We're doing good on chat. I'm just hiding some stuff.
JAKE: Wonderful. Let's go back to the code.
JASON: Back to the code.
JAKE: Let's rename run design mode or something. What do we want to call it? Like run design mode? And then we will have run code gen as another async function. Why does it still say run at the top?
JASON: Did I break it? Updated, there we go.
JAKE: Okay. So in here, just write return, because code gen needs to return a promise. I'm sorry, no return. Figma.code gen is a new name space for the API, .on parens generate, and callback.
JASON: Is that call back async?
JAKE: It is, actually. We can just return a new promise. Exactly.
JASON: Okay.
JAKE: Return an array. And in the array do an object. Write language. And then this is actually important, upper case HTML. These are formatting. This is code syntax.
JASON: Oh, this isn't referring to my label, this is referring to your internal --
JAKE: So Figma knows how to do it. We have a whole bunch of languages it can format as. Then do code. Let's just do hello world, this will be the --
JASON: Can I pull this in?
JAKE: Yes. And then title. And this can be whatever we want it to be, like HTML. Wonderful. Just delete that. Okay. I think now -- oh, we need to actually --
JASON: Do I run them both?
JAKE: I'll show you. If Figma.editor type, remember from the manifest, is equal to Figma, lower case, then run design mode, and then we'll do else if --
JASON: Oh, no, that's not the button I meant to push.
JAKE: Else if Figma.editor type equals dev. In our case, this is enough to work. Run code gen. You can also run a plug-in in the sidebar in Dev Mode and that is yet another thing you can do with a plug-in. This would technically be true for that circumstance too. But that's where this is good enough for now. You can detect if we're running in code gen. Okay, so now go there, development. Let's see what happens. Okay. Let's party. We've got a code snippet. We've got a code snippet.
JASON: Look at us go.
JAKE: Anything you select in Figma is going to render that code snippet.
JASON: This is great. Okay.
JAKE: Behold.
JASON: So then what we can do is we can start pulling stuff out. So how do I get the current instances in here?
JAKE: You actually at a global level, at any point in the plug-in, can access Figma.current page.selection. But actually, arg from the function is what we want to do.
JASON: Is that the instance?
JAKE: Yeah. Well, it's a node. And we will need to know whether or not it is the instance, right? That's going to be logic we'll have to apply. So if -- you know, we could say node.name, maybe, is equal to whatever the name. We could do like if node.type is instance and no.name is whatever we call the component, then we know that it's one of the nodes we want to run the code gen for.
JASON: But the name will match the component, not the name of the thing? Because --
JAKE: Look at Figma. Episode preview is the name of the instance, right?
JASON: And each of these -- oh, wait, I have to get out of Dev Mode for this to work.
JAKE: Shift D. They're all named that, right?
JASON: Got it.
JAKE: We could do a couple of things. Theoretically a designer could rename an instance, I don't know why they would, but they could. One thing we could do is we can go instance.main component name is this would be our definitive way to check whether it's an instance of the right component.
JASON: So we would do node.main component name.
JAKE: Except that's async. We have to get main component async, and it's main component.name effectively is what we're doing. So here. Actually, not everything has a main component. So we actually want this inside of this, if node.type is an instance. If node.get main component async, like we're going to have to await getting the main component async. Main component equals --
JASON: Main component.
JAKE: Async. If main component.name is the name we're looking for, then we know. Then we know.
JASON: Okay. Now we're sure.
JAKE: Yep. Maybe that's when we return this code, and then otherwise return an empty array or we can return plain text that says we don't know how to do code for this or something like that.
JASON: Yeah. So let's do one of these. There's our guard.
JAKE: We have a default fallback of an empty array.
JASON: Default, we return nothing. Then if it is the --
JAKE: This is the new async stuff. I want to make sure that's the right -- can we validate that?
JASON: Sure, let's do it. If I come in here and I come down --
JAKE: Why is it back to -- oh, I have CSS set to default. Can you just -- click on the settings. Uncheck that and then go back to -- okay. We're not getting anything.
JASON: We're not getting anything. Jake let's look at the console. Let's log main component really quick. Yeah, we're not even in the if. Okay, great. I think the error is actually higher up. Let's go back to our code. Let's look at what's passed in on generate. And this is in the docs. Ah, we have to write no.node. We get the language in the callback so we know which, because we can have multiple languages, and we get the node.
JASON: There is our episode -- oh, wait, that's not the right one. Oh, my goodness, what am I doing? Recenter. Hey!
JAKE: Click on that.
JASON: There's my episode preview.
JAKE: There we go. If we click something else, we --
JASON: If I come down here and click in, we get nothing.
JAKE: Yes.
JASON: Perfect. It's working.
JAKE: Amazing.
JASON: Down here I need to do some stuff. I'm going to get the properties.
JAKE: Let's do -- can we look at -- I think it's get property.
JASON: I think you're right, because we did that earlier.
JAKE: Yeah, it should be --
JASON: Where was it? It was like get.
JAKE: Get property might be a getter that we can use to get property title. No, we're still going to need the IDs. We need the IDs for the funky names. Get property on an instance. That one right there. So we're going to have to do a similar thing, where we'll have like the opportunity to put our little function in like a helper to reduce.
JASON: Okay.
JAKE: Then we can pass in the property definitions or the properties. And you'll get that little map back. We can reuse all this code in a function.
JASON: Okay. We're going to move this up into a function. That function is going to be called get properties.
JAKE: From stuff, yeah.
JASON: From node. Guess we pass in a node and do one of these.
JAKE: In fact, you're going to pass in property definitions in the first case, and you're going to pass in properties in the second case. So it's just like definitions or properties is the arg. Yeah. Because they're going to be separate. They're different object types. But the keys are going to be exactly the same. Does that make sense?
JASON: Okay. Then I need --
JAKE: Definitions or properties, then just get rid of that, boom. So, yep, yep, yep, then return props.
JASON: And then -- I think I broke my brain.
JAKE: No, we're good, we're good.
JASON: Then down here, props is --
JAKE: Yep, then pass in all props. And then -- I mean, you can just get rid of that variable, doesn't matter, though. Yeah, exactly, you can just --
JASON: Yeah, why complicate things.
JAKE: That's what happens as you refactor, things become redundant, because we're actually refactoring. Here we should be able to call in the same thing. Now it's --
JASON: Main component?
JAKE: No, we're doing it on the instance itself. We can do it on the instance -- sorry. This is why your brain is breaking. We're not going to do it off -- we could theoretically do it off of the component property definitions of the main component, like you were just thinking. We could do that. We can also just do it off of instance.properties.
JASON: Properties.
JAKE: Can we go back to the docs? Where is our instance? Are we in instance right now?
JASON: Instance node.
JAKE: Yeah, then scroll down. Let's print it.
JASON: [Laughs].
JAKE: I think it's component properties.
JASON: Okay.
JAKE: Let's try it. I need to see this through. We should be doing it, it's simpler. I think it's component properties. Because we're going to have the set instance component -- we'll have to read instance component properties so we'll need to figure out what this is either way.
JASON: Okay. Let's -- oops -- run it.
JAKE: Yeah. These run by selecting something. Chat is going bananas. Okay.
JASON: Hey, look at it go!
JAKE: We wrote a function that --
JASON: Go back to the docs [laughs], yeah, love a node.node.
JAKE: Our helper function can take an instance properties or a main component's definitions. The keys are the same in both of those objects.
JASON: Right, so basically it's the same object, one is scoped to the instance, one is the parent.
JAKE: One is the values, one is the definitions.
JASON: Got it. So what I can do from here is I can -- we can take this one and say --
JAKE: Instance.component properties, props.title, right?
JASON: Props dot --
JAKE: Instance.component properties, braces, square brackets, then it's props dot upper case title, or if you want to do it your way too.
JASON: If you want to do it your way [laughs].
JAKE: Fingers crossed. Are you selecting the parent? Let's look at the console. Instances not defined. It's because it's node. Right?
JASON: Oh, right, right.
JAKE: That was my bad, I said instance.
JASON: We're closer.
JAKE: Wonderful. I think it's dot value. Hey! Look at us go. Then we can take this one, do the same thing down here. We got this, we got this. We got time. We can do this.
JASON: Okay.
JAKE: Insert is your title.
JASON: Oh, yeah, I need the title up here for our thingy. And then for image, I want my data. So it's instance data.
JAKE: Instance.get plug-in data. And the key is whatever the name is.
JASON: And the key we called it was image.
JAKE: And it's a function.
JASON: Right, right. Okay.
JAKE: Brilliant.
JASON: I don't need -- oh, goodness.
JAKE: Goodness me. It's respecting all of this white space. If you wanted to tab your boys back to the left there.
JASON: Indeed, indeed.
JAKE: Oh, my goodness.
JASON: Look at us go, y'all. We've got -- it's just working.
JAKE: It's just working.
JASON: It does the thing I wanted to do.
JAKE: Conceivably we have a react component or whatever.
JASON: Mm-hmm.
JAKE: Let's just like pretend.
JAKE: It could be like, you know --
JAKE: We're going to duplicate it. Don't overwrite what we just wrote because we're going to actually give the plug-in the ability to do HTML or react.
JASON: Should I add another thingy?
JAKE: You can add multiple code blocks. But we're going to do something else. We're going to say if, up here, then comma language after node. That's the other property here. Remember, when we in our manifest specified languages? That's what that is. So if language is equal to I think we called it lower case HTML, then we're running this. We're returning what we just wrote.
JASON: Okay.
JAKE: And then else return an empty array. And then let's go back to our manifest really quick, getting through it, it's not going to take long at all. Manifest, add another language here and call it react. And the value will be lower case react, just as a key to check. Yep. And then react. And then we'll go back to -- copy and paste all this, we'll change our HTML to a component of some kind. Yep.
JASON: We'll do it as -- let's see.
JAKE: Do it in your else. Yeah, sorry, else if language is equal to react, perfect. And then that will be JavaScript, upper case. This is the --
JASON: Oh, it's all --
JAKE: This is the Figma key for that. Then let's change this code to looking at JavaScript.
JASON: Let's just make it a --
JAKE: Yep. Wow, what a great --
JASON: Yeah.
JAKE: What a component we made in our component library. We're not going to do compose components. We'll do everything. These could be slop properties where these are paragraphs being passed, whatever we want to do, then title is react. We can name it whatever we want but we'll do react. Now check this out. When you scroll up a tiny bit above the box model --
JASON: Let me close this.
JAKE: We're only writing good code from here on out. Development. This has multiple languages.
JASON: Look at us go.
JAKE: I know what the bug is. Close that. Deselect, reselect. I think this is a development bug. React. We solved it. We just generated a react. It's that easy. Do you even code? There's a bug I think in development where we have to just reload it.
JASON: This is slick. It feels good to me, because, you know, this is what I would expect to happen, right? Okay. So let's see. We have about 15-ish minutes.
JAKE: Do we go into -- do you want to do images?
JASON: Let's do images. We're just going to swap this this way.
JAKE: The old fashioned way to do images with the Figma plug-in was to actually open up an invisible UI window, fetch the image url, draw it to an HTML canvas, get the image bites, ship it back to the plug-in API, create a fill, and put it in that way. We now have a widget API that looks like JSX, it's really cool, it's got it all wrapped into an image component. Check this out, I can copy this code. We're going to come back here. We're going to go back into our design mode, right? And so where are we?
JASON: There's our image url.
JAKE: Image url is here. Let's do const image node, right? What we're going to do is call this thing called create node from JSX async. We have this custom widget API. Widgets are kind of on canvas nodes that have a state and everything like that, very react-like. I'm going to plug this in here and we're going to hope that this works. And then console.log.
JASON: We can swap these around.
JAKE: I don't think we need to.
JASON: It should come in at like 600. I don't know what the height will be, 16x9.
JAKE: It will do like a cover image object fill.
JASON: 400 or so.
JAKE: It ultimately does not matter at all. So now we're back in design mode, right? I'm going to run our plug-in again, LWJ is what we call this? Now we're getting an error, perfect. Oh, shoot. We can't do this because we're not compiling TypeScript. We're not compiling the JSX.
JASON: Oh, right.
JAKE: But we have a way around this. Without JSX, huzzah [laughs], if there's any [indiscernible] watching, they knew that was coming. Well, maybe they did, depends which -- if [indiscernible] was watching, she knew that was coming. So this is the same thing except instead of JSX, we're doing it this way. Now let's run that again. Do we have an image somewhere? Oh, it's a promise.
JASON: It should be okay, we should still be able to do it, just async it.
JAKE: Well, now these are promises, it's going to skip past. Let episode -- promise await all is definitely something I used to do all the time, then someone taught me this little trick for going from -- yeah. And then you just say -- we don't even need to map these anymore. What were we mapping, what were we returning? We weren't running anything.
JASON: I was doing a four each. In my heart I was mapping.
JAKE: Aren't we all? Let's see, let's see. Oh, boy, this would be great if this worked. Oh, my gosh. Image on the canvas. So now we've created a new node. And what we actually need to do now is just say, we need to find the placeholder for that instance.
JASON: Right.
JAKE: And we need to set its fills to be this node's fills, if that makes sense. So I'm going to just -- what is this called? We called this rectangle, in the main component, we'll say --
JASON: Rename it to image or something.
JAKE: Image. Then what we can do is what is our parent component?
JASON: We got 15 minutes, we're good, we killed it, we're doing so good.
JAKE: So we'll say const image placeholder equals instance.children.find. So this is going to start looking at all the top level children inside of that instance, right? So that's these three right here. So we'll say, N, and we'll say N.name is equal to image. That should just give us that instead of your little handy at zero, we'll do a find instead of a filter. We should be consistent, I'm sorry. Then we should just say image placeholder.fills equals image.fills. And then let's see if that works quick. So I'm going to delete this.
JASON: Probably need to set the size differently for that to work?
JAKE: No, because it will center it on that thing.
JASON: We can just do whatever we want.
JAKE: We'll see what happens. Look at that, right? So now, we have to automate what I just did manually, which is image.remove. We create this image using the little handy dandy Figma API. We grab its fills. And then we set it on the instance's thing that we want.
JASON: Yeah.
JAKE: It's the same node.
JASON: I feel like when you were talking about this earlier, you said, I don't know if we have time for images, it's really complicated. I see there's a little bit of loop-de-loop here but it's not too bad.
JAKE: I haven't used this approach yet so I wasn't sure if we were again run into some bugs. So now, you don't have any endpoints with more than one?
JASON: Let's go back into -- I can do it.
JAKE: Back to you.
JASON: You should do it like this more often, it's fun to be able to throw back and forth with people.
JAKE: It's the same schema.
JASON: It's the same data, just filtered for future or past. Then if we run this again.
JAKE: Oh, that's a lot.
JASON: That's too many.
JAKE: No, let's see. It's running. I mean, nodes are being --
JASON: This was maybe --
JAKE: How big was it?
JASON: It's not that big.
JAKE: 377. Okay.
JASON: Can I limit these? Hold on.
JAKE: Hit cancel. Close the plug-in.
JASON: Yeah, we'll just take --
JAKE: Schedule, a slice of like 20 or something.
JASON: Wait, hold on, I can do it like -- no, no. Or schedule --
JAKE: Round robin program. It's like deejaying.
JASON: Why don't we do ten, ten is plenty. All right. Try that again.
JAKE: Delete all those, delete that. Oh, what's up, builder? What's up, Adam? Yeah, okay. Cool.
JASON: This is dope.
JAKE: We can also manipulate X and Y position on the canvas.
JASON: Okay. Can we, in six minutes, put these -- get these to drop into another component?
JAKE: Like a frame?
JASON: Yeah. Because like if I took all of these --
JAKE: Okay, yeah. We got to get going. Let's do it.
JASON: I'm going to delete these. What I want is, I want this --
JAKE: Oh, yeah. If we create the auto layout frame, that will make this easier. You don't even need to scale it. Once it's in auto layout, it will grow based on its children, right?
JASON: Perfect.
JAKE: You want to do column or row?
JASON: We'll have it do like a little wrap.
JAKE: Okay. Let's name it something so we can treat it like get node. Great. So we have a preview auto layout. Let's at the very beginning of run design node, let's find that node. Figma.current page.find all with -- well, it's at the root of the page?
JASON: Should be.
JAKE: Okay. Dot children, find. And then we'll live through all the children at the root. That should just exist. We're going to pretend that we know that's the case. And TypeScript would hate us for doing this, but it's fine. Okay. So --
JASON: Now we have our instance.
JAKE: You can actually just do container.append. I think it's append node. Can we go to the docs? What time is it? We got time. Just do append, search apen. Append child. Okay, yeah, that works.
JASON: So instead of component create instance.
JAKE: No, we're still creating the instance. We're just appending it to -- so do container.append child instance.
JASON: Do I need to move this one out of its space?
JAKE: No, it's fine. That's the beauty of auto layout. And then --
JASON: Oh, look at it go! We got to fix our auto layout, but look, look.
JAKE: We'll add a max of 1200 or something.
JASON: Look at us go.
JAKE: Now we do it for 377.
JASON: This is dope. This immediately makes me so happy, because I was just working on a layout for myself.
JAKE: And then shift D.
JASON: Where a huge amount of the time I spent was on dealing with my silly -- look at it!
JAKE: We can just inspect. Oh, we're actually react developers here, so now we come through and start selecting all these. Scroll back down.
JASON: This is huge. This is dope. So, I mean, this makes me want -- this alone, this ability to throw instance of a component into an auto layout, will save me days.
JAKE: Yeah.
JASON: Because I do this all the time, I always want to mock up, what does this layout look like, and I spend a ton of time copy-pasting data to I have realistic previews. We don't have enough time, but like the next step would be create a UI so I can choose how many I want.
JAKE: Yeah, you open up an i-frame. You could paste JSON endpoints into the UI and search, if it wasn't a static situation. I was just going to show, this isn't great for our case, but then you come here, and you publish, you can add like something here, so you publish this to your Figma profile, essentially. If you're an org, you can publish it privately to your internal org and distribute it that way. If you were performing org-specific operations with a plug-in like this, you could have --
JASON: For example, I have like a "Learn with Jason" org inside of Figma, I pay for Figma, I could publish it so I don't have to have the code selected, it would just be any project that I have open inside of my org, I would be able to run this.
JAKE: Yeah, it's the difference between like staging and production.
JASON: Yeah.
JAKE: You just have this local development and production. You could publish this. The benefit of publishing it is if you had members of your org, they would all have access to it. Right now this is only on our machine, right? So you can also do some interesting things in Dev Mode like I come in here, set it as default as an individual, but then org admins, if it's an org plug-in that does everything the org needs, you can set it at an admin level. I did not mean to click that. But yeah.
JASON: This is incredible. We've got a lot of power here. We've got a lot of flexibility. I have a million more questions but we don't have enough time for them. So for folks who want to go deeper on this, what additional links shall we share? Let's do the switch again.
JAKE: So I've got like an figjam file with a bunch of developer links, developer resources, it's that one. You can clone that to your own -- like that's one way that we like to kind of share information, is publish to our community like that. But then there's also like if you go back to the links here that I sent you, like plug-in API docs we were just looking at. We also have plug-in samples repository on GitHub which there's a link to in there. Then I have like a work GitHub account with a lot of Figma-related stuff including some of the plug-ins I've made, if you want to see more powerful plug-ins, I open source everything I build for the community. And then my personal side is Jake.fun, if you're interested in learning more about what I do personally, lots of fun web stuff. My personal GitHub is on there. And lots of little experiments. Web audio, I do a lot of web audio stuff.
JASON: Yes, I'm actually -- your website is really fun.
JAKE: My CodePen is fun too.
JASON: Will you pull up your CodePen? You have one of most fun covers I've ever seen for a certain value of fun, it's also a little unsettling.
JAKE: So I started like -- I started like taking my full name out of all my things. This is my old -- this was one of my first fun things. This is like AI chess that is a not-smart AI, it's very silly. This uses your webcam to change music based on the color you're holding in front of it. This one is like a big music thing that I did a long time ago, this was the most popular pen I ever did. There's whole bunch of random stuff in there. If you like front end, I do too.
JASON: With that, we're effectively out of time. I'm going to quickly switch us over and do a shoutout, thank you very much to Netlify and Nx for sponsoring this episode. Thank you to Lee from White Coat Captioning for being here to caption. Thank you to Jake and Figma for setting us up in the office today.
JAKE: Of course.
JASON: With that, we're in fabulous shape. I hope you have a good day. We'll see you all next time.
Learn With Jason is made possible by our sponsors: