Recent submissions

Comment · 1 year ago
It's not possible to make slots work without a separate tree like shadow DOM. The browser can't tell what the container for a slot is vs what content should project into it.
Comment · 1 year ago
It's wrong - both that it's general "current advice", and the advice itself when it does pop up.

Yes, there are some people who say to build web components without shadow DOM, but I'm convinced they're only building leaf nodes so they don't need composition with slots. As soon as they try to build any kind of container element they hit big problems.

Comment · 1 year ago
Slots definitely don't work without shadow DOM and there's really no way to make them work. It's the biggest problem with turning shadow DOM off.
Comment · 1 year ago
Lots of comments in here are about shadow DOM, so let me give my take in one place:

Yes, Lit uses shadow DOM by default (for good reasons, I think!) and yes you can turn it off component-by-component, but that does bring some challenges.

Shadow DOM is most fundamentally just a private branch of the DOM tree for a component's internal DOM details.

Frameworks have this implicitly with DOM defined in a component's template vs passed as children. But that distinction isn't visible to other code, the browser, and CSS. This is both good and bad.

The biggest thing this separate tree gives us is the ability to tell what nodes are "children" - those are the light DOM children. Once you can separate children from internals, you can build slots. Slots are holes in the internals that children get rendered into.

Without something like shadow DOM you can't have slots. And without slots you don't have interoperable composition and you don't have viable container elements. You need some way to place children in an element that isn't confused with the element's own DOM.

So to me, before encapsulation and style scoping, interoperable composition is the most important feature, and that's really why Lit defaults to shadow DOM on. Without it we'd need some special `.children` property and Lit's component composition suddenly wouldn't be compatible with everyone else.

But the style encapsulation is often a major pain for developers, especially if they're trying to integrate web components into an existing system with whole-page stylesheets. It's a big blocker to a lot of design systems porting to web components.

That's one reason I proposed something called "Open Styleable Shadow Roots"[1] which would let styles from outer scopes cascade into a shadow root - a way to break open style encapsulation but keep slots. It's been hard convincing browser vendors that this is needed, but I'm holding out hope that it makes progress soon.

[1]: https://github.com/WICG/webcomponents/issues/909

Comment · 1 year ago
The great thing about web components is that you can build them however works best for you.

Native web component APIs don't have the DX that many people expect though, because they are so low-level. Lit provides just that declarative reactivity on top.

Comment · 1 year ago
Comment · 1 year ago
Yes!
Comment · 1 year ago
Comment · 1 year ago
There really is no way to metaprogram against class fields except with decorators.

Class fields aren't on the prototype. They're essentially Object.defineProperty() calls that occur right after the super() call of a constructor. You can't get at them at all from the class declaration.

I know more than one way to do something is sometimes a downside, but we have a large audience an a huge portion of it wants to use TypeScript and declarators, and another huge portion of it wants to use vanilla JavaScript. We factored things to give the best DX we could to each group with relatively little cost to us.

As for why metaprogramming, we want a component to update when it's state is changed. Like plain web components, Lit uses classes.

So here, we want setting `el.name` to cause the component to re-render:

    class MyElement extends LitElement {

      name = 'World';

      render() {
        return html`<h1>Hello ${this.name}</h1>`
      }
    }
We do that by replacing `name` with a getter/setter pair where the setter schedules an update of the instance. Without decorators, there's no way to see that `name` even exists, much less replace it.

Decorators actually do the replacement for us, we just have to build the thing to replace it with:

    class MyElement extends LitElement {

      @property() accessor name = 'World';

      render() {
        return html`<h1>Hello ${this.name}</h1>`
      }
    }
Comment · 1 year ago
Comment · 1 year ago
Lit's just a JavaScript library published as standard modules, so it doesn't require a bundler. Using Lit efficiently is the same as using any other library.

HTTP/3, import maps, and HTML preloads can make unbundled app deployment almost reasonable in some cases. You'd still miss out on minification and better compression form a bundle. Shared compression dictionaries will make this better though.

Comment · 1 year ago
I think web components already compete extremely well for application development, and you see very complex apps built with Lit out there: Photoshop, Firefox, Chrome OS, Chrome DevTools.

Apps are well served because they have more control about how components are used: they can import the same shared styles into every component, take are to not double-register elements, etc.

But I think there are some important standards still missing that would open things up even more in the design system and standalone components side:

- Scoped custom element registries. This moves away from a single global namespace of tag names. Seems like it's about to ship in Safari. Chrome next.

- Open styleable shadow roots. Would allow page styles to flow into shadow roots. This would make building components for use with existing stylesheets easier.

- CSS Modules. Import CSS into JS. Shipping in Chrome. About to land in Firefox.

- ARIA reference target: make idref-based reference work across shadow roots

Comment · 1 year ago
Lit maintainer here. I should be going to bed, but I'll answer any questions if people have any!

Not sure why Lit showed up on the front page tonight :)

Comment · 1 year ago
You have a very large axe to grind against web components and Lit, and you show up just about everywhere to make the same comments, but I'll play along anyway:

Yes, Lit templates give some special meaning to attribute names with a few prefixes. No, it's not "HTML-like". It's valid HTML. Not that it matters much. You bring this up all the time but I'm not sure what the actual criticism is. Developers seem to understand the small syntax carve-out just fine.

No, there are no custom JavaScript rules. Templates have some rules. I'm not sure why they wouldn't? In general you can't make things like tag and attribute names dynamic because you can't change them in HTML. You can actually write the template you show with what we call static templates though.

`classMap()` is a template directive. It has some rules about how it's used in templates, just like other JS functions can have rules about how their used. I'm not sure what makes that not a function.

But to your main point: Lit is not like React because it's not a framework. Lit helps you make custom elements - it's an implementation detail of some web components. Everything else about those elements: how you instantiate them, style them, where they work, etc., is all defined by the HTML and DOM standards. React is a framework, and defines its own rules about how its components work.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton