A design system is much more than a set of HTML elements, CSS styles, and typography. It's a way of thinking about the world and how the world will see you in it. It builds consistency, which becomes familiarity, which builds trust between you and your users. It frees your team to experiment, prototype, and learn, and it makes it much easier for your newest hires to contribute on day one.
In software, a design system has the added advantage of reusability. Color & size definitions, arrangement of DOM nodes and CSS classes, animation parameters, and interactivity are, with planning, not only reusable in the actual product, but can be updated independently of the product itself.
Design systems for web apps typically incorporate a living style guide, a code-driven view of the state of design tokens and elements. They may also implement a playground for each component, letting the developers and designers experiment with the component in question to try different usages of the component using real code.
Vue makes a lot of pieces of building a design system very easy:
There were two talks (one of which, by Miriam Suzanne, has a video up now) about the state of design systems and living style guides at VueConf 2018. The Tidelift frontend was starting to get large enough that we were building some reusable components, but it was hard for a designer knowledgeable with HTML & CSS to get in there and modify them. We decided to go with the Vue Design System, which wraps up a living style guide and design token system.
When I asked for comments about the design system so far, developer Amanda McDermott says, "How do I make sure people know where to find things like common styles, mixins, components, and assets? How do I make sure the documentation for all these things exists and is kept up-to-date? Using a design system provides clear solutions to both problems, and helps limit the influence of implicit institutional knowledge."
Still a work in progress. There’s a lot of defaults left over from the stock Vue Design System, but we’ll get there.
In the prior component-based style guides I’ve worked on, there were two approaches for filling the guide: extract-and-reuse an existing component, or create a new component from scratch. When we started on the design system, we had a handful of components we either wanted to create or wanted to standardize:
With these first three targets for standardization and documenting, we were off!
The extracted Toggle CI Switch in action within the living style guide, complete with props and event documentation. Being able to interactively test the component within a self-contained Vue instance made development very fast.
We are still experimenting with our workflow, so post-mortems, filled out by both the developer and designer involved on the component, are important for growth. At this stage, much of the feedback revolves around learning how Vue works and how to handle merge conflicts. Once time goes on, I hope more of the comments move toward using testing-related issues and trialing new versions of components in the app for user feedback.
“Being able to experiment in a component without taking up engineering time was awesome!” says designer Lauren Hanford. “This will allow us to focus on the usability of a feature when we pair, knowing that we can easily change the visual design and push consistency out across the app later. Also, how I feel about scoped CSS:”
One thing we added was unit testing using Mocha and Chai (VueDS added Jest in version 2.1 and we started using it at 2.0. Still, I prefer Mocha+Chai over Jest and would’ve changed it out anyway). Again, with the way that Vue single file components work, writing unit tests against components and getting the tests to run on each Travis CI build was a piece of cake. We have not tried venturing into snapshot tests yet (there is a Chai plugin for that). I know that will prompt some discussion about usefulness after we’ve had some time to get used to the design system.
The recommended way of getting the design system into your Vue app is by publishing a private NPM package of the final build, but we found that dealing with multiple NPM users and private package access for each was way more difficult than committing the dist folder on each internal version bump. When an update to the design system happens, a PR is merged to master, the NPM version is incremented right on the master branch, and the contents of dist are committed with that version bump and made accessible to the Vue app when it’s included in package.json using a git+ssh URL. Will this bloat up the history and repo size of the project? Sure, but for us, the tradeoff was worth not having to manage a ton of individual private NPM accounts.
The real test will be when we start using the design system in non-Vue ways. We have a static site that has a lot of the same tokens and elements as the app. These are currently being built by hand, but finding a way to reuse the HTML from the Vue components and the CSS in static areas will save time. So far, developer and designers at Tidelift have been loving using it!
If you're interested in learning more about Tidelift and the Tidelift Subscription (now supporting the Vue.js ecosystem), subscribe to updates and follow us on Twitter.