Conf42 JavaScript 2020 - Online

- premiere 5PM GMT

Building React frontends visually

Video size:

Abstract

Plasmic is a novel visual builder for React and the web generally. It enables super-fast creation of maintainable, production-ready presentational components that can be imported into arbitrary codebases.

Design tools are fast and amazing tools for thought, but for a host of reasons are limited to creating drawings rather than production assets. Developers must instead re-create surfaces from scratch, by hand, using code (often heavily using tools like the Devtools CSS inspector, the closest thing developers have to a design tool). This inevitably leads to discrepancies and back-and-forth with the design team, and ultimately two sources of truth that are never truly in sync.

Summary

  • On the web today, the status quo is to write everything in code. Now there are visual creation tools that let developers actually build production uis. There are also website builders. How can a rethought development experience look like for the web?
  • This brings us to the last category, which is UI builders for web apps. These are all about bridging design and development, but they all have very different takes. The idea is to start with rough, exploratory designs and refine it into something that's robust.
  • We really try to streamline and simplify a lot of layout in CSS. The way that state and variations of a component are all modeled in plasmic is through this unifying concept called variance. You can actually switch between my base appearance and my completed appearance.
  • Todo app is just a skeleton starter that's generated for your convenience. But you can actually do whatever you want with this file. You can flexibly wire up any props that you want on them. Plasmic watch will live stream any edits I make in the editor into my code base.
  • Plasmic is a client application with a lot of complex state that is constantly changing. What makes this application tricky is the combination of latency with scale. This is where tools like state management frameworks come into play.
  • Another imported feature of plasma is one that I haven't shown in this demo, is code components. This is about the ability to bring in your existing react components, maybe from your own code base or maybe from a library like material UI. The goal is really to automate away and do as much as possible of the grunt work of translating designs into web standards.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
