Re: [WICG/webcomponents] [open-stylable] Collection of user stories (Issue #1052)

**User story**: I’m building a web app. I’ve already written the styles for various user interface elements (e.g. buttons, form controls). Now I have a larger composition that I need to repeat throughout the app which includes a number of these elements (e.g. a modal dialog that includes a few buttons) and I would like to use the shadow DOM for this. Slots are the wrong tool for the job since the component doesn’t need the composition they provide. Parts are equally awkward since they require me to rewrite my CSS. I would love to write the styles for these elements once, then allow the web components in my app use them (ideally without requiring my _entire_ stylesheet also be applied to the shadow root).

<details><summary>Why slots are awkward for this use case?</summary>
<p>

DSD used purely for example and some details might be left out:

```html
<delete-dialog>
  <template shadowrootmode=open>
    <dialog>
      <form method=post>
        <slot name=confirm-button></slot>
        <slot name=cancel-button></slot>
      </form>
    </dialog>
  </template>
  <button class="button button--danger" slot=confirm-button>Yes, delete it.</button>
  <button class="button button--secondary" slot=cancel-button formmethod=dialog>Cancel</button>
</delete-dialog>
```

Problem: I’m not interested in making this abstraction super flexible. Needing to use slots here is creating extra work when I want to use the component: I want the component itself to know which buttons to use, what their text content should be, and any sort of other attributes they need. Further, requiring the buttons to be provided as slotted content makes this more prone to failure.

</p>
</details>

<details><summary>Why parts are awkward for this use case?</summary>
<p>

DSD used purely for example and some details might be left out:

```html
<delete-dialog>
  <template shadowrootmode=open>
    <dialog>
      <form method=post>
        <button part=confirm-button>Yes, delete it.</button>
        <button part=cancel-button formmethod=dialog>Cancel</button>
      </form>
    </dialog>
  </template>
</delete-dialog>
```

To style these I need to use `::part(confirm-button)` and `::part(cancel-button)`.

```css
.button,
::part(confirm-button),
::part(cancel-button) { /* button styles */ }

.button--danger,
::part(confirm-button) { /* button danger styles */ }

.button--secondary,
::part(cancel-button) { /* button secondary styles */ }
```

You might have noticed that these part names aren’t great for mapping to my button classes. They are what I might expect from a custom element though since they are more semantic. It could be better if I wrote my custom element but instead use more presentational part names:

```html
<delete-dialog>
  <template shadowrootmode=open>
    <dialog>
      <form method=post>
        <button part="confirm-button button button--danger">Yes, delete it.</button>
        <button part="cancel-button button button--secondary" formmethod=dialog>Cancel</button>
      </form>
    </dialog>
  </template>
</delete-dialog>
```

Now when I write my CSS it’s a bit better:

```css
.button,
::part(button) { /* button styles */ }

.button--danger,
::part(button--danger) { /* button danger styles */ }

.button--secondary,
::part(button--secondary) { /* button secondary styles */ }
```

In this situation the problem might well be solved for this use case, however, it requires a strict one-to-one in regard to part name and class name. If I use a third party component, then I might not get the presentational information that I need from the part names and end up needing to do something like the first parts example. Further, now since my button selector is not just `.button` in my system, any element that contains buttons needs to select both `.button` and `::part(button)`.

</p>
</details>

<details><summary>Why not wrap your styled elements in custom elements so they can be used in shadow roots?</summary>
<p>

- Form associated elements won’t associate with any forms they are a part of—there would need to be extra logic written to make that work (i.e. making the wrapper element a form associated element).
- Third party custom elements don’t know about my styled custom element, so this requires me to have the styles available to apply to parts that they might expose.
- I don’t want to modularize my entire CSS component library just to use the Shadow DOM.

</p>
</details>

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

Message ID: <WICG/webcomponents/issues/1052/2008672378@github.com>

Received on Wednesday, 20 March 2024 05:16:08 UTC