Anton Borries

Saving Time and CO₂ - A story about a custom Design System

Transcript

Anton

Hi everybody. Yeah, I'm going to talk about Harmonize today. So really, really quick for me. I'm Anton, as Vadim said, I'm the author of Home Widget. But like day to day, I actually work at 1.5 and we're Europe's leading clean tech startup for CO2 neutral energy, heat and mobility. And so as that, we actually build a lot of software, both for like customers who have a PV system, for example, to see what is their PV system producing, but also for our installers like installing these systems. And so beginning of last year, we wanted to shift a bit on how we actually built that software. So we wanted to make sure that it's really scalable, that we're really fast building it, and that it's like super consistent across the whole user journey from getting to know what are the possibilities of building like this system to actually having the system and seeing what's doing. And so we wanted to have all of these things for our devs, but also for our design team and really for all teams and all tech stacks. So in order to have like devs and designers be scalable, have speed and be consistent, we really need collaboration. And collaboration from you, for me, is first and foremost about communication. And communication really starts, I think, to talk about the same things. So a component like this, we may call it app bar, but a designer may call it top bar. If you're like me and you come from like an Android background, you may get flashbacks now if I say this used to be a toolbar. Components need to be the same name, but also like a color. Imagine you should implement something like this. What is it? Is it primary color, brand color, accent color, purple, purple 60, whatever that means. So we really wanted to make sure that we harmonize for our designers, for our devs across all systems. And so that's why we built Harmonize, which is our design system. And we decided that for this design system, we wanted to have our designers lead this effort. And they said, okay, if we can decide what we want to build, we want to build an atomic design system. For those who don't know what an atomic design system is, you really start with atoms. So these are like your color tokens, spacings, typography. If you have then these kinds of things, you build molecules out of these. These can be your buttons, your controls, progress indicators, really small, in our cases, widgets, built out from atoms. And then you take all these molecules, combine it with more molecules and atoms, and you build organisms, things like input fields, tabs, list items. And so you build out all of these things and you get a really nicely built and consistent design system out of this. So on the Atom side of things, our designers build it with Figma tokens. And what we did is build a custom pipeline to generate Flutter and Dart code out of these Figma tokens to generate theme extensions so that we really have parity and the same thing. So if you look again at our color example, inspecting it at Figma, it turns out the color was actually content interactive. And so in code, as I said, we are generating theme extensions. So a dev would access it like this. And so you can see you have the color and you access it by colors, content, interactive. So for each of the color and each spacing token, like devs, they just have to look at the Figma design and can get easily to what color token they should actually use. And then we took all of these tokens and atoms that we have and we built out our custom component set. And there again, we wanted to have component parity. So this is an example of our metrics component, which we use, for example, to see what is my PV system currently producing. So this is how for the metric the Figma configuration panel might look like. So these are all the things that designers can change when adding this component to a Figma design. And then we have a harmonized metric. So you see we have the same name, just put in the harmonized in front of it. And these are all the options that a dev then has in the constructor. And so for each element, like the leading icon, the trailing icon, the label, paragraph, all of these elements has like the same representation with the same name and the same options in code as it has in design. So whenever you have to implement a feature, you just look at, okay, this is the component a designer used, and these are the things they adjusted. And then you can just take the same thing in code and it's like super easy. And so out of this, we are now at around 100 components of variations. It's like a bit hard to actually count it. So I settled for a nice round and big number. But yeah, it's constantly growing and constantly evolving. So just two days ago, I added a new component, for example. So once you have all of these components, the cool thing is then you can really establish patterns and frameworks to really nail this, the consistency that things are always the same. For example, snack bars that we provide like a super easy way to show a snack bar. So we have a show harmonized snack bar, we give it a harmonized snack bar, and we can build the snack bar. And then as a platform team, we strive to make sure that just because we have this, this thing theoretically, we want to make it even easier for our devs to really build things with it and just use a Riverpod extension, for example, to just say, okay, show a success message. And like it's super easy this way. Another example, for example, is onboardings. Let's see if the video now plays. So we have a lot of educational needs in our app because we have big energy graphs where we want to show onboardings. And so we have a harmonized popover for this. So we just have a harmonized popover controller and then we give it some popovers and everything else will be handled. So if we look at this popover, we really give it a position. So should it be above or below a certain widget? We use a link, which is a layer link, and we use composited transform target, composited transform follower. It's not as hard as the sliver names earlier, but still quite a long widget name. And then a scroll key, so we automatically can scroll to the element when the user wants to get to the next step. So really, this allows us to establish patterns and frameworks we want, or what Manuela told earlier about semantics. We can just put the correct semantics to the correct components and really ensure that the accessibility of the app, for example, is really consistent and really nice throughout the app. So building a lot of components and implementing stuff, when does the collaboration actually happen? So if you look at like a feature development cycle, obviously there's like exploration time beforehand, but that's for the product people, I guess. So we split it basically down into design, development and QA phases. And so relatively early into the design phase, we encourage our devs and designers to have the first touchpoint together so that a dev can give input on a certain design to say, okay, this may be a bit difficult to implement. Okay, we need maybe a new component for this, and then we can build the component during the design phase. So once we get to the actual development phase, the component is ready to use for the dev. And then between design and development, we do a handover to like this new annotations at Figma, for example, to really ensure that we get the details of the implementations right. And then before we actually merge it, at the same time as we do a code review, we do a design review using WidgetBook in this case, so that the designer can, before it actually makes it to a build, before it makes it to QA, can have a review and really make sure that what was implemented is what was designed. And this way, we can really ensure and take also like burden away from our QA teams that they can make sure the feature works and not how the feature actually looks. So, did we reach our goals? I would say yes. So we migrated our app to the new design in less than two months with like a super small team. Actually, like last year at this conference, the day after the conference, we presented like the first migration screens to our CEO, got approval luckily. And then as I said, it took us less than two months to migrate the full app while also continue building stuff. Things like dark mode we added in in less than a week with like two persons because if you look at all our components like they are built using these color tokens so we just created a new color set for a dark mode and can easily switch the web also since we have our design system and we are working with our design system, we are with bi-weekly releases of app. And I realized that bi-weekly can both mean, I think twice a week or every two weeks. So we are at every two weeks, we're not releasing twice a week. But yeah, we really get to really consistent and fast release cycles to bring new features as quickly to users as possible. We are also using it across the whole organization in overtime teams now, the design system, and we're using eight and counting products using the design system. And when we ask our designers and devs, like, does it actually help you? Does it save you time? They say per task per like in a week, they save more or up to 30% of their time, which I think is super, super cool. So, couple of key takeaways at the end. Generally, Flutter is really great for building custom UI. You can get really far with material, for example, as well as styling material. But also building custom UI elements is, in my opinion, like Flutter is the perfect tool for this. When you build custom things, make it hard to break things. So use lints, for example, to ensure that you use the correct component from a design system and not a material thing. And then we provide options to change things in the components, but only the ones we want people to change. Like we don't want to have a metric, for example, where the value is all of a sudden yellow. We don't want this. So it's possible, but not easily possible. And lastly, talk to designers. I figured designers actually are kind of nice. So that's it. Thank you. These are my socials. If you want to fill out, like there's a quick survey, like super quick. There's also a question whether you want at least parts of it, like the Figma to code pipeline or the design system as a whole, if you want that open source. If you all press yes, maybe I can convince my manager to actually make this open source. If you want to use Harmonize right now, go to jobs@.1.5.com. We are hiring at the moment. Thank you.

