Blog

How to select a framework for design system components

Design System components aim to be a universal solution for all teams and all products in an organisation. But which technology or framework can provide this universal solution?

We’ve created a handful of design systems in the last year using different technologies. Each customer had a dominant technology like Angular, React or plain old JSP. But none of them used only that technology. A recent customer had a wide mix of PHP, Bootstrap + jQuery, Salesforce Lightning Web Components, Angular, more recently React and also native Kotlin and Swift applications. So the question rose: which framework do we use to develop design system components that could work for all their products, with all these different technologies? We got ourselves a challenge.

Just use Web Components?

Native Web Components may sound like the obvious solution. They are the universal web standard and are now supported in all modern browsers. But while Web Components offer a good low-level API, they are hard to author and maintain without a library. And sadly Web Components render in the browser, but can’t be rendered on a server (SSR). This is something most customers expect, as they have at least one major product that requires SSR for SEO and performance. So instead we looked for a framework to create universal components.

Framework criteria

A design system is a large investment. So when selecting a framework to develop design systems components with, we want to make a well thought through decision. Among our selection criteria are:

  • Framework ecosystem: maturity of the framework, the organisation behind it, documentation, examples, tutorials and availability of extensions and (compatible) libraries.
  • Compatibility with Web Components: can the framework consume and compile to components in the web standard? Custom Elements Everywhere is a good reference.
  • Runtime environments: what’s the framework bundle size? And does it support server-side rendering?
  • Compatibility with the customer: we aim for maximum adoption, so what works with most of the technology the customer uses now and plans to use in the future?
  • Popularity: it’s important for a customer to have a design system developers favour. That means using a popular framework that your current and future developers will like. State of JavaScript is a good reference.
  • Works with Storybook, ZeroHeight, or something similar: clear and interactive documentation of a design system is important for its adoption.

Framework selection

For our customer in question we considered multiple frameworks. During our inventory phase we performed desk research to compare the frameworks. We also held a workshop to discuss options and risks with developers and stakeholders from the customer’s teams. The result were two candidates to develop the design system with:

Top candidates:

  •  Stencil: using web standards, focused on design systems, small runtime, experience in  customer’s teams.
  •  (P)React: most popular framework, best option for React/Next.js apps, experience in customer’s teams.

Others considered:

  • Lit: “new” framework by Google, no experience at customer or De Voorhoede, good Stencil alternative.
  • Angular: heavy, focused on app not design systems.
  • React Native: no Web Components, not used by the customer’s native app team.
  • Svelte: lightweight, increasingly popular, but small author team, maybe less mature.

Let’s have a look at how our top candidates would be used for a design system.

Design System setup with Stencil

Stencil describes itself as “Stencil: A Web Components Compiler” and “Stencil's primary objective is providing amazing tools for design systems and component libraries.” Sounds like a good fit for a design system, so how would this work, what are the benefits and what are the risks?

Develop components using Stencil and compile them to Web, React and Angular components

Concept

  • Components are developed with Stencil using TypeScript, JSX and CSS.
  • Stencil is configured to output Web Components (custom elements), React & Angular components (see code below).
  • CI generates compiled packages for each target with Stencil runtime (7kb) + proxies to integrate with target framework (for compatibility).

This is how Stencil enables you to output to multiple packages:

import { Config } from '@stencil/core';
import { reactOutputTarget as react } from '@stencil/react-output-target';
import { angularOutputTarget as angular } from '@stencil/angular-output-target';

export const config: Config = {
  outputTargets: [
    { type: 'dist-custom-elements' },
    react({ /* … */ }),
    angular({ /* … */ }),
  ];

Benefits & risks

  • Web standards, interoperability.
  • Young framework, so few examples, libraries etc.
  • SSR needs attention due to Shadow DOM. Declarative Shadow DOM may solve this in the future.

Known compatibility issues with React & Angular. We’ve experienced this in previous projects. And Stencil also notes “All Stencil framework integrations are not yet completed”.

Design System setup with (P)React

React also makes a good candidate for design system components thanks to its maturity, popularity and ecosystem. We knew our customer had plans to build more React applications in the future and use Next.js (a React meta framework) for public websites. But at the same time they still had web applications with other technologies like Angular. So how could we make React components available as Web Components, while also keeping performance and bundle size in check? For this we looked into Preact, a lightweight drop-in replacement for React. This is how this would work:

Develop components using React and also compile them to Web Components using a Preact wrapper

Concept

  • Components are developed with React (JSX).
  • Preact-custom-element is used to wrap each component into a Web Component.
  • CI generates (compiled) packages for React projects (without bundled runtime) and as Web
  • Components with Preact runtime (3kb) + wrappers.

Benefits & risks

  • Most popular framework, large ecosystem with docs, examples and helper libraries (like MUI Unstyled and Headless UI).
  • Fully compatible with React and Next.js, including SSR.
  • Preact-custom-element is a single point of failure?
  • Do generated Web Components work well with Angular?

Server-side rendering components

As mentioned before, our customer planned to use the design system components for public websites, requiring server-side rendering, primarily for SEO and accessibility. Some of these websites would have their own server-side JavaScript runtime (like Next.js) and could simply use our React component packages. For other websites we need a different solution. For those we could create a service which they could use to render components and then include in their HTML pages. This way we support different server-side runtimes for our design system components:

Design System Components available as (npm) packages and via a (pre)render service

Concept

All of these concepts sound good on paper. But how do they play out in practice and how well do they integrate with existing technologies used at a customer? To decide between our two candidates we’ve developed proofs-of-concept during a discovery phase.

Which technology is right for you?

We ended up selecting (P)React for our customer, because it integrated best with their current technologies and future plans. Which framework is best for your design system depends on your criteria. Things change over time, frameworks evolve, web standards expand. This means that we take these steps every time we need to select a framework for a design system. 

Need help with your design system? Contact us.

There’s a lot more to creating and implementing a successful design system. So we plan to share more on the different steps involved. One important step is the designing of the system. Valsplat has written an excellent article on this on a project we did together:  Designing a world class design system (Dutch).

You might also like:

← Alle blogposts