Hacker News new | past | comments | ask | show | jobs | submit login
Shoelace 2.0 release: UI toolkit that works with all frameworks or none at all (shoelace.style)
218 points by 1337shadow on July 17, 2020 | hide | past | favorite | 110 comments



Shoelace author here.

A couple days ago, I released Shoelace 2.0, an open source library of common UI components.

These components work with any framework, can be loaded via CDN, are fully customizable with CSS (no preprocessor required), and install easily with a simple script + stylesheet. They were built with Stencil.js, which is a fantastic tool. The end result compiles down to vanilla web components.

Each component was designed from scratch to be lean, customizable, and easy to use. Accessibility is a common question folks have about component libraries. I’m definitely not an expert here, but I've spent a lot of time trying to get it right. I would like to echo the experts and say that accessibility only starts with components, but hopefully having a good foundation to build on will encourage others to think about it more at higher levels.

I hope you'll take a second to check it out! I'm happy to answer any questions you have about the project, how it's built, etc.


Longtime user of bootstrap & tailwindcss for pet projects. I've looked at the 'What Problem Does This Solve', but I'm not sure where Shoelace could fit into my workflow.

Bootstrap is great for when I just want to quickly prototype and build a decent looking interface, but it feels confined when I start wanting to style things myself. When designing MPAs I typically use Bootstrap.

Tailwindcss is great for styling anything and everything, but I find sometimes I waste too much time styling little things that other CSS frameworks already have nice defaults for (and I am a terrible designer so this compounds my dificulties). I often use tailwind for SPAs.

Forgive me if my question is a little naive, but where could I fit Shoelace in for pet projects? Do you see it as being a suitable replacement for one of these usecases? Complementing them? Does it lie somewhere in the middle?


Shoelace is more akin to Bootstrap. You can use it for quickly tinkering, prototyping, or as a foundation for your own design system.

One thing Shoelace doesn't provide right now is a set of base styles. I've considered offering these as an opt-in CSS class or a <sl-prose> component, but I'm not sure it belongs tightly coupled with the library.

On one hand, it makes sense to provide a single "theme" that styles both components AND the underlying website/app. On the other hand, this will make themes very opinionated and potentially overbearing. I still need to think about this more.

In the meantime, you can use something like Tailwind's typography plugin [1] to handle base styles and use Shoelace in lieu of Bootstrap. IMO Shoelace + Tailwind is a great combination for those who prefer utility classes.

1. https://github.com/tailwindcss/typography


What would be the convention for using tailwind to style components in general?


You can use Tailwind classes on all your markup as you normally would. In terms of Shoelace components, they're more limited to layout, spacing, flexbox, grid, etc. for arranging and positioning (e.g. don't expect class="btn btn-blue" to turn a Shoelace button into a Tailwind button — although you can use them alongside each other if you want).

To style the internals of a Shoelace component, you can target it in a stylesheet using CSS custom properties or CSS parts as described in the docs. [1]

1. https://shoelace.style/getting-started/customizing


Sounds great! I'll have try it out in my next pet project.


I think Shoelace would be roughly equivalent to if Bootstrap offered web-component versions of their components, so instead of

    <button class="btn btn-outline-secondary">...</button>
would be like:

    <bs-button outline color="secondary">...</bs-button>

While this doesn't sound all that useful, I think this would be very handy for the interactive components like popovers, tooltips, carousels that need a lot of tag soup and javascript:

    <bs-popover>
      Hello World
    </bs-popover>


The "in" animation on components like dialog or drawer doesn't seems to work on Firefox (78.0.2 on Windows). Very abrupt in, smooth fade/slide out.

Also there are small version of buttons but none for other form controls which is quite odd.

Seems nice and lightweight overall. I would love to see a dark version too.


This was addressed for the drawer here: https://github.com/shoelace-style/shoelace/issues/103

I can't seem to reproduce this for other components, but I'll check again.

> Also there are small version of buttons but none for other form controls which is quite odd.

Button, input, textarea, and select all have size variations. It's missing from checkboxes, radios, and switches but I'm not sure how useful that is. Feel free to submit an issue so folks can vote on it.

Edit: this has been identified and fixed in dialogs!


I had a look through the docs, and this looks really nice - a great collection of components, and well documented too!

I'm new to web components though, so I was surprised when I saw in the docs that you need to use the CSS `::part` selector to style components, rather than simply using more "traditional", well-known CSS. Is this a result of using a shadow DOM? If so, what benefits does using a shadow DOM use for these components?

Thanks!


This is an intended side effect of using a shadow DOM. I tried to outline the advantages in the Customizing section of the docs [1] and I think these three points will answer your question.

- Customizations can be made to components with explicit selectors, such as ::part(icon), rather than implicit selectors, such as .button > div > span + .icon, that are much more fragile.

- The internal structure of a component will likely change as it evolves. By exposing component parts through an API, the internals can be reworked without fear of breaking customizations as long as its parts remain intact.

