This is the second entry in a two-part series covering various strategic and functional aspects of design systems.
The challenges discussed in this entry are specifically relevant to individuals that have roles in engineering leadership, user interface architecture, and design systems engineering.
You can find the first entry on scope and governance here.
Beyond Scope And Governance
In the previous entry I discussed some strategic pitfalls that teams can embrace in the hopes of creating the perfect design system. Succinctly, adoption can become abysmal and team velocity can grind to a halt. But, what about teams that embrace a strategy with a liberal governance model and humble scope? Is success all but guaranteed?
Beyond the abstract world of strategy lies the far more practical world of implementation, which presents its own unique blend of dragons and mirages.
Let’s dive in.
The Dreaded Platforms
I have routinely found that there is an undeniable misalignment between teams that are building cross-platform user experiences and the users that are consuming them. In my view, this misalignment is best described as follows:
Designers and developers want…
- To deliver a unique experience as part of the competitive landscape on a given platform.
- To have this experience be largely consistent across the platforms they support.
Meanwhile, users want…
- A consistent and familiar experience between competing apps on a given platform.
- The best possible experience on each platform they use, even if the platforms are inconsistent.
This is because users largely understand (and even embrace) that the platforms are meaningfully different and likely always will be. Furthermore, users are seriously uninterested in incurring the cognitive load of learning a litany of custom controls, interactions, and patterns for each app they install and/or website they visit.
The Myth That Won't Die
Despite this fact, there has been no shortage of attempts over the years to bridge the platforms with a single UI implementation. I’ve been around long enough to have experienced the evolution of this phenomenon from Java, to Flash, to several lower profile players in between, and finally arriving at our most recent industry additions with React Native / React Native Web / Expo / Electron / Flutter / Ionic / anything else I am forgetting.
For design system teams this approach can be extremely compelling. Imagine delivering a universal experience while resolving various platform inconsistencies!
Every man who has ventured here over the centuries has looked up to the light and imagined climbing to freedom. So easy... So simple... And like shipwrecked men turning to sea water from uncontrollable thirst...
...many have died trying.
There are about a dozen good reasons why (over the long term) this is a very, very bad strategy for engineering organizations to embrace. But, even if these holy grail chasing libraries were able to achieve their historically elusive potential for development teams, this strategy still deliberately:
- Violates platform best practices.
- Undermines user expectations.
- Increases cognitive load.
All of which will deliver an objectively worse experience to the very people paying their salary.
One Ring To Rule Them All
For many designers and developers that are already on board the #usetheplatform train, the above might seem painfully self evident.
To those readers, I say: we aren’t out of the woods yet.
Design system teams in medium to large organizations often find themselves in the position of having several development teams deploying applications to a single platform. In fact, deploying multiple applications to a single platform is often the impetus for developing a robust design system in the first place.
For the sake of specificity, assume for a moment…
- The platform in question is the Web.
- Every application uses the
Thus, the design systems of days past were often limited to reliably documented specifications and, perhaps, some accompanying CSS.
If You Give A
paradigm shift regression a rush of new developers embraced the UI portion of the stack. Conjoined with their arrival was a deluge of pedantic tendencies, embraced en masse, that have not translated effectively to how UI development delivers optimal experiences in practice (here’s looking at you, functional programming).
For design systems, the impact of this shift has been catastrophic.
<button> element and...
- Abandon the vendor agnostic and zero runtime behavior they get from the browser for free.
- Wrap it in an overly complex, painfully sluggish, statically typed, transpiled, build chain dependent, vendor locked render function.
Make no mistake about it, the utility of this approach for user experiences is entirely nonexistent. As such, those of us who prioritize our users are often told that positive externalities will necessarily emerge from the ideal developer experience.
- They are forced to use the same vendor library as the design system.
- They are forced to maintain a compatible version of that library.
- They are forced to maintain compatible patterns (such as classes versus hooks) within that library.
- They are forced to wrestle with integrating it into their build chain and deployment.
How is that documentation and CSS looking right about now?
Here is the good news: industry consensus that the SPA architecture is, by and large, a regression for the Web has finally emerged, and its departure will almost certainly include all of the headaches and nightmares described above.
So, where does this leave us in regards to choosing an implementation strategy for a design system?
Principle #1: Design Native And Build Native
Abide by them at all costs.
Bridge the platforms with your information architecture, user journeys, and design tokens.
Principle #2: Documentation Is Paramount
Documentation is flexible, scalable, platform agnostic, empowers non-technical contributors, and allows for development teams to exercise necessary discretion on the specifics of implementation.
If you can trust your development teams with the hard stuff (async programming, business logic, etc.) then surely you can trust them with the easy stuff as well (styling a
<button> element according to some basic documentation).
Narrowing down to the Web platform, specifically…
Principle #3: Don't Undervalue CSS
Certainly, there are annoyances to be incurred and challenges to be overcome, such as naming conventions, cascading, inheritance, minifying, versioning, deployment, removing dead/unused code, and so forth.
As my colleague, nemesis, and frenemy Dave O. affectionately pointed out in his own blog: