Note: This is very new and is a work in progress - nowhere near ready for use yet!
This is a web component implementation of the U.S. Web Design System's (USWDS) library of open source UI components. The goal of this library is to reduce the barrier to entry for using USWDS components.
The development process uses Stencil, but the resulting web components can be used within any framework, just like regular HTML 😍.
If you're working with basic HTML, you can add the library with a single script tag. After that, you can start using the web components!
For use with frameworks like Angular, React, Vue, and Ember, see the Stencil documentation.
<!-- minimal example usage -->
<html>
<head>
<script src="uswds-web-components.js"></script>
</head>
<body>
<usa-button>
<button>Button</button>
</usa-button>
</body>
</html>
Once things are set up (see Getting started), here's how to work with the web components:
- Look through USWDS components documentation
- Grab component HTML from an example
<button class="usa-button">Default</button>
- Wrap that HTML with the corresponding web component from this library
<usa-button> <button class="usa-button">Default</button> </usa-button>
- (Optional) Remove redundant classes like "usa-button" while retaining styles
<usa-button> <button>Default</button> </usa-button>
That's it! The web component will automatically handle loading relevant styles, scripts, and assets that you'd normally need to set up manually.
First, let's look at the USWDS button documentation to see what code is needed to make a button:
<!-- from USWDS documentation -->
<!-- assumes USWDS styles, fonts, images,
and scripts are loaded -->
<button class="usa-button">Default</button>
This is a regular HTML <button>
with a class named "usa-button", which is used for styling.
Let's try taking the same code from USWDS's documentation, and wrapping it in a <usa-button>
web component:
<!-- assumes uswds-web-components.js is loaded --->
<usa-button>
<button class="usa-button">Default</button>
</usa-button>
This gives you the same result, even though we didn't include any styles or fonts. All the styles, fonts, images and component-specific scripts live inside the web component.
Since <usa-button>
knows it's a USWDS button, the "usa-button" class is redundant. Let's see what happens when we remove it:
<!-- the code you write -->
<usa-button>
<button>Default</button>
</usa-button>
If we inspect the rendered component in the browser, the HTML looks like this:
<!-- what's actually rendered in the browser -->
<usa-button class="uswds-web-components">
<button class="usa-button">Default</button>
</usa-button>
The web component is automatically adding in the "usa-button" class that the button needs in order to be styled correctly. Cool!
What about a component that uses JavaScript? Let's see what happens when we add a tooltip to the button. The USWDS tooltip documentation says that tooltips are progressive enhancements for the title
attribute:
<!-- the code you write -->
<usa-button>
<button title="Tooltip">Default</button>
</usa-button>
Here's what's rendered in the browser:
<!-- what's actually rendered in the browser -->
<usa-button class="uswds-web-components">
<span class="usa-tooltip">
<button
title=""
class="usa-button usa-tooltip__trigger"
aria-describedby="tooltip-949101"
tabindex="0"
>
Default
</button>
<span
class="usa-tooltip__body"
id="tooltip-949101"
role="tooltip"
aria-hidden="true"
>
Tooltip
</span>
</span>
</usa-button>
That's a lot of changes! Here's What's happening under the hood:
<usa-button>
adds a "usa-tooltip" class to the<button>
element (just like how it's adding the "usa-button" class)<usa-button>
imports and initializes the official USWDS tooltip script.- The USWDS script handles the rest of the changes shown above.
Pretty slick!
Here are some answers to questions that I've asked myself:
Why include the
<button>
element in the light DOM when we could hide it in the shadow DOM? Wouldn't it be nicer to write something like<usa-button>Default</usa-button>?
One reason for this is for better search engine optimization (SEO). Some search engines don't see or understand content that's in the shadow DOM (see this post on Web Components and SEO), so it's a good idea to retain sematic content in the light DOM instead.
Another reason is for simplicity and consistency across the web components.
- how would this work in more complicated components?
- easier to understand what the code you're writing is actually doing
- https://lea.verou.me/2020/09/the-failed-promise-of-web-components/
- easy to just copy code snippets from USWDS documentation, paste inside a web component, and have it just work
- no new API's to learn
Isn't one of the big selling points of web components style encapsulation?
Yup!