A Working Theory of Components



Nov 28, 2017
2:30 pm
Alamo Drafthouse New Mission

Throughout history, our tools have affected how we understand the world. In our young industry, our tools, needs, and processes are constantly changing. We build sites and frameworks and components with the tools we have at hand. As we do, we discover problems, invent solutions, and then invent new tools.

Design Systems are our current model of making sense of the intersection of front-end code and design. With the tools we have today, what is our working model of a component? How do we define them, create them, and ensure they work at scale? In this talk we’ll discuss how our tools affect our understanding, create a checklist of factors that make a component a component, and how to implement the theory of components with the tools you have at hand.

Sketch Notes

A Working Theory of Components

Artist: Cindy Chang


Una Kravets:

So, our next speaker who will be up in a second is Elyse Holladay. Elyse works as a development system engineer at Indeed. She worked on the Design System at RetailMeNot and she writes CSS and ensuring friendly documentation. She comes here from Austin, Texas, where we used to both run the Austin Sass Meetups. She used to teach classes at code school. We have a lot to learn from her today, so please give a round of applause for Elyse Holladay.


Elyse Holladay:

Thanks, Una. Can you all hear me? As Una said, my name is Elyse and I'm a design system engineer at Indeed.com, in Austin. Today, I want to talk about our working theory of components and how to implement this theory with our current tools. So, let's start with the law of gravity. Gravity, a mysterious, unexplained force, works on all objects in the universe. They attract each other based on their mass and distance. More mass will attract each other with a greater gravitational force. This sends the planets in their great orbits around the sun.

Newton's mathematica was published and they used Newton's laws of university gravitation to improve truth about the world. They worked out descriptions of the planets called tables. It showed where the planets would appear in the sky and Newton's math always matched the real observations that could be made.

The small discoveries began to accumulate that didn't make sense. The first observation of what would be the planet Uranus, didn't fit. Jupiter seemed to be moving faster. That couldn't be reflected in math. And many began to wonder if Newton's laws were not universal after all, if there was a flaw in the theory.

But not the French astronomer who was a paralleled mathematician. In 1846, he said Neptune had to exist. Within a month, an astronomer in Berlin found that within one degree of where he predicted it would be. As a colleague put it, he found the planet, au bout, at the tip of his pen.

The inaccuracies meant he was wrong. If the observations of the planets and the mathematical tables don't match, we shouldn't say it's inadequate or wrong. There was no need to toss out gravity all together. He was committed to the theory and taking it as far as it could go and learning more and more about the world. Certainly, they didn't know everything. He believed that has time passed, we would improve upon our understanding.

Over the past 15 years, our understanding of the world of front end development has changed more rapidly than the university. We have been working on how to design and code for the web. When CSS came out, we were stuck in a phase where no one knew CSS. Then came j query. Do you remember this? A developer should be able to change the markup in an HTML template without worrying about breaking a CSS rule or functionality.

As we began to build web apps, these structures with pairs, options and states, our attention turned to tools that would help us work modular, flexible code. We learned how to do responsive web design and Sass. On the design side, we moved from photo shop to sketch and we have tools like Abstract that are narrowing the divide. Our needs have changed and our tools have improved and we are updating our understanding of the world. The tools we have today didn't exist 5 or 10 years ago and you couldn't be having this conference in 2008. We had no frameworks with which to build a web apps for components. No way to break up components and isolate them. We use the tools we have not just to create solutions to the problems we face, but to face new tools. These tools aren't just helping us do our job, it is changing how to do our work. We are filling in the gaps and the unknowns and we're coming to a new understanding with these new tools of how to do the front ended scale, Design Systems.

A Design System promises consistent, cohesive visual design, user experience and code across projects, pages and team process. And last year, at Clarity, we talked a lot about why you might need a Design System and how you can get your company to invest in one. We are committed to this theory, even as our tools are changing. I want to talk about the next step, understanding how to apply this theory in our every day work. How do we make sure it lives up to enabling a consistent experience spread across products?

What is our working understanding of a component today? How do we test this theory? In the early 1850's, he was calculating the orbits of every single planet. He intended to create a complete set of tables. First, he mapped out the actual orbit of each planet based on observations. Next came calculations. What did Newton's laws predict the orbit should be given the known gravitational pulls with the sun?

The mathematical representations of Venus, earth and mars all behaved properly. It produced a chart that matched the one formed by the observational record of the three material planets making their way around the sun. One, though, abstinently refused to conform, mercury. Mercury's orbit shifts forward incrementally each time it orbits. Its orbit makes its own orbit. This shift is too large to be explained only by the pull of Venus and earth's gravities. He and his book length report wrote that the likeliest solution was a planet or a group of smaller planets circling in the vicinity of mercury's orbit, with a gravitational pull. He named this possible planet Vulcan.