- It encourages us to think more about how components are designed and how customizations should be allowed before users can take advantage of them. Once we opt a part into the component's API, it's guaranteed to be supported and can't be removed until a major version of the library is released.

1. https://shoelace.style/getting-started/customizing?id=compon...


Understood - I'm more of an old-skool CSS kind of person, but this explanation makes good sense.

I had another look at the docs, but I still don't see anything about the benefits of shadow DOM for this library (unless the benefit is the "part thing"?)


The shadow DOM encapsulates styles and behaviors in the component. Nothing leaks in, nothing leaks out.

The concept can get confusing, especially once we start talking about how styles reflect on slotted content (i.e. elements in the "light DOM") vs. shadow DOM elements, but that's probably more relevant to component developers rather than consumers.


Is it inspired by element ui [0] in any way ? The look and feel is very similar.

[0] https://element.eleme.io/#/en-US/component/installation


Yes! I love Element. I mentioned it here in the attribution section. https://shoelace.style/?id=attribution


Great. Your link to element ui on the attribution page is broken btw. Looks like it is adding the base url of shoelace to the element ui url. So the link is showing as "shoelace.style/element.eleme.io"


Good catch. I'll get that fixed!


As someone new to web components, I'd love to see an example app/site made with this - something really simple, with no frontend framework, just showing how you use them.


I'm not sure what is your definition of vanilla, but I suppose the output of stencil.js comes with a VDOM runtime.


Of course, there are underlying utilities that enhance the components. The resulting components are standard web components.

From Stencil's website [1]:

> Stencil is a compiler that generates Web Components (more specifically, Custom Elements) and builds high performance web apps. Stencil combines the best concepts of the most popular frameworks into a simple build-time tool.

> Stencil takes features such as Virtual DOM, async rendering (inspired by React Fiber), reactive data-binding, TypeScript, JSX, and Static Site Generation (SSG) and then generates standards-based Web Components and web apps with these features baked in.

1. https://stenciljs.com/docs/introduction


Digging this! Nice work.


My biggest concern with using Shadow DOM for things like this is that it makes it depend upon JavaScript, which I strongly prefer not to do.¹ I know there’s some research work into declarative Shadow DOM², which has the potential to resolve this, but that’s still quite some way off. As it stands, I don’t feel comfortable using Web Components with Shadow DOM for things like this, which is a pity, because it’s a delightful way to work, and this toolkit looks very good in most regards. Instead, I like Svelte’s model which essentially allows you to write things this way, but have it result in light DOM, so that you can still do server-side rendering if you desire.

¹ Requiring JavaScript harms accessibility, especially for web pages (as distinct from web apps). It makes pages take longer to load, not be as spider-friendly, and be more fragile when JavaScript fails to load, whether deliberately or accidentally—and simple network failures and the likes break things more often than you might imagine. I myself browse the web with JavaScript disabled via uMatrix, mostly because it speeds the web up a lot on average. Privacy improvements are a distant secondary reason. When I encounter pages that require JavaScript, I either give up on them or open them in a Private Browsing window, where I don’t have the uMatrix extension enabled; or if it’s something I expect I may be using more than once or twice, I see about more precise whitelisting in uMatrix.

² https://github.com/whatwg/dom/issues/831


I stumble upon http://tailwindcss.com & https://htmx.org and suddenly things have gotten far easier than ever.

I have found I write far less markup than bootstrap (despite I only have a few custom css), can do custom styling easily, can do theming easily, etc. And with htmx I could move nearly 95% of all to the server side, yet have close to the same experience than with vue.

Considering that a lot of stuff still need to travel to the backend have the logic on the client have not been that useful for my needs.

My only gripe? I need to use npm to run the production builds with tailwind for have less size, but, I have (finally!) small css!


> Instead, I like Svelte’s model which essentially allows you to write things this way, but have it result in light DOM, so that you can still do server-side rendering if you desire

I've never used web components before, and I use SSR a lot (ASP. NET Core) - are you unable to use SSR with all web components, or only those that use shadow DOM? What's the reason I can't just render an `<sl-whatever>` and render the `value` attribute at the server?

Apologies if I've misunderstood or got some of this wrong!


It’s just the Shadow DOM, because it doesn’t serialise (which is roughly demonstrated thus: if you take document.documentElement.outerHTML it won’t include any of the shadow roots, and there’s nothing you can do in a .html file to produce a shadow root without adding JavaScript to insert it).

So if you have a component looking like this in your dev tools:

  <sl-emoticon which="smile">
    #shadow-root (open)
      :-)
  </sl-emoticon>
Its HTML serialisation will still be <sl-emoticon which="smile"></sl-emoticon>, never with a :-).

Look, there are ways around this lack of serialisation of shadow roots; the examples in https://github.com/skatejs/ssr succinctly show early experiments in the field, where it serialises the shadow root as an element, which it then turns into a shadow root with an inline script—but if the JavaScript doesn’t run, that won’t work and you’ll be left with a weirdly broken element, so I disqualify it and say “Shadow DOM is incompatible with SSR”.

