Shoelace: A Web Component Kit
shoelace.style
shoelace.style
All issues I can see are fairly minor. I'd like to see inputs use the native formAssociated api rather than just relying on hijacking FormData (though using the FormData hijack as a fallback). Component scoped design tokens should be part of the `:host{}` style for that component, not in the global scope. Semantic tokens would also be a better approach for improved themability. The localization is hacky, but I'll give the authors major props for actually pushing a suggestion to the spec[1] to allow for better handling in native components.
Some other minor things I'd like to see is performance comparisons with similar React/Vue/Svelte components as well. Webcomponents can fall into poor performance when there are many occurances that overuse observedAttributes.
All in all though, this library looks really great.
Look neat. They even have Typescript type definitions to it.
I did a simpile test with ScalablyTyped in order to import those into ScalaJS to no avail but there might be a fix.
It looks strictly OK if you just glance at it from a distance, but was incredibly buggy across every single browser that I threw at it, and SLOW AS HELL to boot. I'm talking UI elements taking a second or so to respond to actions that don't even interact with anything over the network.
I don't know how much of this is just down to the app itself being poorly designed and built, but just looking at the UI5 components was enough to make me recoil in disgust.
If they are eating their own dog food it needs some work, if this page is any indication
The only parts I don't like are the event based APIs.
It's 2022, I feel like we've settled on promises as the best way to handle async.
The author wasn't particularly receptive to the issue I raised around it, even offering to create a PR.
I think event based APIs are really holding what would otherwise be a very nice component set back.
That said, while promises are a very useful tool, I consistently find events to be an easier mental model to work with in the context of the DOM. This is primarily due to the bubbling nature of events.
It's entirely possible that you and your friends concluded in a bubble that promises are the pattern to rule them all, but don't speak for all of us.
Web components are nice and all but they need JS and I want my sites to work without JS.
My top-level comment thread there is particularly still relevant and applicable; the mandatory use of Shadow DOM means client-side JavaScript execution is required and server-side rendering impossible, which I don’t think is good for most web stuff.
- https://github.com/airbnb/hypernova
- https://github.com/prerender/prerender
Fans of efficiency and simplicity might recoil but if it works and is easy to setup, these far out approaches might just catch.
- https://github.com/WICG/webcomponents/issues/788
- https://github.com/w3c/DOM-Parsing/issues/58
- https://github.com/w3ctag/design-reviews/issues/494
- https://web.dev/declarative-shadow-dom
In pre-render they seem to have started in this direction extremely recently:
https://github.com/prerender/prerender/pull/731/files
I don't use prerender so I can't definitively speak to it being solved and hiccup-free, but I think that limitation is going to go away in the future.
So you certainly can’t rely on scriptless server-side rendering of Shadow DOM being possible—it’ll work in Chromium only, and it’ll probably be at least another year or two before other browsers even contemplate doing anything with it.
(And of course, even once Shadow DOM is serialisable, that’s a far shot from a particular frameworky thing being SSR-compatible, but I was quibbling over the Shadow DOM and impossibility aspects, so I shan’t step back on that.)
I personally know that I make the choice between client-side rendered (Vue, Svelte, Mithril, Lit, etc) and server-rendered (Nuxt, SvelteKit) these days and I purposely made the choice to use client-side rendered when I was dogfooding my own native web component project. Looks like it's still a choice that has to be made and SSR isn't quite there (everywhere) yet.
Kudos to Shoelace for including a draggable splitter which is usually missing from other libs.
The web is stuck in the perpetual "reinvent the concept of circle" stage without even moving onto "reinvent the wheel" stage. This "great and new" lib is literally indistinguishable from, say, jQuery UI from almost 20 years ago.
The day-today enjoyment of writing code has withered away somewhere.
Native web components are the endgame for flourishing frontend ecosystem (that many see as mostly waste, and sometimes they're not wrong) -- in the future you'll be to build whole sites writing HTML like:
<script src="/path/to/some/custom-component"/>
...
<custom-component> ... </custom-component>
That's the future Shoelace is helping bring about and I think it's a really nice minimally, and paradoxically simple way to build webpages that have the functionality you want without the hassle of heavier frameworks, if you're lucky to find just the right component to spice up your page.I will say that it's hard to execute cleanly on this vision and it looks like Shoelace is doing a pretty good job -- I made a small contribution to this space[0], and I have to say that getting started with my project is much less clean (as far as dogfooding goes it was functional but didn't taste great!).
Looking forward to trying out Shoelace in the future.
One thing I really want to see tackled though (by a standards body) is the data management story. Maybe it's best left to practitioners and library authors but I think something like services-as-DOM-elements[1] (disclaimer: I thought this up) could work. Then we get a world where we can drop pre-made display elements and pre-made data stores onto pages.
Also heavy mention to tailwind -- the class soup bit is annoying but it's sparked an absolute explosion of reusable templates which I think are helping people build better looking sites faster than ever before. Just like with Bootstrap, of course, we're all getting tired of seeing really similar design elements but the acceleration is probably a net good, even if it requires abusing CSS a little bit.
They are decidedly not the future. If they were, they wouldn't implement the same primitive components that we were re=implementing twenty years ago.
> Native web components are the endgame for flourishing frontend ecosystem
They are not.
> in the future you'll be to build whole sites writing HTML like
Funny you say that. Because the original vision of Web Component was against quote, "great example of an empty body tag, and sort of this pathological case of piling yourself into the JavaScript boat" [1]
But now it's apparently "pile everything into a Javascript blackbox"
> it's a really nice minimally, and paradoxically simple way to build webpages that have the functionality you want without the hassle of heavier frameworks
It is literally a framework that you still have to tie together with data handling, events etc. Just because you hide it behind a "custom-component" doesn't mean the complexity has gone anywhere.
> One thing I really want to see tackled though (by a standards body) is the data management story.
Ah yes. The data management story.
> Then we get a world where we can drop pre-made display elements and pre-made data stores onto pages.
And how exactly do you propose to "just drop them" onto pages? Have you also perhaps solved the API story for those elements? I mean, isn't it the great lie that web components perpetuate of "just use premade components"?
And yet there are now a few hundred avatar web components, several thousand button components, a million badge components, and all of these primitive things are not compatible with each other.
[1] https://fronteers.nl/congres/2011/sessions/web-components-an...
My browser has a loading bar and your web page is not a video game pulling in hundreds of megs of assets in the background. What could possibly justify this kind of behaviour for a UI toolkit?
Asynch page fetching is faster, but not instant. If you have a reliable way to improve your app's responsiveness but can't drive a native progress bar, what offers a better UX? A subtle, tasteful custom progress effect or nothing? Or do you declare the entire approach invalid on a technicality?
That seems reductive and petulant, like giving up your favorite wine because the winery switched to screw caps for sustainability reasons.
Not saying these apply to Shoelace, but it's also the sort of page that really doesn't need a spinner on first load. Let the browser load things, it already knows how to do that pretty well. 3G connections you say? Send me the unstyled HTML first so I can at least get to the content instead of making some bullshit spinner that will probably crash anyway.
I hate the modern web.
The behaviour you are describing would indeed be frustrating. It describes (well) many of the sites built with SPAs, IMO.
Thankfully, that's not at all what I'm talking about. My stack - server rendered content, Turbo Drive for asynch page loads, Stimulus for light client interactivity that doesn't involve permanent state - is amongst the most battle-hardened.
In real terms, hard page refreshes take hundreds of ms on top of whatever data is sent. Turbo Drive can replace content in whatever real-time is, which is especially noticable on mobile devices. A properly constructed Turbo Drive powered app can therefore feel native to most users, but with server-rendered content.
If you haven't tried it, you might be shocked when you do.
As an addendum: Shoelace is not my site, and I share your distaste of "Loading" prerolls. That said, a quick blue line across the top of the content area that you only see for the same amount of time you'd be waiting for content to load anyhow seems distinctly fine - and that is, not coincidentally, exactly what Turbo Drive does out of the box.
If my page has an accordion or tab component will Google be able to crawl the text inside it?
If the content is part of rendered html and wrapped into webcomponents, crawers have no issues accessing that. If the content is loaded dynamically and injected into open mode shadow dom then js enabled crawlers should be able to crawl those too.
If the content is hidden away inside closed mode shadow dom, and also the content is not part of initial HTML then there is no way for a crawler to access it.
Even if lit gets discontinued/deprecated/whatever, they can gradually switch to another library one component at a time. And the user's won't have to do a thing.
lit is strictly an implementation detail, and the consumers just care about the web component API which is part of the browser platform.
Also, if I have web components, why do I need React?
In react you will be calling <Button> components, whether those are web components or react components doesn't take away from what react is great at: giving you a framework for declaring a reactive ui. Having the base components as web components makes them framework agnostic. maybe you don't need react.
React was like a long, painful specs gathering process. Going forward, I would never start a major project with React when simpler, standards-based approaches are now just as viable.
The main reason people use web components for buttons is to provide a consistent API and DX, and to facilitate themes and code reuse.