|View this newsletter on the web.
📝 How to tell the difference between a React component and a design pattern
[Robin:] The odd thing about design systems and front-end development is that not everything in a system can be turned into a component or a variable or a design token. Ethan Marcotte mentioned this just the other day:
A design I change, a pattern I build: they’re not just artifacts, but threads in a larger web. The results of my work—of our work—ripple throughout the rest of the system, and a systems worker strives to understand that.
Jina Anne described this in detail when she wrote about how a design system is much more than just the deliverables:
So in the design systems work we do, you often think of a style guide. Or a component library. Or a Sketch UI Kit. And there are arguments on whether either of those things can be called a design system if it doesn’t include this other thing or that other thing. We even talk about whether design systems are products or are more of a service. My take? The word “design” and “system” used in combination together literally just means to systemize your design (and in my world view that is more about the overall experience). And so if for you that means a Sketch UI Library, then you do you! My point is I think there is too much focus on the deliverables in the first place.
This leads into an area of design systems work that’s taken me years to figure out: there’s an enormous difference between a React component and a design pattern. Also, feel free to replace “React” with any other framework here — that’s just what I’m most familiar with today.
Many problems in my design systems career have been caused by mistaking a pattern for a component, and vice versa — so let’s begin with The Tale of IconLink: Once upon a time, we had a component called
Icon that looked like this:
This would render a pencil icon next to some text that said “Edit.” In the mockups, however, designers would constantly place icons within links and so a new component was born:
IconLink and it worked like this:
<IconLink linkSrc="http://gusto.com" iconName="pencil" linkText="Edit" />
This made sense at the time. We’re using this pattern everywhere, so let’s make it a component. But! Under the hood of this component it was effectively made up of the following two components that already existed:
<Link href="http://gusto.com"> <Icon name="pencil">Edit</Icon> </Link>
It took me a long time to realize that
IconLink should never have existed in the first place and we should just use
Icons embedded within them because it was always confusing why we needed the
linkText prop or the
iconName is also pretty confusing if you’re familiar with the
Icon component, too.
(This was when I realized every component API in your library should teach you how all the other components work, so if
iconName is the prop for adding an icon to one component, then that should be the case for the lot of them.)
Now, the problem here is that not only is the API more confusing and named differently from other components, but that the API is now much larger. You have to remember that things are different for this one component, as it becomes one edge case. And not only that, but if we want to add a new prop to
Icon, then we probably will forget to update
IconLink in the process. This makes things generally much harder to maintain as time passes.
So the fewer relationships between components that need to be maintained in a library, the better. This also means that any components like this — that just passe props down to another component — is pretty much always a bad idea. Icons inside links is a design pattern (a common agreement between everyone in the org that this is okay) but it shouldn’t be a component for this very reason.
My point with all this is that it’s easy to see every problem or design as a new component or a mix of currently existing components. But instead, we should make components that can slot into each other neatly, rather just continue to make more components. Now, after about two weeks of refactoring, we’ve deprecated and deleted
IconLink, making our library of components a little bit easier to understand.
Things are 1% less confusing today, and that’s enough for me.