Balancing Stability and Innovation in Design Systems
Design Systems are critical infrastructure. They should be taken seriously. I like having a conversation about each Design System change to ensure it fits with the overall vision–while also making sure it won't break production for our customers. I like pushing for 100% test coverage. I like having visual regression testing. These things help ensure your critical infrastructure is well tested–you'll be more confident in your changes with these tools and processes in place.
But while Design Systems should move slow and be intentional about every external change, there's also room for internal innovation. Internal innovation can happen much faster than shipping features, as the feedback loop is much tighter–it's immediately affecting your internal Design System team. Internal innovation in a Design System is a great way to prove out ideas before deciding to ship them more broadly.
We're system thinkers. We're good at generalizing things and thinking about how to make something general-purpose. So this type of work fits really well with Design System folks' skillsets, in my opinion.
What exactly do I mean by "internal innovation"? Anything that would speed up your Design System team to ship features. Or something that'd help improve the system, increase accessibility, or raise/ensure the quality bar. And bonus points if it's helpful and could be generalized for teams outside of your group. You may also find that opening the door for this leads to benefits to your users as well.
Example: Filling gaps
Glide Core is archived on GitHub, but you can still view the code. We decided to create a @required decorator to enforce Web Component attributes (or properties) to be required. This is something that Lit doesn't provide out of the box (for good reason).
We wanted to ensure our form elements always have a label for accessibility reasons. Using the @required decorator allowed us to enforce that.
This is an example of something that starts in the Design System, but could be generally helpful for almost anyone using Lit. And once again–it's good for accessibility, which does impact users.
Example: Shared ESLint rules
I recommend writing your own ESLint rules. There are a ton of advantages. These lint rules may begin in your Design System, but may be helpful generally to others as well. Just like the decorator above.
ESLint rules may help nit-picks on PRs. If a robot can automate opinions, it's less time spent in a PR review going back and forth on something.
Example: New tooling
The web development ecosystem changes quickly. New tools land. Some of them are great, others are noise–that's another topic. But say you want to switch to a different test runner internally that'll give some benefit to your team. Doing this internally is a great way to prove it out, without negative impact on your users.
For example, say you're on jest. Switching to Playwright would mean you could run your tests in a real browser. You could configure visual regression testing. You could make use of their accessibility testing. This type of change also has an impact on end users–they benefit from a more stable and reliable product. +1 to the "critical infrastructure" comment.
Additionally, making this switch may give you confidence to propose this change more broadly across the organization.
"Switching to Playwright meant we improved our quality by testing in real browsers and interacting with the elements in tests just like our users. We also took advantage of visual regression and accessibility testing.".
Sounds pretty cool to me.
Example: Replacing dependencies
Using a third-party package allows you to use something off the shelf and get going. But not every package solves your exact needs. Some may no longer be maintained. Ideally you can contribute to open source software to help make the world better for everyone. But if not, building internal tools that replace unnecessary dependencies means less external dependencies and less risk. Especially with the recent supply chain attacks on npm packages.
Lowering our dependence on third-party packages is a good thing, in my opinion. Browser features keep getting better. Just use the platform (where you can), bro, please.
You get the idea
Above are some examples that came immediately to mind. But hopefully you get the idea. How can you retain the quality and stability our customers expect with a Design System being critical infrastructure while also keeping up with the times and potentially making life better for your team? For your users? For other engineers in your organization? I think this is how. Embrace a model of internal innovation, while not negatively impacting the Design System externally.
Take a look at your Design System. How's your team doing? Do you feel like there are things the Design System could innovate on to improve processes for your team? Are there opportunities to improve design consistency or testing practices? Are there things currently private to the Design System that could be generally used and helpful to others?
Spending time on innovation keeps the train moving. It may also scratch the "I have an idea itch" for some of your engineers. While some of these things impact the Design System team only (which is still good!), it could lead to great benefits to your Design System consumers. And even your product's users. And that's cool.
Tony Ward