But for Web Components in general, there’s nothing stopping you serialising them with their light DOM, though if your component goes adding children to itself when or after you connect it you might need your connectedCallback to detect if this has effectively already happened (on the server side), and wire things up instead of changing its children. This process (wiring a JS-side component tree to an already-existing DOM, rather than rendering from scratch) is known as rehydration and applies to more than just Web Components.


Some of this stuff is bleeding edge and not every possible use case has been addressed. Web components bring a valuable contribution to what browsers are capable of, and everything will catch up in time. For example, there's already talk about a declarative shadow DOM [1].


Hmm, this all sounds... complicated. Incompatibility with SSR is a deal-breaker for me (I mainly work with ASP.NET Core), so unfortunately I don't think this is for me afterall.


You can do that, I render web components with python. Treat them as black-box custom HTML tags in your server side template.


I do not think this is an issue for one very important reason: There is "Web-Apps" that just need JS and when deactivated it does not make sense at all to use them. Look at apps like [Prezi](https://prezi.com/) as an example.

I concur that normal content like news articles should still be accessible without activating any JS at all.

The idea of real web components not bound to any of these fancy JS frameworks that die and get replaced so quickly nowadays is amazing in my opinion.


To be sure, web apps do exist where not requiring JavaScript would be impossible or unreasonably difficult—though even so, most web apps don’t fit into this category. But the very nature of perceiving this dichotomy as acceptable is what leads to people making websites that require JS: people made web apps that rendered completely with React, saying to themselves that they didn’t need to support no-JS operation here, so now they were familiar with React, then when they went to make normal websites they used what they were familiar with, never mind that requiring JS was a bad idea here. Deciding that it was OK to break no-JS users for apps (still worse, normalising this) inevitably led to breaking no-JS users on sites.

People talk about the good of web components not tied to any framework, but in practice it doesn’t tend to pan out that way. These things are a framework themselves, so now you probably have a whole extra framework for every such thing you use (though admittedly each will be a lot lighter than React or similar), and it forces you to work in a different way from what you’re used to within your main framework. People routinely end up wanting (or sometimes needing, especially when React is the root framework) tighter integrations between their frameworks, so they go wrapping the web components in a new layer, e.g. to get better types and tooling support, or to route events through their own system rather than the plain DOM events system, or to do something or other involving types that aren’t just strings. That last one is a major limitation and shortcoming of Web Components as a fully-general solution: if you’re passing in attributes, for example, it’s strings all the way, but people often want and sometimes need more complex things. As an example where this causes substantial inefficiency, imagine a chart element that needs an array of data; if it’s straight web components, you’ll be nudged firmly towards turning it into a bunch of elements, or serialising it as JSON and setting it as an attribute, where setting it as a property (something you can only do via JS, so you’ve lost the declarative nature of the element) will be way more efficient.


Some things are just not going to work without JS:

- file uploads, the browser fails to indicate that an upload is in progress, the user clicks "submit" again and again because they don't see that the browser is uploading,

- file uploads when part of a form with other fields: if some text field doesn't validate, then the form will be shown again and the user will have to upload his file again, unless you go through the length of partially saving the form ... in which case you give up on having a nice transaction that saves the form at once

- selects with at least thousands of choices, they will freeze the browser, you need an autocomplete

So, as long as your website requires a file upload, or offers to select an option for a foreign key on a table with a lot of data then JS is required. Now, that might only be the case for a page or two, that doesn't prevent the rest of your site from working without JS because webcomponents aren't as invasive as typical JS frameworks that basically want to own all of your page.

If you really want to pass JSON to your webcomponent it's pretty easy:

<your-component><script type="text/json" slot="your-data">.. dump your json here</script></your-component>

But, you could also render your stuff directly and let the webcomponent inspect the DOM and build its own data structure.

Anyway, I fail to see the shortcoming here.

WebComponents are not tied to any framework once they are built, or, if they were coded without.

Shoelace doesn't require loading of any framework, but it's built with the brilliant StencilJS library: required to build, not to use.

For me the only shortcoming is with browser based ES modules but they are being fixed with the ImportMap proposal.


What you’re describing are all inadequacies in current browsers to deliver a good user-experience for native HTML features. There’s no reason why browsers can’t show upload progress/status for non-AJAX uploads, and there’s no reason for browsers to keep on having poor <select> UX. etc.

JavaScript itself is a workaround - it shouldn’t be the solution.


There's also no reason to expect browsers to become anything more than poor man's window decorations for webkit/etc, cause it didn't happen for three decades. We're on our own here and that ain't gonna change.


He's describing only SOME ways to solve those use-cases. No way I'm trading extensibility and programmability of a browser for something some guy thought up to be 'ideal' solution to those cases.


If some field of the form doesn't validate then upload has to start over, unless you store the file in some tempdir and add it to the session and go through that kind of length.

What exactly do you suggest to fix select ? Even if it was parsing a JSON blob, you still have thousands of results, an autocompletion endpoint seems much more efficient.


Why can't we look at JavaScript as the solution instead of as the workaround


We’re kinda getting distracted from the original topic, but I’ll bite anyway.

File uploads are just fine without JavaScript. Sure, some users will fail to notice the throbber and status bar text that indicate that the browser is sending the request and hit the submit button again. Unfortunate, but hardly destructive.

And then if the form doesn’t validate? Yes, you should partially save the form. You typically have to do something like that when you implement all your validation in JavaScript anyway, because client-side validation is typically imperfect, and there are extra possibilities of failure on the server. The robust way of doing uploads in APIs of this style has always been to upload a blob, and then pass its ID to the form, so that you still have it if something goes wrong.

Select with zillions of choices: that’s a terrible case for a select anyway; I’d be inclined to leave it as a text box and enhance from that. Purely out of interest (not because I would recommend it), I just ran an <input list=x><datalist id=x> with 10,000 options and it performed quite tolerably in Firefox. (When I type something that matches all 10,000 options it takes as much as a few hundred milliseconds to start displaying options, but it seems to load the options to present progressively, otherwise it’d have blocked for much longer than just a few hundred milliseconds.) But that means you’ve got to transfer all the options up-front, which might be otherwise unnecessary. Anyway, again you could implement it otherwise and I can even see how a full autocomplete (just, y’know, manual autocomplete) could work without JavaScript, using an iframe and formtarget=_parent. You’ve roused my interest, I’m going to put this on my list of fun technical demonstrations to make just because I can. I have a SSR/CSR hybrid framework in mind to make which will handle these sorts of things properly, using client-side scripting where beneficial and available but working as close to perfectly as possible without it. But I certainly wouldn’t recommend anyone go to the effort of trying to make something like this work without framework support; that’s a recipe for pain. In the short to medium term, this is a case where it’s quite reasonable to require JavaScript, because the framework tooling to handle it otherwise and do it well with both server-side and client-side rendering just doesn’t exist.

In my comment I was not saying that JavaScript shouldn’t be used, but that in general you should make things so that they work in the absence of JavaScript, even if imperfectly.

My remark on Web Components shortcomings wasn’t about passing JSON—which you can do in an attribute without difficulty, no need for a text/json script in general—it was at the fact that you need to do something like that, because all you have for representing things is DOM nodes. The shortcoming is that you can’t pass data structures and objects by identity to your component like you might with components in systems like React, Vue, Angular or Svelte. Instead, you have to serialise and deserialise constantly, which is wasteful, or else dodge out of its declarative nature and use properties instead of attributes, which is rather contrary to the design and concept of Web Components (and would broadly be anathema to Declarative Shadow DOM, contrasted to the likes of Svelte SSR + rehydration can if necessary relink things where object identity and exact data structures are valuable).

I think you understand what I meant by “framework”. React is a framework: it requires that you write your code in such-and-such a way, upon which it offers such-and-such functionality. Web Components is a framework. StencilJS targets the Web Components framework, and by virtue of extra runtime code it provides or must generate, it’s kind of a framework itself.


> I’m not saying that JavaScript shouldn’t be used, but that the absence of JavaScript should be supported in general, even if it isn’t perfect.

Aside from an SEO perspective, I don't understand why this is still such a popular perspective. JavaScript is so ubiquitous that turning it off is akin to removing the wheels from a car and expecting it to drive. Perhaps some cars will, but would you really want to take a trip in it?

To your point, I tried disabling JS on Amazon recently and I was able to make a purchase, but the website felt broken, the product preview carousel didn't work, and I definitely didn't want to use it like that again. IMO, you can't disable JavaScript in 2020 and have a good web experience.


I have js disabled by default for years now, mainly because for the type of content I randomly access, the percieved speed is a whole lot faster. E.g. I can start reading an article immediatly instead of waiting for content to stop jumping around or watching a spinner while a couple 100 kloc worth of js load an convert a bunch text in json to a bunch of text in html.

As an additional bonus I can get trough reading an entire article without newsletter signup modals being shoven down my throat.

For sites I use regularly and I as a user benefit from more interactivity not just the advertisers, I hit the toggle switch to activate js.

But I dont think this is a particularly popular or that common a perspectice. If it werent for fear of a SEO penalty the web would be much less usable without js activated.


This is exactly why I disable it: better speed, fewer annoyances, with bonuses of less data transferred and more privacy.


> I can start reading an article immediatly instead of waiting for content to stop jumping around or watching a spinner while a couple 100 kloc worth of js load an convert a bunch text in json to a bunch of text in html.

I absolutely understand this point. It's the most frustrating thing about this decade of the web or, really, ever since browsers disabled popups.

However, I don't think this is a case against JavaScript as much as it is about poor web design practices. This is what happens when websites force feed visitors garbage to get clicks and when developers add things without regard to performance.


I'm not against JavaScript (or any other languages running in the browser for that matter). Ironically, when I started doing this I was a full time frontend dev.

For me this was just a "hack" to significantly improve my browsing experience. While I'm not advocating people doing the same, I disagree with the sentiment that absolutely everything is an app and static documents being an archaic concept.

One of my gripe is with people claiming that the absolute priority is the user and their experience, while all they really care about is conversion numbers and how quickly the devs can churn out new features.

And the other aspect is the same why I don't like this image so popular with product managers

https://blog.crisp.se/wp-content/uploads/2016/01/Making-sens...

While I do get and agree with the main point they are making, the image also implies that the more complex a product is, the better. But a car is not inherently better, more useful than a bicycle. The latter will outperform it in many use cases.

I see it the same with websites/apps. If you are building an browser based photoshop alternative, by all means throw all the shiny tools and frameworks at it, I'm willing to let it load a little and I'm not expecting it to work blazingly fast on a 50$ phone and a spotty 3G connection. But for a textual content based website, maybe consider letting the user just hop on and get going.

And I do think framework independent web components are the way to go for this btw.


Well maybe one could argue that you can have a decent browsing experience, I like to be able to view content without JS enabled (I'm a uMatrix user myself).

But as you say, as soon as you want to do something like a form that's a bit complicated then of course some browser side interactivity is going to be very helpful.


Fair enough. Thanks for posting this, btw!


But your point makes a lot of sense, really what we all hate is when a page slows down your computer because it loads a gazillion of ad scripts and all. Some scripts is ok, if the site works after I enable the first scripts that seem legit to me then I'll save the config and move on with my life.

Thanks to you for sharing your code ! We're lucky to have Shoelace and you ;)


I'd gladly take more spartan websites if they load quickly and minimize Javascript.

It's one of the reasons I really like Hacker News.


Agreed, but this is also due to the population that hn targets ...

Also, as soon as you want to do something that's a bit more complicated than displaying a textarea and a handful of inputs or selects in a profile page, then JS is going to help a improving UX a lot ...

TBH it feels to me that webcomponent pages load faster than Vue/React/Angular sites, so at least that's an interesting compromise.


I agree in theory, but really HN is lacking some features which would make it more enjoyable all which would likely need minimal JS, e.g. sorting, notifications, and some better way to read multi-page discussions. You will likely never read this comment since HN has no notification concept!


Neither sorting nor notifications require any JavaScript whatsoever. As an example, old Reddit has sorting and notifications and handles them all server-side with no JavaScript required. “A better way to read multi-page discussions” is too vague for me to comment on.


I just tried a datalist with 4 elements: https://jsfiddle.net/zguvdet0/

And it doesn't cut it for a foreign key: it can't even have a separate option value and label like the basic select ... Well, it sort of can, but then the user sees the value of the option (the related row id in the context of a CRUD) and not the label ...

Does that mean that when I choose "something" and go back to my form again i will see "123" because "123" is the id of "something" on the remote row ?

I must be doing it wrong ... otherwise, it's far from acceptable UX.

https://jsfiddle.net/zguvdet0/


You seem almost to be deliberately fabricating problems. In this case the solution seems rather obvious: you would put the label as the value, and resolve the label back to an ID on the backend. Just as you’d be checking the ID on the backend anyway, to make sure it’s valid.

Yes, this could be a problem if the label is not unique. But if that could happen you already had problems, because how was the user supposed to tell which “ACME Inc.” they were supposed to click on?


I'm sorry to make you feel this way, I'm fine ignoring the typical customer that will not accept such an UX for the shake of the discussion, I'm fine with having unique labels even though that means that I would either have to store them in the DB, either rebuild them, for example, in the case of "<firstname> <lastname> (<email>)", I'm afraid a user could do a typo in-between selection and form submission, for example while opening the form on an existing object to modify another field (users do mis-click, and give me a call), in this case, should I be showing the input with the data that contains the typo so that the user can see it and delete the value and start over ?

Also I know users would be happier if I could display some kind of image along with the labels like an avatar, to make a form (boring by definition?) more lively. Do you really believe it was a mistake to make select fields accept a different label and value ? If not, then why don't the input+datalist do the same ?

And even then, what's the equivalent of a select multiple based on an input+datalist ? Please, forgive my ignorance, but I don't understand how to allow multiple selection with a datalist and an input and no JS, without having the user submit the form for each choice they want to add.

I to filter the datalist choices based on another field value without JS ? for example, a country field that would filter users.

How can I have a datalist of countries and a datalist of cities, so that you get to choose your city based on the country ? Do I have to omit the Country field and show 300k cities ? Do you realize how many cities are named "Springfield" ? The datalist would have to propose like 50 results at the time and the user would have to search through them (assuming their browser could load the 300k cities without crashing), wouldn't it be much better to first have a country and then state or region selector to make it easier for them ?

I'm not trying to create problems, I'm trying to find solution for problems that users actually have ... And I have a repo that does /just/ that with a very specific backend framework and has 1400+ stars so the problem seems pretty real to me ...


I was never proposing datalist as a solution, far less a general one (it’s definitely not!), just pointing out its existence and potential suitability for some cases, and as a point of interest.

You can typically get a really long way with just plain text boxes, and then if they produce an invalid or probably-incorrect value, prompt them “did you mean such-and-such?” (and either force them to select a correct value or allow them to say “no, I really meant what I typed”). In fact this would sometimes be better than the types of combo boxes or autocompleting dropdowns people often use, which often have poorly-implemented failure flows (e.g. if you have to choose a valid value and it’s fetching valid values from the backend, and it makes you wait a second until the response comes back, ever time, or else it’ll forget you typed anything). And it can combine with live JS-powered validation if desired, or not.

Especially for addresses, I find the approach of allowing almost freeform text entry and then proposing ways of massaging it into shape to be excellent. Either one totally freeform field, or a series of text boxes depending on the country—and isn’t it an issue that we often put the country field last even when it can affect the understanding of earlier fields! But it’s technically more difficult to do this and requires extra functionality probably on the backend or via some external API to do well (to say nothing of countries with, shall we say, massage-resistant addresses), so software developers tend to do things the technically-trivial way rather than the more adventurous way that, if done well, will be better for users. (And perhaps it’s just as well, because if done badly it would be much worse.)

But really, most of what I’m talking about is just thinking about the no-JS behaviour, particularly when designing things from scratch. When you have an existing system that already doesn’t want to work that way you’re kinda stuck, but greenfield developments are a good time to lay down the right foundations.


Maybe I'm just a moron but when I see framework or libraries like this, I want to see examples like bootstrap. I see nothing on the homepage that shows me what this actually does. Again... Maybe I'm an idiot, but in today's age, everyone wants things visualized. I think showing some examples right off the bat could not only show the benefits of using this, but help explain it better to people like myself. As of now I see no reason to use this.


This isn't just a UI/UX skin to applied to your website. Looking for an example of what a button or other element looks like is irrelevant as it's customizable.

I personally appreciated the introduction to Custom Elements and an explanation of the philosophy of the framework. So much of what we do as developers involves tight coupling and lock-in to a full-stack.


This is a great idea. I ended up publishing the documentation site _as_ the website and didn't even think to show some examples.


DUDE!!!!! AWESOME!!!!! now that is what i'm talking about!

I am in love with the tooltip :)

https://shoelace.style/components/tooltip


Ya, I'd love to see a demo page where you show off 25-50% of your favorite examples. The individual doc pages look really nice though


I'm still shocked at the decades it took for web technology to "discover" component based architectures. It's the main reason I steered clear of JS and web tech as much as I could, with a small dalliance to Echo2 in 2007.


To be fair, mozilla had a component-based architecture for the web since 1997 (called XUL). Some things were a bit odd to use but it worked pretty well and for the next ~20 years, it was way ahead of HTML & co. in just about everything, including localization, accessibility and performance.


XUL made one big mistake: RDF.

It's basically a law: anything RDF touches, will fail to get adoption.


The problem with encapsulated components is you surrender flexibility. For example, “components” for things like buttons and checkboxes are straightforward enough. But what about a checkbox-list? And how does that component accept data for data-binding purposes?

Another place where “components” generally fall-over is when a component needs to act as a parent or container for arbitrary markup: yes, there’s the “slot” system but those are still defined and controlled by the component, not the consumer - even though ultimately it’s the consumer’s application.

I compare the situation to the component ecosystem for VB6 and WinForms - which to be fair was a lot worse as consumers often had little to no control over how those components rendered, appeared or behaved - but (no pun intended) elements of the same problem exist today.

Another example is WPF - which has major unaddressed issues still - which to be fair is worlds apart from WinForms in terms of what it’s templating system is capable of. A nice thing about WPF was that a component (Control’s) XAML was transparent and editable at design-time in VS, so the consuming application’s developer could get what they want out of it, the catch was that WPF templates are horrendously complex: getting VS to expose the XAML for even a <Button> would dump 50KB+ of markup into your application XAML because it was an all-or-nothing system and you needed XAML for every button state and behaviour - right down to the pulsating button glow effect that was only ever used in Windows Vista...


It's not always easy to provide a good dev exp with complex components, but it's not impossible. Using composition wisely can offer endless flexibility while maximizing code reuse.

For example, Shoelace's <sl-select> component mimics the browser's <select> component. It has single select, multi-select, size variations, shape variations, type-ahead selection, validation states, etc. This component is a composition of <sl-dropdown>, <sl-input>, <sl-menu>, etc. and its entire source is less than 500 LOC (including doc comments and prettier formatting).

This is significantly less than many independent <select> alternatives I've seen, and the component itself doesn't have to worry about positioning, styling, etc. because that's handled by lower-level components.

> Another place where “components” generally fall-over is when a component needs to act as a parent or container for arbitrary markup: yes, there’s the “slot” system but those are still defined and controlled by the component, not the consumer - even though ultimately it’s the consumer’s application.

With web components, slotted content stays in the light DOM and is therefore controlled by the user. It's actually kind of a pain point when building them because, internally, you don't have that much control over arbitrary markup. (You can access markup through slot.assignedNodes() and style things with ::slotted() but it's not what I'd call a first-class experience for component developers.)


Isn’t the answer... more components? If the more complex components are themselves composed of a small number of simple components, you can replicate them with your own tweaks.


The difficulty was not discovering it but implementing it. The DOM was not built for abstractions like components -- it's a fundamentally global, imperative API.


Why does it feel like JavaScript development is always accompanied with a huge amount of emoji?


I used to be with it. Then they changed what 'it' was, now what I'm with isn't it and what's 'it' seems weird and scary to me.

It'll happen to you!


Thanks, Abe.


The average age of a developer is ~30 (https://insights.stackoverflow.com/survey/2016#developer-pro...) and JavaScript is very popular (https://insights.stackoverflow.com/survey/2016#technology). Couldn't actually find any solid figures on the average age of a JavaScript developers.

So it's probably likely that it's younger developers (such as myself) that are used to using emoji and like to use a bit of emoji to add colour and personality to the page.

I'm rather stereotyping here though, it could be some older person who just loves emoji too


I am in my thirties, so I guess I fit the stereotype. (They're mostly limited to the homepage though.)


you just don’t understand what it ️ means to ️ develop for the ️ web.


The only component I want to see in a demo of any UX framework - be it desktop or web - is the almighty tree table. I‘d like to see sorting, filtering, column resizing and -reordering, including save / restore of the above. Row (multi-)selection, striping, hover. Inline editing. Show me all other components inside a row.


Tables can get quite complex as features get sprinkled on. I doubt any out-of-the-box solution will nail it for all use cases. I'm not opposed to including one in Shoelace at some point, but I'd want it to have an API that's capable of handling the majority of [reasonable] use cases in an elegant way.

It's definitely high up on the list of components that are challenging to get right!


Little detail not mentioned: no server-side rendering possible at all.


I'm not really sure what you mean: I actually pre-render everything in templates, when in webcomponent however I use the slot attribute which also is an implemented standard now.

Anyway, that's the feature to pre-render everything: https://stenciljs.com/docs/hydrate-app


Shoelace is using the Shadow DOM. You fundamentally can’t prerender that yet. (Refer to my comment.) I’m a little surprised to see no mention of that in the Stencil docs.


Actually, you can disable shadow dom on Stencil components, which I ended up doing in my own code because it then nicely integrates with my favorite server side framework, that still does most of the work.

What is it exactly that you can't pre-render ? That's not very clear to me. You can put any kind of content inside your web-component tags:

<your-paragraph><p>your test</p></your-paragraph>

If the browser is recent enough to support TLS 1.3 (which we all want to move on too don't we !) then it is recent enough to support web-components for sure.

So, that's pretty much how I see it: browsers have to upgrade for security reasons, if we're getting features like the ability to do some components without having to load a fat frontend framework, components that integrate perfectly with my favorite server side framework, then my question is why: why should we not haz nice things ? we're getting them for free after all ! Without even webpack to make a 1MB bundle ! I'd like your help to better understand what's the bad news here ...


I’m not familiar with Stencil, but it looks like the Shadow DOM switch is targeted at the component author, as something that they will need to adjust their code for, and thus I would expect that it won’t be quite as simple as just turning off shadow DOM, though it could still be straightforward, though still something you’d need to do. I’m not sure. Other aspects of Shoelace might also be designed with Shadow DOM in mind, though the couple of components I’ve glanced at the code of seem safe; but interactions between Shadow DOM and ID references (e.g. <label for>, aria-describedby) can be a little fiddly.

I’m talking about the document becoming interactive and operative without or before JavaScript is loaded. Shadow DOM is not part of the HTML serialisation, so anything using Shadow DOM fails this test. Fixing this is what Declarative Shadow DOM research project is about.


Confirmed that the shadow dom switch is available to the component author, so they'd have to do two builds if they wanted to use both in different projects.

Agreed the shadow dom didn't seem ready for me neither, but I feel that we're getting there, and meanwhile it's hopefully optional.


This is not true. You can pre-render shadow DOM with stencil - it has an option to generate a separate package which takes in HTML for components and outputs the shadow HTML ready for rehydration on client, including all the necessary CSS. This can be called on server before sending to client. Or at build-time for static sites.


When using stencil prerendering or SSR, you absolutely can write a component with shadow dom and have it prerendered. For example, most of ionic's components (https://ionicframework.com/docs) are shadow dom, and you can prerendering an Ionic app. The prerendered html generates a flat dom tree, and when the clientside JS hydrates each component it'll update the component to use shadow dom, all without a flicker, and it reuses the same original dom nodes.


I should have been more specific: I was speaking of SSR working and being interactive without JavaScript, based upon my interpretation of the significance of jiofih’s comment. Hence also my reference to my other comment, which goes into more technically precise detail (concerning the shadow DOM not being serialisable, hence JavaScript being required to make any faking of that work again). I used the word “prerendering” because the parent comment did, but I should have been more careful with my terminology, because I didn’t quite mean that.


That's not correct, Stencil has support for pre-rendering Shadow DOM components.


Stencil requires you to use NodeJS - so if you want to use it with a “traditional” non-SPA ASP.NET or PHP web-application then you’re SOL.


Well, at least you can still pre-render inside your web-component tags - like I do in python.


That's not entirely true. If you pre-render your pages then there's no server-side Stencil code needed. You just need to serve those pages to the client and they will hydrate.

EDIT: don't understand the downvotes, seeing as we built Stencil. Stencil can definitely be used in a more traditional server-side environment like ASP.Net or PHP


I didn't see any documentation on Stencil's website regarding how to pre-render Stencil components without using their NodeJS toolset.

(I did not downvote you, and someone has downvoted me as well, it seems)


This is built using stencil which supports server-rendering

https://stenciljs.com/docs/hydrate-app


Very nice library! Good to see web components taking of.


I'm very excited about web components. One thing that I don't understand yet is how server side pre rendering works in these situations. Basically the elements need to be downloaded before the browser can render anything, which will delay the page in it time. I guess if everyone was using the CDN then these components would be cached for multiple applications. But they would still need to be initialized and render themselves on each page load,which could take long for complex components.


I'm no expert here, but Stencil is capable of SSR [1]. I believe you'd need to install Shoelace locally and tweak a few configs to get it working, though.

1. https://stenciljs.com/docs/static-site-generation


That looks amazing. Using bootstrap or other css frameworks across different frameworks (react, vue etc) is a pain. This looks like a good start!


On mobile Safari I can’t seem to long press on any links to bring up the menu for Open in background, Copy etc. At first I thought this might be a consequence of how the toolkit was built but it seems its standard Docsify behaviour. A callback to the old ‘disable right-click’ functionality in IE that thankfully newer browsers ignored.


Good catch, I never noticed that. I'll see what's up with Docsify and submit a PR if I can fix it upstream.


Very interesting, a team at my company recently started writing an internal UI toolkit as well. The first stage would just be HTML + CSS (and maybe some JavaScript), but the second stage will be web components as well, to make it framework agnostic.


Maybe Shoelace can save you some time. Thanks for checking it out!


The drawer component doesn't seem to work in Firefox 78. Clicking on the buttons to open the drawers doesn't do anything.


This was addressed here: https://github.com/shoelace-style/shoelace/issues/103

Just tested with Firefox 78 and verified it's working now. You may have an older cache.


Just tried again and yes, it works now.


But where is the difference to e. g. UIkit? Only write in component-style without div-tags and use css-vars?


Well Shoelace/StencilJS/WebComponents leverages browser ESM support and as such is able to import scripts as-needed as you browse, you can see that by leaving the Networking tab open in the browser inspector, and I believe that's pretty nice - that's the kind of reason why webpack got chunk splits ...

You can probably achieve that with UIkit if you make one bundle per page with webpack or something, but with web components such as Shoelace you get that for free. So there's that, wether it matters to you or not is up to you of course.


The difference is in how they're built and consumed.

UIkit sprinkles CSS and JS on top of existing HTML elements: <div uk-dropdown></div>

Shoelace defines web components, which are custom elements: <sl-dropdown>


Is it just me or doesn't any of the examples work ?


Doesn't work for me on mobile but I'm using materialize for Android which opens it in a web view so that could be part of my issue. Haven't tried Firefox or chrome on mobile.


Seems to be working for most people. Are you using a legacy browser?


There's some polyfill for IE11, maybe it would be worth a try ?

https://stenciljs.com/docs/browser-support/

It seems it is necessary for browsers that have been abandoned and that are never going to have TLS 1.3 support: IE11, Edge 16-18

Personally I'd leave it just to push users onto abandoning those browsers that will never support TLS 1.3.


[flagged]


I disagree. The OP explores the new territory of web components which are framework-agnostic by their sheer nature.

This might be well the future right around the corner.


This is a bit off topic, to put it lightly, but seriously, please read your comment again and reconsider how you talk to and about people. It is clear you have supremacist disdain for the creator out of a self-generated sense of superiority, but reality is that it is something you can or cannot use, so just ignore it if you don't like it. Maybe, if you are so much better, you could even provide some mentorship or guidance by providing constructive, i.e., useful, criticism; if it is warranted. But try to maybe address why you are the way you are instead of trying to degrade others as you externalize your issues.

I believe you should be able to say what you said and it should not be removed or even lashed with downvotes by the archetypal rabid reddit type mob, but I hope you really consider your words.

Even if you are correct on the face of it being just another one of those horrible bootcamper, why would you want to lash at someone who is trying to do things, who maybe didn't have the opportunities you had, or is just trying to improve and get feedback. Not everyone is as perfect as you.

With that; let's see your framework that is perfect and far better than Shoelace.


That's some nice personal attacks you got right there ! Just to clarify: I'm not affiliated with the author, and haven't even used or contributed the lib, I just stumbled on it and thought it was pretty nice and wanted to share it. As for my resume well it already has everything you would ever dream of; not that I care: I have my own ventures.


What was going through your mind when you wrote this?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: