These days many companies bet on building and using design systems to make their design processes easier and more consistent, and there is a lot of information available. A lot of people have written about it and shared their experiences. There are dedicated design system Slack channels, websites, GitHub repositories and multiple conferences available on this topic.
If you are looking at larger sites or systems, you really want to ensure that you build a library of components, not only to get your visual language across consistently, but also to make components manageable and system maintenance as easy as possible.
For Colloq we knew we wanted to have a component library in place that exactly did serve all of these needs. For the first couple of months it’s been fairly easy to build additional components, but as our application has evolved, our system has grown, too. We now have more than 150 components that we are actively using on the site.
There are lots of resources and examples of component libraries showing their approaches and discussing the how to build such libraries. But it’s rare that you can read about the constant challenges teams can face when growing a design system or changing a design later on. In this article I want to share one of the issues we came across and provide some insight into how we solved it:
In the image above you can see an example of our SpeakerCard list items using
li elements on the left, and a single use SpeakerCard using a
div element on the right.
Components and correct semantics
While I always like to assume (and hope!) everybody builds their websites and applications following web standards and writing semantically correct code, it can be a tough challenge to achieve in complex, modular systems. With a component library you will sooner or later face the issue of getting the correct semantics in place.
We have a component called
SpeakerCard. This component is then included into an
ul wrapper on the listing page.
Our SpeakerCard’s component markup:
<li class="speaker-card"> <p>SpeakerCard content here</p> </li>
The SpeakerCard wrapper partial:
<ul> <?php echo $this->partial( 'Components/SpeakerCard/Default' ) ?> </ul>
Now we have a detail page displaying one of these list items. But we also want to use the same component in other places, only showing a single speaker. Since it technically isn’t a list (of one) anymore, we want to use the same component, but without its list structure (
ul wrapper and
li element) to avoid ending up with incorrect semantics. When we tried to create a flexible solution, we found a relatively simple implementation that allows us to change a component’s container element to anything we like.
Let’s take the example where we want to display our SpeakerCard with a
div as our container element. To achieve this we can call our component partial with an additional parameter that defines its wrapper:
<?php echo $this->partial( 'Components/SpeakerCard/Default', array( 'speaker' => $speaker, 'element' => 'div' ) ) ?>
In our component partial template, we first check for the $element parameter. If one has been passed, we wrap the component with an escaped $element-element, which in this example is our
<div> from above. Otherwise we’ll fall back to using our default wrapper element
<?php if ( !isset( $element ) ) $element = 'li'; ?> <<?php echo $this->escape( $element ) ?> class="speaker-card"> <p>SpeakerCard content here</p> </<?php echo $this->escape( $element ) ?>>
This additional parameter for our component partial call enables us to always output semantically correct markup. This allows a lot of flexibility on where we can use the components of our system in different sections and parts of our site. Our example using PHP is only one solution to this problem, but the same concept can be used in other languages or frameworks and avoids ending up with a non-semantic application consisting of only generic
It would be great to hear how you have solved similar issues or other specific challenges you came across when working on your design system or component library. If you want to have a closer look at our components at work, head on over to colloq.io and check it out! Please reach out for comments and other ideas on now to approach challenges like this one.