A Shared Language Through Design Systems
A Shared Language Through Design Systems
I am no expert on the subject of Design Systems but what I am, is bilingual. I grew up in graphics and design was my first language. I moved to development and lived here long enough to start dreaming in code.
What I am is an interpreter fast becoming adept at catching the subtle nuances easily lost in translation, acting as a go-between when designs are switched to code. Focusing on my team's journey on creating the spacing for Zoopla's design systems. I will touch on the:
- communication challenges between design & engineering
- the skills I used to be the bridge between both roles
- process in creating a shared language between the product team, and
- any future improvements I can foresee
I love design systems. I watched talks on them. I've read books about them. Believe me, when I say I've done my time studying the theory. But it wasn't until I started working at Zoopla and that's been about 18 months now, that I've actually had the chance to really get my hands dirty, working on a design system. To collaborate with both designers and developers on building a design system, to experience the teething pains of working on a design system that's in its infancy, and to appreciate just how hard getting this right can be.
Now, I can hear you wondering why on earth you should carry on listening to me, talking about design systems when clearly, I'm no expert on the subject, but yeah, I agree. I'm no expert, but hang on a minute before you go stay, stick with me because what I am is bilingual and let me take a moment just to explain that point.
So, once upon a time, actually, quite a long time ago, I had this notion that when I grew up, I'd be working in advertising. So, I went off to study at art college and my sketchbook went everywhere with me. I was all about the visual communication. I essentially grew up in graphics and design was my first language. But a career journey takes its twisty turns when you start packing that box of life. And in mind there was marriage raising two kids, plus running a home business and you get the picture. So, eventually I came to a point work-wise where I got itchy feet. I was ready for a new challenge. And I decided to pack up my career back and relocate to development. And I've lived here long enough now that I've started to dreaming code. And I can just about hold my own when the conversation turns technical, but unbeknown to me, having lived both sides of the border, I was to find my niche as an interpreter located somewhere in between the realms of Design and Engineering. And I've become skilled at catching the subtle nuances that are easily lost in translation when design gets switched to code.
So, I'm talking to you now as that interpreter about my team's journey in creating the spacing for Zoopla’s design system. Now, I won't go into the nitty gritty of what we actually built, but instead, I'm going to focus on the communication challenges that we faced between Design and Engineering. How previous knowledge was useful for me to become the bridge between both roles and the process that we took in creating a shared language that everyone can understand. So, I'm going to start by talking about the communication challenges we had. In particular, when we started to work on our spacing design tokens, and our first give you some context on the product teams and the design systems here at Zoopla.
So, this talk involves the consumer teams who work on the Zoopla website and app and the customer productivity teams who work on property software products for estate and letting agencies.
Design controls a series of Figma files and these are broken out into foundations, patterns, basically, this is loosely based on the atomic design principals and these files determine the basis of our component libraries that are maintained by engineering. And to begin with our design system served only the consumer teams working on the website and app. And we started to build out a very similar pattern now for the customer productivity teams. And that's actually one of the teams that I work in. And we've got a collection of centralised design tokens that hold all of this together with an additional layer of tokens on top that are specific to particular products.
I'm not going to go in depth about design tokens, but if you do want a starting point to find out more, I have included a link. But basically, design tokens are variables that we use throughout our code, and they give us a single source of truth to control global styles, like color, typography, spacing and I've grabbed a few examples here from our code base for you to see. We were working on the first iteration of our version of the design tokens and whilst doing so, we wanted to provide feedback to design from an engineering perspective to voice concerns, ask questions and propose some changes. We took the opportunity to start discussions early and this was important for a number of reasons.
Firstly, if we can achieve consistency with how we name and apply our design tokens, we can build a shared language and understanding not only between the functions of Design and Engineering, but also across our consumer and customer product teams. And did I mention that design systems are hard? Well, our experience here at Zoopla has not changed that story one bit. We're following hot on the heels of the consumer teams on our design systems journey. So, we're really keen to make sure that we learn from previous mistakes and communication is key to sharing those learnings. If we don't talk to each other, not just within our own teams, but across different functions and product areas of the business that are also using the design system, then we will disastrously keep making the same mistakes over and over. And lastly, we needed an agreement on the shared foundations now, because if any fundamental changes are made, then the code base is built on top will have to be updated. And generally designed tokens don't tend to change once they've been set. So, if we can make those changes early, then we can minimise any resulting impact. And the spacing tokens were top of our list for concern, because we didn't like the current naming convention, which was linked directly to a pixel value. If this value changed, then we'd have to update all the tokens accordingly. So, it made sense to us to stay clear of name variables, and instead take an abstract approach.
The proposal was to have a naming strategy that defined multiples of a base unit. But before we could even start that discussion, we realised that we didn't have any process in place for making improvements to the design system. So, we decided to address this first and put together a new proposal process, which looks like this.
The first step is to create an RFC, Request for Comment. But this alone is tricky. We've got documentation in multiple places like many places do. So, engineers tend to put their documentation in confluence and in Google Docs and the source code itself is coexisting in different locations. So, we've got one code base in GitHub and the other is in GitLab, not to mention that our designers were documented in Zero Heights in Frontify. So we needed to be confident that the RFC was shared, where it would be seen, read and engaged with. And we decided that the design system, Slack channel was the most appropriate place to kick off the discussion because it was the one place that everyone had access to regardless of product team or role. That in itself, doesn't guarantee that people will join in with the discussion. So, if we can get consumer and customer tech leads to champion the proposal and making sure that it had visibility in weekly update meetings, then we can safeguard against the RFCs gathering dust. And we wanted to be mindful of any previous issues and the context around that. So, we've got in touch with an engineer from the consumer side, ran through our proposed name change to the spacing token, and then we listened. We knew that during design handover, Figma only shows pixel values. If Figma could display the spacing token name instead of a raw pixel value, then we were in agreement that an abstract naming convention for the spacing token would be an engineer's preference, but we weren't in that position yet. Because Figma only displayed pixel values, we learned that actually the reality is abstract token names, right now, demand too high a cognitive load during handover. Designers think in pixels. The code base had a base font size of 16 pixels, but engineers then map that to REMs because that's the code base unit of choice. This made it harder for an engineer to mentally map spacing 5xs, how many pixels in Figma and then what do I convert that to for REMs?
So, our proposal had become a question. Could we get Figma to display spacing variable names? And in our quest for answers, we went to design to find out. At Zoopla, Figma is configured to use automated spacing, which doesn't use a token name. So, the answer, well, it was no. Figma wouldn't show the token names, but we also found out that actually abstract token names are harder for design to work with and there was some resistance that this could make it difficult to insert an additional size in the future. The key learning was that designers need to understand the token names too. If we move to using an abstract naming convention, we wouldn't be getting rid of the problem of cognitive load. We'd just be removing it from engineering and throwing it across the border to design.
So, it became clear that an alternative approach was needed. If we wanted to make this work for everyone. We decided to instead reset the base font size for the productivity apps to remove the cognitive complexity for ourselves, as engineers, and by resetting the font size to 10 pixels, we could keep to the current naming strategy, which directly referenced the pixel size. And we achieved a one-to-one mapping of pixels to REMs. So, instead of 16 pixels equating to one REM, 10 pixels was now one REM. So, 16 pixels is 1.6, 20 pixels is two and so on. This eases the cognitive load for the dev teams and it let us stick with the naming convention that's understood by the design teams - success! We'd reached an outcome and the fourth step in our proposal process.
The discussion has given us some very valuable information and we needed to capture our learnings in a decision log. It wasn't the outcome we'd originally set out to get, but it was a compromise that still gave us the same end result. And this illustrates the value of keeping a decision log. It's not just recalled the outcome, but the why behind an outcome. So, in this instance, it wasn't the fact that this didn't result in a change to the space and design token that matters. The important piece to log was the why not and this last step doesn't really play a part here, but we've since discovered that sometimes a discussion might only happen between engineering or only in design. Regardless, if we want to make sure that we're all reading from the same page, then we need to make sure that we have procedures in place to keep everyone regularly updated, because otherwise it doesn't take long for parts of the design system to become out of sync.
This next part looks at what happened when it was time to start using the design system. And I was lucky to be in the first product team to do just that. And this is where that previous design experience comes into play. We had a basic selection of bricks or components ready to use, and we'd laid a solid foundation with the design tokens. But what about the mortar? How are we going to hold our bricks together to build new page layouts using these components? The problem is that components exist in isolation without any context, the component doesn't know how or where it will be used outside of the component library and it doesn't need to.
To start building out new UI, using the design system. We wanted to define the relationship between the components within a given layout, but we didn't yet have any means to control that spacing. So, we looked at the consumer side to see what we'd learned from there. And one of our principal engineers, Craig had already looked into the app using the component library. And unfortunately, he found that pretty much every component was UI-glue. This issue of spacing hadn't been tackled yet. So, what is the UI glue you asked? Well, good question. Engineers were adding containers around components to start attaching space into them. There was no set way of doing this one might use margin and other use padding, or even Flexbox. Basically, the app specific components were becoming bloated with this UI glue or low-level CSS that was being added to stick components in the right place on the page and Craig told me that this was the most important thing after design tokens that we needed to get right for Zoopla design system. The challenge was to enable us to have a single way of doing layout and the longer that we continue to create this UI glue to stick out components in place, adding in custom CSS each time we composed a layout, then the higher the risk of inconsistencies and bad practice slipping into the code base. So, taking all of that into consideration, if we could use layout components to give us a set way of applying CSS for layout, then we'd improved standards and consistency. And with this new ability to add and rearrange components on a page without having to go in and manually tweak the CSS we can do away with the worry of working out what CSS to apply and speed up the development time significantly. And once the spacing becomes a reusable component, we can remove significant chunks of UI glue from the code. And take advantage of deduping and code splitting, which ultimately improves load times.
So yeah, thanks Craig. There was absolutely no pressure there then. I did some research into how this is handled elsewhere so that I could start setting constraints.and this was a little trick that I remembered from my designer days to break the creative block when you're starting off with a blank canvass. A lot of the layout components that I looked at took a utility class approach to control spacing by using a class. Maybe that's because some of them dealt with more than just spacing, like adding borders or applying background colors or setting text alignment. The example shown here are some of bootstraps spacing utility classes. So, my concern with this is that this could then become a kitchen sink where more and more options are added in over time. We're trying to reduce bloat and make things simple. So, where does the line get drawn on what gets added in and this opening up of the react API property class name is unlocking a back door that could be very tempting for an engineer to sneak in freestyle customer CSS classes, which then defeats the whole object of trying to maintain a consistent UI. These are spacing components after all and the simpler the API, then the easier it's going to be to understand and use. So, this set the first constraint not to use the className property. Now this next piece of research was the light bulb moment for me translating this into terms that I understood as a designer, even though in essence, this was an engineering task. Designers treat space as a physical thing, which is placed between elements. Space isn't directly applied to an element. Subtle differences but very significant. It's obvious when you say it and thank you to Mark Dagleish for pointing that one out and hold on to that point, because it pops up a few times.
Early discussions had mentioned that we could maybe use an isolated spacer a component, which at first glance does fit this line of thinking, but it has no concept of the relationship between a set of components, which might need consistent spacing. Think in terms of a list of items, for example. It also adds a lot more code, a separate space of component is required to define each individual space. So, that set the second constraint to use relational spacing only. And I wanted to use margin to define the space between components, but because margin affects the space outside of whatever it is that you apply it to. It's not always a popular choice in design systems. The component shouldn't have any impact on this external space because bear in mind the same problem applies to allow component it too has no idea of how or where is going to be used. So, if a layout component defines its margins, but only between its child components, then this won't impact it surrounding space and we're all good to go. So, with those constraints set, it was time to scope out the project based on the work at hand, I talked to the designer in my team, explained what I was trying to do and chose this piece of UI as the subject of our layout experiment. And look, he instinctively filled in that physical space, the space that was sitting between the components which highlighted how space changed in relation to those components. And that got me thinking what if we could make these low components, which have the single responsibility of handling spacing stay true to the spacing design tokens that exist within the design system. In other words, it's the functionality that engineering wanted, but use the language of design.
So, this became our fourth constraint to link us back to our design tokens our layout components would only understand valid spacing tokens to set the size of the spacing that we wanted and give them were using TypeScript. This was actually relatively easy to achieve and this also gave us and extra safety net. If design provides us with an agreed set of spacing tokens, then we could guard against any rogue pixel sizes creeping in from a layout. And that kind of brings us to the end of this spacing story. It's not anything groundbreaking with those constraints set, where we went on to build our box components taking inspiration from braid and a stack component taking inspiration from every layout. And of course, there is no end point with a design system. It's something that's constantly evolving. In fact, we're already revisiting those spacing design tokens to see if we can actually switch to an abstract naming convention after all. Maybe we can make it work this time. Now, that we've got a greater appreciation of the value of creating a shared language because when you start to work with a shared language, you have much better conversations with everyone. And we need that strong communication across teams, if we want to foster better working relationships and encourage people to voice concerns or suggest new ideas.
Design system is never done and we need to encourage regular feedback to make sure that it keeps working for everyone who's using it. And with a shared language, you get higher engagement. People stand a better chance of being heard and more importantly, understood. It was surprisingly easy for me to get engagement on the layout components, present back to everyone and get buy-in when the work was done. Designers were engaged. They repeated that to me. "Yes, of course. That's exactly how we see spacing." So, I knew I'd made the right connection. They were excited to see the tokens actually being used in this way and engineers were equally engaged and this enabled them to share concerns and that we could then address and work with. Ultimately, that better communication is going to bring about a greater understanding. I'm experiencing it in my own team and across product teams here at Zoopla and I'm experiencing it between Design and Engineering. Design system can deliver huge benefits, but only if it can be understood by everyone.
So, I've got a final question for you. Are design systems hard or is it how company translates, what the design system is that makes it hard for everyone working with it to understand?
I'll leave you to interpret that one. Thank you for listening.