Re: [WICG/webcomponents] Shadow DOM mode as opt-in feature flags (Issue #1049)

Hi, @caridy. Thank you for your question and the opportunity to be more clear in my proposal. First and foremost, none of what I am proposing is new functionality; it's a means the selectively opting into various subsets of existing functionality that you currently have to use either all together or not at all. I think it will be easiest to answer your questions in reverse order.

5. Because each flag is opt-in, overlap doesn't matter. For example setting mode to `"open"` is exactly the same as specifying `"encapsulate-ids  encapsulate-events encapsulate-styles"`. If you set mode to `"open encapsulate-styles"` there is no conflict, you're simply being redundant; it's the same as saying `"encapsulate-ids  encapsulate-events encapsulate-styles encapsulate-styles"`. To your point `closed` is a little harder to describe because I didn't propose a flag to individually opt-in to making the `.shadowRoot` property of the host element a private accessor. I'll add a recommendation of a `private-accessor` flag to the original post for completeness. At which point setting mode to `"closed"` would be exactly the same as setting mode to `"private-accessor encapsulate-ids  encapsulate-events encapsulate-styles"`.

4. Because each flag is opt-in, specifying `"none"` means exactly that: don't encapsulate anything. All ids, events, and styles are shared with the Light DOM. What you still get is a shadow root in which `<slot>` elements will still work as expected, so you essentially get the functionality that's desired when people request "Light DOM with slots." There is still a shadowRoot, so it's not technically Light DOM anymore, but you get the desired conceptual effect.

3. Even with `mode="open"`, not all events bubble out of the Shadow DOM to the Light DOM. The ones that do are re-parented to the shadow root's host element. If an open shadowRoot contains a button for example, the click event is re-emitted to the Light DOM as a click event with a target of the host element, rather than having a target of the internal button. Other events, such as `change` and `input` are blocked entirely and the custom-element author has to re-emit them manually somehow or use complicated form-associated APIs. By _not_ specifying `encapsulate-events` (leaving this value out of `mode`) you are saying you _don't_ want this re-parenting and event blocking to happen. So instead of saying `mode="open"`, you would instead say `mode="encapsulate-ids encapsulate-styles"` to get everything `open` currently gives you, _except_ for messing with events. I made a CodePen demo that you can interact with and watch the console log to get a feel for what's happening. https://codepen.io/shannonmoeller/pen/WNmYZLm?editors=1011

2. The effect of `encapsulate-ids` already exists for Shadow DOM. It's not a new feature. What is new is the ability to have this _not_ happen. Instead of `mode="open"` you could say `mode="encapsulate-events encapsulate-styles"`. Everything else would be the same as `open`, except ids would be shared with the Light DOM. This feature only makes sense with declarative Shadow DOM `<template shadowrootmode="...">`, or when using custom elements that will be used exactly one time. This is the exact same "foot-gun" that already exists when using `id` attributes, so I don't see this as posing a new risk. It's simply something you have to know to handle properly as a web developer in general.

1. The benefit of using whitespace-delimited values is that it allows you to set multiple values when using declarative Shadow DOM: `<template shadowrootmode="encapsulate-ids  encapsulate-events encapsulate-styles encapsulate-styles">`. We could conceivably limit this ability to the `shadowrootmode` attribute and require each flag as a boolean option for the `.attachShadow` JS API, but making the value of "mode" inconsistent based on where you specified it felt wrong and it makes it harder to figure out what options to give to the JS API. Do you omit `mode` entirely from the options object? Does that break backwards compatibility since omitting `mode` right now defaults to `closed`?

-- 
Reply to this email directly or view it on GitHub:
https://github.com/WICG/webcomponents/issues/1049#issuecomment-1944228209
You are receiving this because you are subscribed to this thread.

Message ID: <WICG/webcomponents/issues/1049/1944228209@github.com>

Received on Wednesday, 14 February 2024 16:55:22 UTC