Introducing Shoelace, a Framework-Independent Component-Based UX Library
Web Components are great, but there’s currently a few small hitches to be aware of.
That said, there are other ways to get Web Components to
just work with a web app that’s SSR’d with something like Next. The short version is that the scripts registering your Web Components need to run in a blocking script before your markup is parsed. But that’s a topic for another post.
Of course, if you’re building any kind of client-rendered SPA, this is a non-issue. This is what we’ll work with in this post.
This renders some nice, styled tabs. The underline on the active tab even animates nicely, and slides from one active tab to the next.
I won’t waste your time running through every inch of the APIs that are already well-documented on the Shoelace website. Instead, let’s look into how best to interact with, and fully customize these Web Components.
Calling methods and subscribing to events on a Web Component might be slightly different than what you’re used to with your normal framework of choice, but it’s not too complicated. Let’s see how.
…and bind it:
Now we can add a button to call it:
That works and logs the event objects as you show different tabs.
Typically we render tabs and let the user click between them, so this work isn’t usually even necessary, but it’s there if you need it. Now let’s get the dialog component interactive.
The dialog component (
<sl-dialog>) takes an
open prop which controls whether the dialog is… open. Let’s declare it in our Svelte component:
It also has an
sl-hide event for when the dialog is hidden. Let’s pass our
open prop and bind to the
hide event so we can reset it when the user clicks outside of the dialog content to close it. And let’s add a click handler to that close button to set our
open prop to
false, which would also close the dialog.
Lastly, let’s wire up our open dialog button:
And that’s that. Interacting with a component library’s API is more or less straightforward. If that’s all this post did, it would be pretty boring.
But Shoelace — being built with Web Components — means that some things, particularly styles, will work a bit differently than we might be used to.
As of this writing, Shoelace is still in beta and the creator is considering changing some default styles, possibly even removing some defaults altogether so they’ll no longer override your host application’s styles. The concepts we’ll cover are relevant either way, but don’t be surprised if some of the Shoelace specifics I mention are different when you go to use it.
As nice as Shoelace’s default styles are, we might have our own designs in our web app, and we’ll want our UX components to match. Let’s see how we’d go about that in a Web Components world.
We won’t try to actually improve anything. The Shoelace creator is a far better designer than I’ll ever be. Instead, we’ll just look at how to change things, so you can adapt to your own web apps.
Take a peek at one of those tab headers in your DevTools; it should look something like this:
Our tab element has created a
div container with a
.tab--active class, and a
tabindex, while also displaying the text we entered for that tab. But notice that it’s sitting inside of a shadow root. This allows Web Component authors to add their own markup to the Web Component while also providing a place for the content we provide. Notice the
<slot> element? That basically means “put whatever content the user rendered between the Web Component tags here.”
<sl-tab> component creates a shadow root, adds some content to it to render the nicely-styled tab header along with a placeholder (
<slot>) that renders our content inside.
The exceptions to this are inheritable styles. You, of course, don’t need to apply a
font-family style for every element in your web app. Instead, you can specify your
font-family once, on
html and have it inherit everywhere beneath it. This inheritance will, in fact, pierce the shadow root as well.
<sl-tab-group> component reads an
--indicator-color CSS custom property for the active tab’s underline. We can override this with some basic CSS:
And just like that, we now have a green indicator!
In the version of Shoelace I’m using right now (2.0.0-beta.83), any non-disabled tab has a
pointer cursor. Let’s change that to a default cursor for the active (selected) tab. We already saw that the
<sl-tab> element adds a
part="base" attribute on the container for the tab header. Also, the currently selected tab receives an
active attribute. Let’s use these facts to target the active tab, and change the cursor:
And that’s that!
That code is in the
App.svelte file. Comment it out to see the original, default animation.
Shoelace is an incredibly ambitious component library that’s built with Web Components. Since Web Components are framework-independent, they can be used in any project, with any framework. With new frameworks starting to come out with both amazing performance characteristics, and also ease of use, the ability to use quality user experience widgets which aren’t tied to any one framework has never been more compelling.
If you need help creating a digital marketing strategy for your business, don’t hesitate to contact one of Digidude’s consultants.