In the years after, astronomers all over the world observed objects near the sun that they believed were Vulcan. On July 29, a total eclipse could cross from Montana to Texas. Getting a clear observation of Vulcan was the biggest prize. James Craig Watson made a reputation by finding asteroids, was determined to find Vulcan using a small telescope, a set of cardboard circles and a sharp pencil, he plotted the transit of an object. Many astronomers saw this during the eclipse, too. For many of those observations, the math worked out well. Vulcan fit neatly into the explanation of mercury's orbit. Observations of Vulcan dwindled and people began to doubt it existed. The question of mercury's orbit created discord and disagreement between astronomers. We know, now, that Vulcan does not exist. The observations of Vulcan were most likely sun spots or nearby stars, but people kept discovering Vulcan because it fit into their understanding of the world. The limitation of their tools and knowledge kept the answer right of reach but they never stopped trying out ideas.

They have no way of explaining mercury's orbit without Vulcan and so they searched for the answers into the unknown.

We, too, are trying to find solutions. We have constraints, business requirements, deadlines. We may feel stuck with our legacy tools, like Watson's cardboard tools and sharp pencil. It can be difficult to work with those limitations. Often, it can cause conflict between us as we struggle forward to a better understanding. We're seeing this a lot now in our community with the struggle over CSS and JavaScript. There's discord among us over which tools are the best, where and how to write the best styles. We had a gap in our knowledge. How do we create components? How do we solve for maintainability, reuse and scale? Based on our experience of the world, we turn to varying solutions to try and solve this. For some, CSS tooling and methodologies. For others, JavaScript. We created new tools and made decisions based on these big, new ideas we had combined with our practical technical needs.

We're working towards the same core idea. We want isolated components that we can reuse. Styles that don't conflict. And an easy authoring experience. So, what is true about this concept that we've believed for awhile, that still holds up? What do we know about components and how to build them, that solves for the value of a Design System?

We know that if a component is too big or too complex, if it has too many options, it's not useful to us. If we can't reuse a component or if it's small or difficult to customize, it's not useful. If a component is buggy or hard to test and looks different in one place than another, it's not useful. We know a component needs to be, one, easy to reason about, context agnostic and independent and isolated.

First, the component is easy to reason about. Being easy to reason about is gut feel. It's not only the size of the component or complexity. Some components that look simple are difficult to conceptualize. If it's difficult to ascertain if code is necessary, it's hard to test whether or not all the combinations work or understand where all the variance might appear in your abstract.

Too few options means a component is pointless. I've been asked to make a box with a border and something you can put in a background. In the end, it doesn't get used. There's a spot that's just right where the component is used with enough options to make it flexible. If it gives you a headache and you can't hold all the options and variance in your head at one time, it's probably too complicated.

What out for markups that use the component with tweaks every time, there text is a different style every time or there's only a button. Watch out for too many properties, states or variance. Sometimes they come this way. This can build up over time as developers add features. If your project is like mine where many teams use the components, sometimes those teams need to if you have a lot of bugs where the components doesn't function properly, it's likely developers are overriding it in ways it can't handle. It could mean it has too many options or they're overriding it to a generic panel. A good solution is to split the component up that fills each case properly. You can create parent components for those.

Components being easy to reason about isn't about the ease in read in code, the harder one is adoption and use. Getting teams to adopt components and uses them relies on your ability to understand what the component is for. Developers say it doesn't have the options they needed. Half of the time, they're right. The other half of the time, they didn't recognize the options available. They need to make it clear what it can do for your developer or designer.

So, a component that is easy to reason about should be flexible enough to support all its use cases without being unwieldy or confusing.

Second, a component is context agnostic. One of the greatest values of a Design System is reuse. We want to take that button or comment card and use it all over. It is usual to the theory of a Design System. To fulfill this, a content must be agnostic. It shouldn't need to know where it lives to look or behave properly. One way to be sure your component isn't going to be effective is to define it once. There is one file that contains the primary class name. It can be done by name spacing your CSS or if you're text stack allows, you can write CSS and J S styles.

It's hard to give up the cascade, but use unique classes rather than replicating styles. Setting styles directly on the elements that need them ensures the markup structure can change. Let the component live in a variety of context and change over time. It makes it easier to reason about.

The component being context agnostic means it needs to function properly and consistently. It should not have logic that controls functionality outside of itself. No external state. Data down, actions up. Take, for example, a call to action card component. This card has a button and when the button is clicked, a modal pops up. And that will work great and so we want to do something different with that card. We want different functionality. Your card button should bubble up an event. I just got clicked. Let it be up to the parent component or application to determine what to do when that event occurs, you can set active states or indicators, but keep them generic.