Vadym

So actually, what's your favorite widget?

Anton

From the design system, you mean?

Vadym

From design system.

Anton

So we have a thing called a harmonized action sheet, which is like a popover style thing. And it like automatically adapts to be more of like a sheet thing, like in the YouTube app, for example, on mobile factors. And then when you resize the window, it actually gets like a popover that's attached to the component. That was quite fun to build. I mean, that's the one thing is which was the most fun to build. But it's also quite nice to use.

Vadym

Can I see it one day? Okay, no, no. And then a few questions of course from the community, from people who are sitting here. Then does Hermanized build on top of material or were you able to exclude it?

Anton

It doesn't build on material, so it's built custom because we just figured that in order to have the correct parity with what our designers are using and building, we probably could have gotten really really far with just styling material but it's just hard to really nail it to... Because I'm not Material Mike so I don't know all the properties I have to set for material. So having all of these atoms beforehand it was just easier because I could build the components the same way our designers were building the components.

Vadym

Yeah, and I think that's actually the question right now about including plugins with UI. So how do you manage to integrate easily packages that are deeply built in with material widgets?

Anton

We don't necessarily have the need. So like one thing is like, for example, date pickers, where we just like make sure that we use the styling options they use and then we provide our tokens into the styling things. And this has been working really good so far. For example, also the vault model sheet is like really nicely stylable. So we were able to make this work for us.

Vadym

I see. And how do you... It's already end of the day, so I'm tired a bit as well. But... How do you actually export tokens from Figma? Is it a custom plugin or something?

Anton

Right now we're using like a plugin that just generates like a JSON file out of it. We want to actually at some point get to the point where we get the, where we use the API of Figma to then like have it pipeline and like whenever a designer publishes a token change, for example, it just happens automatically because there's a bit much manual work involved right now, but we are not updating our tokens too often, so it's still fine. It's a matter of time and priorities and we are quite happy with where we're at. It's just that you never run out of ideas.

Vadym

Yeah, I think there are always a place for optimization and improvement. If it works now, it works. And then if there is some spare time and money and anything else, we can do an improvement. And probably we'll ask you the last question from the list, because people are getting more active in the end of the talk. So...

Let me, let's ask this one because it's upvoted at least. Is it a library or is the code in the code base directly? If it's a library or directly in the code?

Anton

So yes to both. So we use like a monowepro approach. So in the end, our library is a package separately from the app itself. And we use it across multiple apps actually.

Vadym

Okay. So yeah, yes to both. Familiar situation, yeah. Monoreapers are getting more famous, more used nowadays. I got it. Then probably I won't ask all the not upvoted questions because I want you to keep energized and active. So thank you very much, Anton. Thank you for coming here, for giving this talk. How was Anton?

Edit on GitHub