Nearly 6 months into a massive overhaul of our core product, we noticed that the user interface was becoming less and less cohesive. In fact, it was becoming pretty fragmented. I was given the task of restoring order to the universe.
I approached the problem systematically, pulling apart each interface to identify what components they all had in common, listing out all the unique components, then sketching each UI again and again until I felt they were all aligned.
Our team’s lead developer and I arrived at 4 basic layout components that could be used to compose any of our current views, and provided a turnkey solution for future layouts.
Finally, I turned to my trusty combination of ReactJS + MeteorJS to model these components in code and do the visual design. This has always worked great for me because developers can usually copy/paste sections of my code, saving all of us time.
All this refactoring resulted in a much cleaner interface, consistent responsive behavior, and a more powerful set of patterns and components to guide the design of future interfaces.
The Full Story
Here’s a more detailed version of how the project unfolded.
The components we were using for our layouts were pretty fragmented. Depending on the view, you might see completely different design patterns employed for the same problem, and different components used for essentially the same interface element.
In my assessment, we were accumulating clutter and I knew it would be hard to end up with a clean design system the longer we let this go.
Clutter stems from a lack of intentionality, a steady drip of one-off implementations, and losing sight of the forest for the trees. It manifests itself visually, in crowded, confusing interfaces, and behind the scenes in the code. Even though we’re using React, a framework that’s totally oriented around modularity and reuse, those principles hadn’t translated into our designs very well, particularly our layouts.
In interfaces, clutter stems from a lack of intentionality, a steady drip of one-off implementations, and losing sight of the forest for the trees.
We saw an opportunity to fix a lot of these issues before they ballooned into something more serious. I argued that this kind of refactoring would help us move faster when building additional views, adding quality through the process instead of at the end.
The Original Idea
In the beginning we knew we wanted a “fullscreen” responsive app, i.e. where our interface would fill the entire width of the screen and have some degree of vertical responsiveness.
We ultimately landed on just two layout components — one that would subdivide space vertically, the other horizontally — and by combining and nesting those two components we believed we would be able to create any layout we needed.
Our First “Real” Implementation
Besides a prototype that we threw together in two weeks at the very beginning of the project (mostly to prove out certain technologies), this was our first stab at really implementing all these components.
How I Went About Making Changes
1. Identifying existing components
Before embarking on any redesign, it’s important to examine what you’re about to redo, take it apart, acknowledge the reasons why something was designed that way in the first place, and decide whether it needs to be reconsidered. I tried to do this first, then made some decisions about which components should be unique to just one view, shared across multiple views, or shared across all views as a site-wide convention.
At this point, it was time to see how my ideas would hold up in more realistic UI concepts. Sketching the same view in multiple states forced me to wrestle with a lot of usability considerations, and keep iterating until I felt like everything was falling into place.
This is where the constraints really come knocking. How will these interface elements respond at narrower widths? What if this string length exceeds n characters? How will this toolbar work? When we introduce this feature, where will it go?
I found myself considering features that didn’t yet exist because I recognized that I wasn’t just designing a series of “templates,” I was designing a flexible design system, one that would still need to work when we implement all kinds of features later on. When I got the question, I was prepared to respond because I had thought about it already.
Plus, the developers I work with love that they can just copy/paste portions of my code. It saves us all lots of back-and-forth, and it gives me a greater stake in the end result, even recommending a specific structure and naming scheme for our components if I so desire.
Our Second Implementation
We changed a bunch of things under the hood and made some significant improvements to the visual design of the app. What excited me the most, however, were the site-wide patterns that were introduced and consistently applied.
The app was now better poised to scale — visually and architecturally. This increases the likelihood that future designs will fit into a consistent application experience, improves usability, and helps our designers and developers become more efficient.