If a component is supposed to look or behave differently, make sure the logic is well defined. Likely, the component might be split into styles that are more isolated. Sometimes the best solution is not a shared component at all, but implementing that feature, like Linh said, as a special snowflake. It should be reusable and may only be a simple call to action card but can live in many places and do neat things.

Third, a component is independent and isolated. To be context agnostic, a component must be independent and isolated. It gives us more than flexibility. It will look correct in an isolated environment. It doesn't rely on styles from a parent container or a global page. Consumers of your components need to make sure they will work and look correct straight out of the box.

The component should import all of its own dependencies. The same pattern in CSS is equally as useful. This gives you confidence in what is there and makes it easy to test whether or not an imported file is actually used. Depending on your stack, importing styles may require CSS duplication if you kind of get recursive imports of things. You can write this in your own app. You can use a flat structure style sheet or if your text stack allows, you can name it.

You have the ability to test with confidence. You can run unit tests on them. We know then that any bugs we catch in that isolated environment are in the component and any bugs elsewhere, like production, are byproduct of how they interact. Isolation for testing also means that your component tests only itself and doesn't rely on the presence of a parent container or a child component. Don't test the auto complete functionality by testing to see if typing in the text input works. Make sure the drop down appears, that you can select from it, clear it and so on.

The component being independent and isolated means that we can be more confident in its quality and enabling our clients, other developers and designs to entrust in us. We can isolate changes, test them and know we aren't impacting anything else.

If you have components that are isolated and independent of their siblings that can live in any context, you can use other components by composition. You can pull something into yours and compose something greater. Many cases, it might pass an adoptive class or wrap the component in a parent class. It can pass propers to a component, changing the content and options, such as the text or whether or not it has an icon or how many results it can show. If you need to show styles, you can import those in CSS.

In your components JavaScript, have your component bubble up its actions so you can grab those and do whatever needs to be done in your app to meet the requirements.

Our theory of components should be applicable regardless of our tools. You may be using Sass. A majority of us don't get to use the hippest and newest technologies. There are many reason we can't and shouldn't throw out our projects and do a huge rewrite. We wrote templates and handle bars and we're using Sass with components and also providing templates in Soy for Java projects. Stop getting frustrating. Consider how you apply the theory using the tools that are available to you. Test the theory.

We believed we observed Vulcan because it made sense but no real Vulcan ever turned up. Scientists posited that it was asteroids or comets as they poked and prodded at the theory, trying to find a solution. It took almost 60 years to add the information to the theory that would explain Vulcan. In 1913, Einstein is working on his theory of general relatively and as a calculation to see what the map predicts for the orbit of mercury? Can it explain mercury's in explicable orbit? Space and time can be changed by the presence of matter. So, fast mass, like the sun, creates curves and space time so mercury's orbit shifts because that's the time it has to take created by the huge mass of the sun. Without curve space time, you need some other object's gravity to pull, like Vulcan.

But Einstein didn't disprove Newton's law of gravitation. Planets are held suspended, the tables of planetary orbits are still accurate. General relatively updated our understanding of the world. It filled in gaps and created a framework. It builds upon it, strengthens it.

Many astronomers worked as observers, they experimented, saw and recorded how the world really was. Others worked as mathematicians, conceptualizing a theory. So, consider as you work, both aspects. You have a text stack. Your components are your observation of the world. You have to have the map and the concept.

We've described what a component must be to fit into the theory. When you're building your Design System, how do you know if your components fill it, the application and depends on technical constraints. My team put together a document that is a component check list. It outlines the three high level concepts I spoke about, easy to reason about, being context agnostic and being independent and isolated. It contains a much more concrete list of what a component must do. Here's some examples. To be easy to reason about, a component must be self documented with comments for all the properties, options and variances and design and technical explanation. It must have unit and visual tests so we can be sure we know how it looks and behaves.

To be context agnostic, a component should have no layout, margin, float or other properties. It can have styles inside itself to lay out children but nothing that would keep it from being used in a variety of contexts. It should look appropriate in all supported browsers and all screen and devices, including screen and mouse and screen readers and accessible visual styles and look and function correctly in left to right and right to left languages.

To ensure a component is independent and isolated, it should only affect itself. It should not bind any functionality to style classes. It should define using a unique class. It should define or import all its own styles and only define the component in one space. It should work as a standalone component.

This check list defining what a component should be, gives you a tactical way to test your observations. We have a team that builds many of our components, but many teams use them and they make changes. This check list keeps everyone on the same page. We work to make a component work as it's expected to. We keep the theory and promise of Design System close. User experience and code across projects, pages and team process. Every day, we test this theory.

