Cory Rylan

My name is , Google Developer Expert, Speaker, Software Developer. Building Design Systems and Web Components.

Follow @coryrylan
Web Components

Reusable Component Anti-Patterns - Semantic Obfuscation

Cory Rylan

In this post we will take a look at one of the common pitfalls when designing a highly reusable UI component. We will look at the various tradeoffs when rendering application provided content within our reusable component.

When designing composition-based component APIs, it is important to push the semantics of the HTML into the light DOM or within control of the consumer. This helps to create valid DOM structure and improved overall accessibility. For example, if a card component includes an h1 heading, this creates an incorrect DOM structure as there should only be one h1 element within the page. By pushing the semantics of the heading up into the light DOM, the consumer can control the heading level and ensure that the page structure is correct.

<!-- ui-card internal template -->
<h1><slot name="header"></slot></h1>
<slot></slot>
<slot name="footer"></slot>
<!-- consumer API -->
<ui-card>
<div slot="header">header</div>
<p>content</p>
</ui-card>

It is important to push the semantic meaning of elements up to the consumer, rather than obfuscating it internally. This enables the consumer to control the appropriate heading levels for their page, which is important for accessibility and features like aria-describedby for associating content. By exposing the semantic meaning of elements to the consumer, we can enable more accessible and flexible behaviors in our components and libraries.

<!-- ui-card internal template -->
<slot name="header"></slot>
<slot></slot>
<slot name="footer"></slot>
<!-- consumer API -->
<ui-card>
<h2 slot="header">header</h2>
<p>content</p>
</ui-card>

This example uses Web Components and Shadow DOM however this principal applies to frameworks as well, like React children props and Angular ng-content.

Composition-based APIs may sometimes be more verbose than other approaches, however they have the advantage of lowering the overall API surface area of the system and ensuring that there is only one way to use any component. This makes it easier for consumers to learn and use the APIs, as the usage remains predictable and reliable throughout the system.

API abstractions can provide a convenient layer on top of the components, making them more concise and opinionated while still enabling consumers to access the reusable components directly as needed. However, it is important to carefully consider the tradeoffs involved in using these abstractions. It's easier to add new abstractions but much more difficult to fix or remove the wrong abstractions.

Twitter Facebook LinkedIn Email
 

No spam. Short occasional updates on Web Development articles, videos, and new courses in your inbox.

Related Posts

Lit Web Components

High Performance HTML Tables with Lit and CSS Contain

Learn how to easily create HTML tables in Lit with high performance rendering using CSS contain.

Read Article
Lit Web Components

High Performance HTML Tables with Lit and Virtual Scrolling

Learn how to easily create HTML tables in Lit from dynamic data sources.

Read Article
Lit Web Components

Creating Dynamic Tables in Lit

Learn how to easily create HTML tables in Lit from dynamic data sources.

Read Article