If you're a developer on a product team today, you probably know about design tools. Developers sometimes get to work with product designers or UI design who use these tools like sketch or figma, and these are basically vector drawing tools. They're very good at letting you quickly mock up uis and explore lots of different ideas rapidly, without investing the time into necessarily writing any code. But then when it comes time to collaborate with engineering, that's where things can get complex. Engineers have to essentially recreate the uis from scratch by hand, using code, and inevitably a lot of things can get missed in this translation process, or it can just be hard to translate because designs are freeform drawings. And so this leads to a lot of back and forth with design. And ultimately you have these two sources of truth that by most teams admission are never truly in sync. Now there are visual creation tools that let developers actually build production uis, and they're nothing new. They're actually very widely used on other platforms like iOS and Android and Windows, but not really so much for the web. To make one that fits well with the web means fitting well with how apps are written today, which means integrating in a natural way with code that is just increasingly written using these compositional component frameworks like React or view. And also, UI builders are generally perceived as clunky and very technical, a very far cry from the ease and speed of design tools. But anyway, on the web today, the status quo is to write everything in code. So there's a question of what a rethought development experience could look like for the web. How can we simplify things? There are also website builders. Website builders are everywhere. Here's a tiny fraction of them. These can all actually be quite different from each other as well. Some are simpler and more for nontechnical audiences like small business owners. And then there's others like Webflow, where you basically need to know CSS layout. But they're all focused on static websites, optionally hooked up to some content management system. But if you're working on a web app where you have an actual team of developers, or you have a database and user accounts, and I think most importantly just custom business logic, then static site builders aren't really meant for that. So this brings us to the last category, which is UI builders for web apps. This is actually a much more nascent category, so these logos are probably recognized by far fewer people, but it's emerging really fast. And this is actually just a subset of players. These are all about bridging design and development, but they all also have very different takes, so it's hard to summarize all of them together. Like for instance, modules lets you theme a design system of primitive components. Hadron lets you craft web components, Visli lets you craft react components. It's been really exciting actually to see all this activity and just raw tooling innovation happening. I work on one of these. I work on plasmic. So I'll give a quick demo of plasmic just to show one stab at what rethinking developer experience could look like. So this is plasmic. It's a browser based tool. And for this demo, I'm going to create two do MVC, which just a refresher of what everyone's favorite reference app looks like. I'm not going to create the whole thing. I'm actually going to create a subset of it, and I'm also going to create it from scratch. We have a different demo video on our website where we show how to start from a Figma file. So we have this figma plugin that lets you turn one of these figma documents into web standards. And so that's another way to get started. For now, we'll just directly draw on the canvas. You can directly add text, add boxes, et cetera. And the whole idea, the whole workflow that plasmic really tries to enable for you is to just start with these very rough, exploratory designs, not worrying about layout or anything like that. And I'm drawing this box for the task and the checkbox in it. I'm going to make the checkbox rounded. And here I'm just starting by creating these wireframes. And the idea is that you should be able to start with these and then refine it into something that's real, that's robust, that has proper layout and everything. So the idea is just start from scratch, refine, refine, refine, and you end up with something that you actually ship into production. So this task, I could now copy and paste this a bunch of times to have a list of tasks. But now if I actually want to style this thing or update one of these, then I have to do that manually for all the different copies. So instead of that, I'm actually going to right click this and create a component out of it, a reusable component called task. And now if I paste this a bunch of times, then I actually get instances of the same components. So if I double click into an instance, I'm editing the primary copy of the component. So if I drag this around or move things around, then you can see all the instances update as a result. So I just kind of drew some boxes. That's pretty much it for my wireframe of what I want the app to look like. Now from here, I'm going to start applying styling to make it look more like the real thing. And I'm going to start with this title here. I'm going to make it super thin and I'm going to apply some coloring to it. So maybe this light red color and this background here, the whole page, I'm actually going to set to be this off white, warm gray, something like that. And this task itself, I want to be just pure white. And this checkbox, I actually also want that to have a light gray border and just get rid of the background there. And I'm going to fidget with its text a little bit. It's a little small right now. I'm going to make it larger and just adjust its position a little bit. I'm going to set its text color to be something lighter. I'm going to make it maybe something like that. And I'm actually going to save this color as a reusable color token called text color. And so color tokens, spacing tokens, mix ins, these are all concepts in plasmic that let you create more maintainable, scalable designs. And actually they're very close to what you get when working with code. Now I have this list of three tasks and they're just kind of haphazardly placed. Let's say I wanted to introduce real layout. So what I can do, one way to introduce that is I can lasso these into basically a vertical stack like so. And these stacks keep everything distributed and organized. These are actually powered by Flexbox and you can see the controls for this. But we really try to streamline and simplify a lot of layout in CSS. And to show that, I'm going to right click this background to get rid of it. And I can basically, for instance, for this container, I'm just going to snap everything two the top to the left. I'm actually going to double click this bottom edge to auto size the content vertically and also in the horizontal direction as well. So these are some of the simpler features of the layout and we'll see some more interesting features in a little bit. Now, I have this element here, this container. I'm going to give it a name as well. I'm going to call it task list. And you can name elements just to keep your elements organized. And also this will come in handy later for the actual code generation part. These three tasks, they currently are kind of boring because they all say the same thing. I want them to be different and in fact I want the text to be variable. So what I will do is double click this again to drill into it. I'm going to right click this text and convert it to what's called a slot. And slots are kind of like poking a hole in the component. So from any one of these instances, I can select that slot and just change its text to make to do app show, demo, et cetera. But you can actually fill these up with arbitrary content, any number of elements. Now, that is almost it for my app. The only other thing I wanted to do is actually design these tasks in their different states. And this is just a very common thing for components in react. Certainly you want two make them appear differently in different circumstances. So instead of actually just keep double clicking into this task to keep editing it, I'm going to right click this and pop it out into its own new artboard on the side. And this is so I can edit it in isolation. If you're familiar with react storybook, it's the same general concept of just working on things by themselves. So here I'm going to start showing this concept of variance. And the way that state and variations of a component are all modeled in plasmic is through this unifying concept called variance. And I'm just going two, show this in action. So I'm going to create a variant group called states. And inside of states I'm going to create a variant for what my task looks like when it's marked completed. Maybe I want to design what it looks like when it's being edited and when it's marked high priority as well. So these are different states that this components can be in. And for this exercise, I'm just going to design out what the completed state is and I want there to be a checkmark in this checkbox. So I'm actually going to screen grab this checkmark from here because I just like the look of it. So I'm going to screen grab that like so. And back here I'm going to paste it in there and I'm going to zoom in actually to a pixel to adjust it. I can also use railayout for adjusting this. It doesn't really matter in this case. Now, after I do that, I can actually switch between my base appearance and my completed appearance. So you can notice that those changes that we made were actually just getting recorded specifically for the completed state and not affecting the base state. These are not different copies of the components that I'm looking at. The completed state is just a set of overrides or deltas on top of the base appearance. So to show you what I mean, I'm going to clone this artboard and have it sit side by side, and I'm going to set the bottom one to look at the base appearance and top one to look at the complete appearance. And if I make more changes to the base appearance, you can see those bleed through to the completed appearance, but any changes that I make specifically that are getting recorded to the completed appearance will stay within there. So as another example, I'm going to make this text strikeout and change its text color to be lighter as well. So you can just change any part of a component like this. Now, the thing about variants is that you can dynamically combine any number of them. So for instance, I'm going to introduce another variant here for my hover state. And hover is actually just a very common interaction, similar two pressed, et cetera. So there's like this special built in support for those states. And basically whenever I hover over any part of this component, I want this box here to become darker. So I'm just going to scroll down Yang Zhang its border color to become darker, like so now I can actually try this out in preview mode and I'm hovering over this thing. Okay, so that's close to what I want. But I actually realized another thing that I want is for there to be for this cursor to become a hand pointer as well. So I'm going to just set that here directly and preview again. Okay, so that's a lot better. And the thing about these variants is that they come with the component wherever it goes. So back in my main screen I can select any one of these instances. I can change it just for the purpose of mocking up into, for instance, the completed state. I can also preview this whole thing and just play with it. And it's a little nuanced, but you can see we're dynamically combining the completed state and the hover state here with this middle guy. So that is pretty much it for designing out this app. Maybe the last thing I'll do is tighten up the layout of the whole thing. So I'm going to set it to be a column layout and center everything and maybe add some padding to the top and bottom here, like so. And I'll turn this whole screen into a component as well, called to do app. So now my project has these two components. My to do app components, my task component from here. This part is the interesting part, which is how do we work with it from the code? So one way to get started is actually just through our code sandbox integration, and you can click this button and just spin up a sandbox. And you have basically this asset running as a standalone web app that you can directly start mucking with the code for. But more interesting for us is actually generating code into our own local code base. So there's this client that helps you with that. And I already have installed, so I'm going to skip the step. And the two other steps are basically running plasma init. And this is just a command you run every time you want to get started using plasma in a code base. So I have here in my terminal this basically, it's a blank create react app. And just to show you what that looks like, it's just a spinning logo. And I'm going to run that plasmic init command here. It's going to ask a bunch of questions that I'm going to answer with the defaults for. And the only other command here is this plasmic sync command, which is what actually pulls down the components from the project. So I'm going to go back to my terminal, and so now we have this to do app and task components synced down. And I'm going to pull up my code editor on the left and have my running app on the right. And just the first thing I'll do is just get things on the screen. So I'm going to replace all this boilerplate with just rendering this studio app like so. And now I should see exactly what I created in the design tool showing up as a pixel perfect component in my actual react app. From here, this is still the static mock data. So let's say I wanted to replace it with my real data. So what I can do is I'm going to double click this to do app to drill into it. This file has a lot of comments, but I'm going to get rid of these. So you can see that it's actually just a very simple file. This whole todo app Component is actually just a thin wrapper around the plasmic todo app component. So the plasmic Todo app component is this dumb presentational component that handles all the rendering. And this is actually generated by plasmic and is regenerated by plasmic. And we'll see that in a little bit. But Todo app itself, this whole file is just a skeleton starter that's generated for your convenience, but you can actually do whatever you want with this file. You as a developer own this file. So for instance, if I actually wanted to start introducing state or behavior to this, I can just do that here directly. So I'm going to start by adding some state for my tasks. And let's say my task objects are just simple js objects with can in property do stuff like. So I'm going to have three of them. And now I'm going to wire up this plasmic two do app components with the actual tasks. And to do that I'm going to reference one of the elements that I named previously. I'm going to reference it by name. So this task list, I'm going to replace all of its content with my own set of tasks. And to render these tasks I'm going to use the other component that we synced down, this task components. So now I have my own data showing up in the app. And so this is how you can work with these plasmic components, is you can just flexibly wire up any props that you want on them. Now, the real highlight of plasmic is that it's not just a one time code export, but you can actually go back into the editor and make changes to your design and those will be kept in sync with the code. So I'm going to run plasmic watch, which is just this mode where it'll live stream any edits I make in the editor into my code base. And I'm going to have the running app on the right and the editor on the left, like so. Actually don't have a ton of real estate here, so it's going to feel a little squish on the right. But now let's say I wanted to make some violent changes. Two, my layout. So instead of this vertical list, let's say I want it to be a set of tiles. So I'm going to double click this component to start editing it again. I'm going to make it look boxier, something like that. I'm also going to start applying some relay, but to this so that it's a row top aligned and maybe with some padding all around. I'm going to take this checkbox and pop it out of its place so it's free floating and I'm going to drag it down to the bottom right of the task and I'm going to pin it to the bottom right, actually, like so. And that's it for what I want. Two, change my tasks to look like now, this is still a vertical list, and I want this to be a set of tiles, like rows of tiles. So I'm going to change this thing to go from column to row. Now everything is spilling over on the right, but I'm going to turn on wrapping so that things wrap around and I'm going to mix it fixed size so that's actually centered in the screen. It's a little hard for me to tell apart the different tiles right now. So I'm also going to introduce some gap in the vertical direction and also the horizontal direction. So you can see some of the fancier features at play with the layout engine here. And if you think about how to implement things like a cross browser gap in a way that is friendly with things like wrapping and doesn't introduce selector specificity issues, it's actually quite annoying to do. So. These are examples of things that are just very common when it comes to layout tasks that plasma tries to make as simple as possible. So anyway, you could see that as I was making those changes, these were getting live streamed into the actual app. So that is pretty much it for this quick tour of plasmic and what it's all about. So now I'd like to pull back the curtain a little bit and talk about some of the challenges that went into building this thing, including both technical challenges and product challenges. So the first one I'll start with is just the state management infrastructure. So this is a very sprawling client application with a lot of complex state, and it's state that is constantly changing. And there's also a lot of surfaces that are reflecting out various parts of that state. And there are certain operations, certain interactions like drag operations, where if you want it to be smooth, which means if you're shooting for, let's say, 60 frames per second, then you typically have a frame budget of around 16 milliseconds. And if you want to make sure you're not busting that budget, then what that means is you just want to make sure you're doing the minimum amount of work that you can get away with per frame. And so this is where a lot of tools like state management frameworks come into play. They're all about minimizing in various ways that are more or less ergonomic for developers, just minimizing the amount of work that react does, the amount of rerendering that you do in response, two state updates. But what makes this application tricky is the combination of latency with scale. So to show what I mean, this example here, we have a canvas with these three artboards, which is a pretty simple project. But if you imagine a project with hundreds of artboards on the screen, then things get a lot diceier. What you don't want to do is to simply naively just make a synchronous update to your state and then have everything rerender as a result. So an example of a thing we do instead is we break up our updates into small chunks so that we can incrementally and lazily evaluate these updates, these rerenderings, I should say, we can actually see this in action. So as I am dragging around this checkbox here, you can notice that if you watch the other artboards, there's a slight delay and lag between when I moving this one around and when these others update. And that's actually an artifact of our scheduler in play. So there's prioritization of these different artboards where the one that you're manipulating directly is highest priority. The things around you are lower priority, and the things off screen are lower priority still. So that's one example of a way we actually break up some of the work here and then actually prioritize and schedule them. Another imported feature of plasma is one that I haven't shown in this demo, is code components. And this is about the ability to bring in your existing react components, maybe from your own code base, maybe from a library like material UI. And there's a lot of challenges here, such as simply making it easy for users to bundle up the components that they care about without becoming experts in webpack or just dynamically loading the modules into the runtime, because you're essentially injecting this foreign third party code into the canvas, and you want to do that in a secure and isolated way. But, okay, so even once you have your material UI button showing up in the canvas, how do you actually configure it and work with it? So that's where plasmax language tooling comes in. And this is basically about crawling your code base. Two, find the components available in it and reflecting out their interfaces, whether it's documented using typescript or prop types. And this can be nuanced because there are some props that you expect to show up as controls in the right hand panel, for instance, various knobs. And there's other props, like children props, or function as child props, where you expect to directly manipulate them on the canvas through drag and drop. On top of all this, there's these additional problems that I haven't talked about, like just harvesting out examples of how to use the components, because oftentimes that's also very well documented in code bases or documentation as well. There's also a slew of product challenges. So here are a couple. One is about distilling layout into a small set of intuitive controls. CSS layout is notorious for being hard to use, and layout is just such a pervasive aspect of creating uis that plasmic really focuses on trying to streamline that as much as possible. CSS comes with a lot of different concepts, both legacy and modern, and different overlapping ways of achieving the same thing, but with different trade offs and subtleties between them. And to this day, I still spend time debugging which props affect the declared height of can element, so that percentage heights respect that and just other minutiae of CSS. And this is actually really infuriating, because the answer changes in browsers over time. So plasmic tries to unify and simplify a lot of these concepts and distill them into simpler controls that cover the most common cases and then give you escape hatches to actually drop down and exercise full control over your flex basis, et cetera, if you really care to. The last aspect is something I alluded to in the middle of the demo, but it's the ability to actually bring in your designs from other design tools. And there's a lot of challenges here, actually just around mapping the concepts across these different domains. So this is about taking, for instance, Figma's document representation. And that actually is something that is very rooted in graphic design backgrounds. So you have concepts like layers and layer masks and blend modes. And in CSS, for instance, you have inner and outer shadows. In Figma, you have centered borders. So reconciling these impedance mismatches is a big part of the product challenge there. And the goal is really to automate away and do as much as possible of the grunt work, this rote work of translating designs into web standards. Code integration is, I think, the most important challenge for plasmic. If you think about what is natural for visual direct manipulation, and also what's natural for expressing code, we're essentially trying to marry the best of both worlds, and we're trying to find the most natural and flexible interface for doing that. This flexibility is there for practical reasons, right? Just at the end of the day, I need to instrument this element with a certain prop or event handler or behavior. But there's also what I'll call, quote unquote, aesthetic reasons as well. So I want to control what my component API looks like. In this example, I have this task component, and it takes the children for the content. But maybe that's not the interface I want. Maybe I want this task component to take a task entry data object, right? And then internally it can derive what content it should render, what state it should render in, et cetera, from that task entry object. So this is what I mean by control over the component API. So our thinking is always rooted in just giving developers as much flexibility as possible so that the code generation is only there to help and never to hinder. So we use plasma for building plasmic. And in terms of the impact on our own workflow, there's a few things I want to call out. So the first is around this design first mentality, which is about forcing you to think about the end goal, the product and the experience that you're going after, and then filling in the code in service of that end goal. So this is really nice as a top down approach, right? Making sure you're building the right thing. And bottom up approaches definitely have their place, especially in projects with high technical risk. But it can also be more bumbling for other kinds of projects. The second impact on our workflow is if you are lucky enough to be working with a technical designer who can wield something like plasmic, then there's just something very magical about running plasma sync and then seeing a nicer version of your landing page show up in your code base, which it's definitely a direction that we want to explore a lot more is broadening this tool to make it more accessible to thing I'll call out. In terms of workflow, impact is just the elimination of an entire class of visual regression tests and manual QA tools. So, for instance, we have these storybook plugins that would help you compare your implemented components with your designs. And that's obviated by the fact that this tool is essentially a declarative language for you two. What you see is exactly what you get in the final product. Anyway, that's all I want to share about plasmic. It's still really early days for us, but also for a lot of the tools in this camp. I'm actually really excited about this entire category. I think there's just a lot of innovation happening that I think could really transform what front end development looks like. So I definitely encourage you to check out these tools. We'll also be sharing our progress on Twitter. And the last thing I will call out is that we are hiring. We're a tiny team of five people total, three on engineering. So if these challenges sound like fun, then let us know.
...

Yang Zhang

Co-Founder @ Plasmic

Yang Zhang's LinkedIn account Yang Zhang's twitter account



Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways