Building (And Re-Building) the Airbnb Design System | Maja Wichrowska & Tae Kim

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody I'm gonna start today with a story a dramatic story so once upon a time a new design system arose enabling design consistency and code reuse while solving problems of accessibility responsiveness internationalization and performance all out of the box while implemented by an infrastructure team with the best intentions it only considered a handful of use cases and as a breadth of the product grew and evolved friction appeared between the creators and those attempting to leverage the single shared component library and in some cases feeling left out by the creators of the library factions arose parts of the organization rebelled and created new versions of the design system that better suited their specific needs and finally even with event product organization differing goals of performance and design consistency led to multiple cancer than the company each champion a different strategy and vision for the future of the design system and so this tale of friction factions and forked code is where we begin our story of building the Airbnb design system and rebuilding it my name is Maya and I'm tae and we are both engineers on Airbnb x' design system team today we're gonna talk about a number of things first we'll define for you what we mean when we're talking about a design system which will do quite a lot today yep next we'll go into the evolution of air babies design system throughout the years highlighting the key decisions and considerations that were made and so finally we'll do a side-by-side comparison of some code examples so you can really understand what the effects of the architectural decisions we made look like in our code base so what is a design system well we are not just those developers but I think as consumers really really intimately familiar with design systems I think that logos are the tip of the iceberg you know a conversation about a design system might start with Coca Cola's lovely cursive letters McDonald's arches Starbucks mermaid but it becomes really clear that it's not just about the image it's about the colors it's about the typography it's about the spacing and all this is the reason why we find brand swaps so funny I mean these values are so deeply into like ingrained in our brains and associated with coca-cola that's seeing its rival embedded in the same script causes a level of cognitive dissonance that it's pretty funny to be honest I just got a little thirsty weird now on the web we've been using Design Systems for quite a long time bootstrap material design tools that were very familiar with they're probably some of the most popular open source tools out there and of course they're not exactly fresh they've been around for a while and back back in the day when we were all writing a lot of jQuery templating languages so four C's were based on CSS class names and this was actually a really good choice for open source projects after all bootstrap probably still powers hundreds of thousands of websites out there and each of them need to be slightly different they're associated with a different company a different brand and because they use CSS this technical choice allows for them to be endlessly over aidable fema bol extensible which is really perfect but for us with the rise of react we start thinking about component based libraries those based you know we started thinking about rows and form elements buttons colors and typography each as individual pieces that we could just drop into a page wholesale and this is where we come to a spectrum of choices what kind of API do we choose for our components on one end we can use our components as enforcers of our system we do this by building a strict yet constrained API this would enforce consistency across our site through our design system on the other hand we could build our components to be less opinionated and more flexible this would make it easy to do tweaks and build new designs using our system but it leaves the door open for inconsistencies so where do we go from here Maya well let's time travel a little bit and go back to 2015-2016 to try to understand why we made the decisions we originally did and so design systems are lying very closely with UX and product needs so I think it's important to understand not just what's going on in the technical landscape at this time but also to take a step back and look at the business so in 2016 for us Airbnb experiences had just launched publicly and this was a big shift in our app we were trying to make an update to the site to focus less on just accommodations and more about the in-between of the trip and this was something that we hope to do via change to our design language and from a technical standpoint there were also a number of considerations that influenced our path forward now this may seem a bit strange now but we had just come out of a world of massive framework fragmentation where everything was built with whatever framework the engineer was most familiar with at the time we were using in 2015-2016 time around that time I think I was building my own framework using functional paradigm from high school ah well in 2016 we had decided as an organization that react was the future of the way we built front-end but despite this decision much of our site had yet to be rewritten we had also been dealing with increasing complexity due to our growing organization since we're using CSS we shoved a stylesheet containing core styles maybe you know this teal button want white text to every page on the site but as I mentioned before CSS is in and of itself a technical choice and it leads to certain behaviors in our case engineers we're overriding every core style pretty much on every page all the time in many different ways we're also primarily Ruby on Rails shop which made it basically impossible to understand where each of these style definitions were actually being used engineers had super low confidence that when they made a style update to our core style sheet it would work as expected across the entire site and now these are pretty simple examples I mean like background color text color safe but imagine Styles related to Z index or positioning and it becomes clear that this can lead to a lot of unexpected behavior so to avoid this potential downtime engineers were forced to duplicate code and often the bugs associated with that code and that made the problem of complexity grow even more and finally performance was becoming top of mind and while there were tools to optimize JavaScript either by you know tree shaking away dead code or lazy loading code not in the critical path none of these were available for CSS and the end result was that the amount of unused CSS shipped to every page in our site was growing and growing and growing and this was seen as a major contributor to our slow page load times so fragmentation complexity and performance these were all top of mind from a technical standpoint and we took a step back and ask the question what if we could build a design system that helped in each of these scenarios well we had two levers that we could really pull from an architectural perspective how we build our components and how we write our Styles so for the problem of fragmentation this was a really easy answer we build a library and react and then adoption of the library it drives adoption of the react amazing but for the issues of complexity and performance we had to take a closer look at how we were using CSS internally see how that could go as we all know global style sheets are both powerful and performant they're an excellent choice for building and design system however we had the privative from our design team to enforce consistency as much as possible through the we also wanted to feel confident and understand the repercussions of any style updates that we made and as we heard from Maya's earlier slides we were not feeling confident about our CSS truth so oh also at the time we had begun leveraging performance enhancing JavaScript patterns like lazy loading and tree shaking which we saw earlier so because of this we wanted to move our CSS into our jeaious this would allow us to write styles in line with our components and gave us benefits that we felt were highly advantageous the first thing was that our components were tightly coupled to our CSS not only could we write the Styles in line with our component files but it now became easy to add update and remove Styles without those unwanted consequences we were seeing with our CSS changes of your Styles would only apply to that component this was so nice another benefit of CSS and jeaious was that we got the lazy loading and tree shaking that we talked about we're no longer shipping these huge style sheets with unused Styles we only shipped what was rendered on the page this was a super nice benefit of going to CSS nsj a nicety of CSS and jeaious is theming this wasn't a huge requirement at the time but we've been relying heavily on this for a China business in all new locales and finally we finally could prevent those style overrides or biting us in the butt we are able to rid ourselves of override world-class lames and entirely disallow styles for being overwritten this allowed us to enforce the site consistency across the site through our system and so this last bit especially is kind of the underlying principle of what we dubbed our design language system or the DLS I'm gonna introduce this acronym because I can't stop myself from saying it so now you know it cos I'm gonna say it a lot there are a number of ways that this feature kind of manifested itself but the most important was the public API that we exposed to users of our system which in a react world is of course our props and so the easiest way to illustrate what this actually looks like is if we take a look at one of our core DLS component the button by default we ship this beautiful lovely teal button if you've used airbnb.com I am sure you have clicked on it but let's say my designer gives me a new design this blue button I mean you know Airbnb we're getting into alpaca rentals were really eager to differentiate this new product somehow we want this blue button it's important well we might be tempted to just pass in a new class name or some dynamic styles though to override this background color but this was explicitly disallowed by the system this was precisely one of the issues that we had been having with CSS stylesheets we wanted to have confidence that the button that we built as part of our component library was the same button that our end users would see so class name styles were out for what this also meant is that we didn't even allow for slightly less open-ended props like text color a background color in fact the only way to create this beautiful alpaca rental button would be to add a boolean prop to our core component that would apply all of the relevant styles and this is because we expected that our centralized design system team would anticipate all possible design needs of the company and so would build out a complete system from the get-go I heard some laughs I know that's funny we can laugh now it's fine the result of that expectation of course is that every addition to the design system every new blue button begs the question does this belong if it wasn't part of the system at the beginning why are we adding it now and so returning to the spectrum that we kind of introduced earlier you can see that we fell pretty far to the left of the script on the super constrained side of the implementation now for a time this was good adoption of the DLS skyrocketed which decreased fragmentation and improved issues of complexity and performance on the site and product engineers loved it they lauded the reusability the consistency they were excited that problems about responsiveness accessibility were all taken care of DLS was definitely the path forward and the reason that the solution worked so well for us is because we had a design organization that was excited and committed to driving consistency across the platform but we wouldn't be giving this talk if we had built the perfect design system in 2016 remember this is a story about friction factions and forked code and the reality was far different from our expectations as adoption of the system grew the pain points actually became increasingly apparent so it's 2018 the Airbnb product has expanded significantly adding new tiers of accommodations market specific branding acquiring new companies growing into business travel vacation rentals experiences considered service peer spaces and more there's a lot and the end result was that what had originally been a design system that supported one product looked good wasn't enough we needed different typography different colors different uses of image different layouts just differentiate each one of these products while still providing a consistent experience throughout the site but it was clear that the design system just wasn't flexible enough and what's more our poor product engineers were largely the ones dealing with this explosion of designs so imagine yourself as a product engineer imagine yourself as a product engineer in this world of flex your designer comes to you with the brand spanking new design and asks you to implement it how would you go about doing this well I can think of two options first I could create a new computer from scratch I mean I'm sure the design system has something similar but it's not exactly what I need and my deadline is on Thursday and I really need to ship this feature second option may be the better one I could go into the design system and update the code to allow for the minut design but the last time I did this we got into this massive philosophical debate about does this belong is this a core component what do you mean and it's just a lot I understand and both of those options seem very reasonable let's let's go to option one you're on that tight deadline let's build that component from scratch what that leads to is fragmentation throughout the site a lot of developers on tight deadlines and they usually say to themselves just this one time but it's not just this one time and everyone else is doing this do we saw a lot of the same components being built over and over and over again it's going there we go if I raise it higher yeah the developers of these components weren't getting the benefits that came with using a shared design system like the shared code the free well thought-out accessibility and the free maintenance in the long term so this doesn't feel like the right option maybe option two is better going into the design system and updating our component to handle our new design so to do this we'd add a new prop there yeah that would trigger some design logic or yet trigger some logic to handle our designs one or two of these is okay three is okay but over time we get lots and lots and lots of these all baked into a single component and it ends up looking something like this oh yeah yeah this is our button component and it started off being super small but it grew into this mighty beast that can do a whole lot but a super complex to use and maintain our component API quickly went from zero to a hundred which in turn complicated our components internal logic man can I skip it okay thank you cancel it yeah and because of this the bundle size of our components grew and grew and grew and continued to grow and so we would stop new designs which is literally never that's button component started off pretty small but it grew up to 3333 kilobytes woah minified source code this does not exclude external libraries this is a big number for a button as a developer when you import this component and you just want to use your change you have to import everyone else's code as well not only that but if there's any changes made to this button component in the future you're getting those two for free it's this giant hit an iceberg of code so none of these options seems super great for developers unless they're using the design system as is in my defense that's what it was literally built for this is true fragmentation complexity and performance we're seeing these issues arise yet again just in different forms so what if a design system could help with these we're rolling into 2020 the future area be scaling rapidly right now and growing many businesses within the company it's important we can spin these businesses up efficiently and cheaply what's more the Airbnb design team is working on a design refresh to move away from this bubbly colorful look to a more monochromatic design this will allow our businesses to different--you differentiate themselves through color what's yeah we use a design refresh as an opportunity to rethink and rebuild the design system for the future and we also really wanted to take advantage of modular architecture something that reacts the framework that at this point powers nearly a hundred percent of our site was really well designed for so this should this this next part should be pretty familiar to y'all to understand the power of modular architecture let's look at an example if we zoom in on our date picker modal which those of you who know me may know this is my favorite part of the site we could start to split this into smaller pieces we can extract out the overlay we could split the modal container from the day picker and finally bring out the icons text and buttons and this leaves us with a set of independent components that can be jiggered back together and this is great but there's more because now that we have the individual pieces we can change where the components go we can switch out components and we can remove components and adjust accordingly and this leaves us with a whole new composition while reusing the vast majority of the underlying pieces and this gives product teams a lot more freedom to reuse the design system to create whatever it is they need and this seems obvious again react is literally built for this but with tons of developers working on features simultaneously it's easy to build out just what you d need and to do it in a non modular way I mean you just add a prop right having a modular architecture is great but it didn't solve all of our problems I mean buttons are like one of these components and they still got really out of hand to solve for that button component that got super bloated we introduced the base and variance pattern this is how we create reusable and performant components remember that bond component that can render any style do its props the base variant pattern approaches this problem a little differently it starts by separating out the core logic from the design aspect of a component this leaves us with a base and many variants the base defined that defines the components HTML structure some generic styling to make it functional a shared API and then placeholders placeholders are very similar to children and render content in specific locations of your component variants on the other hand are built using the base and apply the specific design styles some additional content or unique logic specific to that variant it's important to note that developers would import and use variants not the base component the base cannot be rendered directly and must first be extended as a ver this brings us to the interesting controversial part of the base France a pattern all variants live in their own separate files this leaves us with four files our base component the base button and three variant files the primary button the secondary button and the tertiary button all very much share the same core code from the base have the exact same API which we see here but apply their own unique differences in their own files what this leaves us with is a base component built for a general purpose and can be easily extended it's important not to tie any design logic to your base instead of providing hooks or placeholders to make designs to be able to implement designs to allow designs to be implemented variants on the other hand are built for a very specific design or purpose they don't allow style overrides and must be rendered as is this gives us confidence as maintainer x' that our brandt component will be rendered as expected on the page this by organizing our components in this way it solves a lot of our problems first being that it's super easy to implement new designs although hard works done for you you just extend a base and do whatever you want to get your specific design needs there's no reason not to extend a base component when creating new designs this pattern also makes maintaining components very simple because not only we simplified our API and got rid of those style props we've taken all that knotty branching logic those if statements those tertiaries and we've straighten it out nice each frame extends directly from the base so there's no branching logic to deal with at all forget about everyone else's code and focus on your own that's what we like what's more is that the bundle sizes of our components remain consistently low or stable before you'd have to import all of this code just to get that one style this costs a lot of blow when you never ended up using it all now when you import a variant component so you only get what you need the super-nice those small bundle sizes no 32 kilobytes one last benefit and it's my favorite because all the variants share the same API swapping out variants is as easy as updating an import statement you can easily get your secondary button your tertiary button all in one line of code so in the past we had major design updates and we had apply these design updates throughout the entire site all at once and some product developers weren't expecting this and did not appreciate the unanticipated changes this even caused a bug or two or three instead of forcing these design updates on everyone all at once we can now create these designs as new variants and it opens the door for iterative migrations this is powerful because it enables the ability to do new designs updates file by file and giving users of your system control to make the updates to QA those changes to a/b test them all at their own pace updating updating to new designs is as simple as a finer replace now we go back to the spectrum and we might think that we're moving our design system to be super flexible but I think we're somewhere in the middle we continue to be constrained because our variants cannot be overwritten they must be used as is but we allow developers to opt out of the system like an escape hatch by extending the base and creating new variants if they need to so we've talked at a high level about two different approaches to the design system implementation so let's look at some code to kind of better understand what that actually means so on this side we'll start with what I'm sure you think is now our only component in the design system the button in 2016 the button was always usable even with no props passed in it was out of the box had designs meant to be seen by end-users so we'd have to start with this teal button styles and so to begin normal simple react component we just want to render a basic button Dom element when using the base variant pattern we start by building a button as well but it's our base button no styles are being shipped to the end-user that we care about here we just want to make it functional so we render this dull gray one in code is actually no different than your normal button at first they look very similar they do and so next what we'd want to focus on is the core functionality things like the onclick handler and anything else related to the Dom or to user interaction and so here we just pass them that prop pass it on to the Dom element the base component continues like very similar when we apply the core API but here is where we need to make our button visible to the end-user we need to apply the style so this is the way that we wrap all of our components and this react with styles higher-order component and so we define those default styles here this is where a bit things begin to differ when we use the base variant pattern we first mark the base button as extendable and to find some base generic styling our background in our color what's more important here is that marking this component as extendable defines the component style API the button class name yeah variants will use this to extend our styles and so we in 2016 would then finally applied those default styles to our individual Dom node and this if we stopped here we could still use this out of the box we could render this page developers have a button that's within the system the base frame pattern also applies these Styles just like the button to our individual Dom nodes it looks very similar but because a base component can be extended variants can apply and override these styles as they choose and so in 2016 again we have a perfectly usable button out-of-the-box and so for every new variation on on this default we go through the same process we define the style we apply the style we define the style we apply the style until eventually we have that long long scrolling gif from before with the bass rant pattern when we want to create new designs we create a new file the primary button file and to find the styles we care about notice that we're extending the base button here as we want to create more and more designs we create more and more files this encapsulate all the encapsulate all the designs into their own isolated component files and this brought us the benefits that we saw earlier and so there are a lot of trade-offs of both sides but I wouldn't actually a hundred percent recommend the base variant approach it's not right for everybody and so when we look at the single component thing we saw off the bat was that performance will degrade over time if you're continuing to add new styles and the complexity within the components will increase but this is a big caveat everything is in one place discoverability of component variations is really high in the system when your designer gives you a design and it's like give me a button you're like cool I'm gonna go to the design system and look at the one component and see what my options are super high discoverability and then this is less of a it's not really positive or negative it's just something that's true maybe about your organization or something to consider there's more burden on a systems team maintaining a design system implementation in the single component approach because everything has to be code review to edit and add it in so your design team it's constantly working your engineering team is constantly working to add new features and new designs to your core library there are some similar trade-offs with a base variant pattern your performance remains consistently strong and your complexity remains consistently low these are good things and we do this by extracting out the share code into a base component and isolating differences into their own variant files but this means that we end up with a lot more files and this can feel wrong to some developers almost like a burden they have to go find these files we use tooling like storybook to help you help make using and finding variants a lot easier and so for us there's been a clear winner as to what we need to implement in our system but the reality is whatever is going on in your world is not necessarily the same and so you may want to pick something else along the spectrum and so the question is going from constrain to flexible when do we use each implementation I'd say on the constraint side if your systems really static like for instance you're a contractor coming into a company for six weeks they're gonna use that system for the next three years but like no one's touching it this is a good choice because it creates that brand integrity over time it's very hard to build something that doesn't look and feel like the brand similarly if the system is small like for instance you're only focusing on colors typography and like drop shadows you can keep it pretty constrained because it'll enable that consistency throughout the site but while allowing a lot of creativity in other parts of it and additionally if you have limited design support you're at a start-up you just hired your first designer you got a hundred engineers all building product every day you can really increase their impact by having a constrained system they'll build it once everyone else will use it and look good throughout the entire site and finally this is something that was really important for us to look at engineering cannot be the only enforcers of design consistency it creates friction between the systems and the product teams it creates friction between design and engineering and so only go for a constrained approach if you have support from your product teams and from your designers a constrained system is a great way to start but if your systems starting to notice some of these points and may be good to move to the opposite side of the spectrum flexible one is if your systems starting to evolve you're seeing a lot of change this might be a good time to consider it because of these changes your systems probably growing and growing and growing and becoming large right you're trying to handle every permutation of every design in your design system and that's a lot of work add some flexibility and push some of that responsibility to your users of your system finally for also if you have a strong design team and can handle the flexibility and use it to flex their creativity allow them to and finally if there's no enforcement of design consistency on the design side your design your constraint design system could feel more of a hurdle than an advantage give the users what they need wonderful we hope that you can take our experience from working on the erbium bead design system for many years apply it back to your work my name is Maya I'm tae thank you so much [Applause]
Info
Channel: React Conf
Views: 28,820
Rating: 4.9008746 out of 5
Keywords:
Id: fHQ1WSx41CA
Channel Id: undefined
Length: 33min 32sec (2012 seconds)
Published: Wed Oct 30 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.