After formulating the theory of general relatively, Albert Einstein pondered what would happen with an exploding star. He predicting any cosmic event should produce ripples in gravity. Scientists didn't agree. Even Einstein didn't agree if this would be true. These ripples would be so small by the time they got to us, we wouldn't be able to detect them anyway. Many believe it was artifacts in the new math. Many scientists didn't believe black holes were real. Einstein's theory explained many things, but it also opened up new questions. The pursuit of science is more than the pursuit of understanding. It is driven by the creative urge, a map, a picture of the world that gives the world more beauty and coherence.

There has been an experimental quest to detect these gravitational ripples that Einstein predicted. They have developed levo. This took 50 years and the teams weren't sure if they would detect anything. Yet the teams persisted because it is crucial to think beyond today's understanding of the world, to give the world more beauty and coherence than it had before.

Two black holes circle each other, churning up space and time until they crash and merge to one enormous black hole, an event outputting more than a trillion times more than the power than a billion sun. They collide in complete darkness. None of the energy comes out as light. It is waves and ripples in gravity. An astronaut floating nearby would see nothing but the space around her would ring. She would hear the wave. Almost exactly 100 years after Einstein predicted it, they defeated it. It opened up new questions for us to ponder. Our work may not seem so grand. What could be grander than black holes, planets, celestial, we can expand the theory, confirm it and strengthen it. We are experimenting with this theory of Design Systems every day as we work. What we learn will add to the theory and help us move forward and create better tools. Searching for new solutions might propel us so far. We have as many new questions as we have answers.

Keep thinking beyond today's understanding of the world and on to tomorrow's. Thank you.



Hey. Awesome talk. Thanks.


Thank you.


Thank you. Please take a seat. I'm popping out from all over the place. I never know where I'm going to come from. First of all, thank you for that. Beautiful slides.


If you saw the credit, they weren't mine.


What inspired that?


A couple books actually and some work that I did at my current job. So, as I mentioned in the talk, my team, we actually we wrote this document and this is one of the first things I did when I joined our team, I collaborated with a couple of my teammates to complete this check list and define what a component was in our library and there were a handful of books that I had read. Did anybody else go to the eclipse this year? Did anybody travel to see totality? I see a couple of hands. Just before that, I read a book called American eclipse. These are all in my slides resources page so if you want the links, you can get them. It was about the eclipse, looking for Vulcan in the eclipse and that led me to the hunt for Vulcan, which goes into more detail about how that the whole, like, finding it on the map and everything. And the last book I read was black whole blues. She published this book before the first detection that was made. So, she's telling a story about building this thing and trusting that there might be something out there and knowing this struggle of progress and how far it was to look past what we know about the world and say, we're going to keep thinking. I was reading that and trying to kind of like pull all of these different things into this idea of what is the theory of what we are working with right now? Because it is so different than what we were doing 5 or 10 years ago.


Do you have anything to say about building and the steps to be effective?


I feel strongly about this. A lot of us I mean, I work at big retail companies. When I worked at RetailMeNot, we had an app and we weren't going to throw that out and start over but we still wanted these new conceptual ideas that the industry was coming out with and, you know, I think it was I think it would have been a mistake to throw out everything we had and do a rewrite so we bit our own custom setup, so you can have a single component folder. We built custom CSS duplication and we built all these tools and it took a long time and it was difficult and painful to do that, to build all that custom stuff. It was less time and less difficult than tossing the entire application that was in use and making us millions of dollars and rewriting that. I think there's a lot of frustration of I want to use this new tool or frame work. You can still take this concept that we're settling on, as an industry, and make it yours in your own tool. It's sad for me to hear, well, we can't do that. It's impossible for us to do that.

As for your second question about how to be effective in doing that? I'm not even going to try to give advice because it depends on your team and your particular situation, whether you have a team and whether you have resources and what your stack is and what your company does. Don't feel so limited by your tools. There are ways to use this theory of Design Systems and components regardless of what your tech stack is.


So, last question, you mentioned that it should be agnostic. When you have a component that looks slightly different in a slightly different context?


There's a variety of solutions and honestly, none of them are quite perfect and this is another place where I wanted to talk about this theory, but I'm not going to try to tell you exactly how to solve that problem. You can do something that's referred to as adoptive class. When you call the component, you say, like, and I also give it this other class. So, here's the text input. And then when I reference that component, I say, also the you know, there autocomplete. If I'm applying styles I mentioned components shouldn't have margin or layout properties. You don't want text floated left because if you put it in the autocomplete, it doesn't work.

So, you can pass this adaptive class. You can have parent classes. There's a school of thought and I know Ben Frain wrote, Enduring CSS. He strongly says, just make a new component. If you need a text input and autocomplete, just write it. Depending on your setup, depending on the way you release things, that might be a better option. Those are the three most common.


Awesome. Thank you, Elyse.


Thank you.