Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-shadow-parts-1] feedback from devs #3467

Open
fergald opened this issue Dec 24, 2018 · 5 comments
Open

[css-shadow-parts-1] feedback from devs #3467

fergald opened this issue Dec 24, 2018 · 5 comments

Comments

@fergald
Copy link
Contributor

fergald commented Dec 24, 2018

spec

I've created this issue as a place to log feedback from developers who have tried using shadow parts. Even if there are features missing, knowing that the basic shape of the API is right and e.g. already works well for some set of components is useful.

@stefsullrew
Copy link

::part feedback + thoughts

Below are thoughts, questions, and general feedback from the SLDS Framework team regarding the currently implemented in Chrome. We're experimenting a little further with slots and some more complex examples, so I expect we'll add a couple other questions with examples.

Feedback

Access control

It would be very useful if it was possible to limit access to CSS rules for a defined part. The purpose is to limit the styling API of a component by only allowing certain things to be overridden or to lock down certain things that should never be overridden.

In the example below “part='title'” is defined but only “color” and “background-color” can be overridden, all other rules would be ignored.

We envision allow all by default with the possibility to allow or deny specific lists of CSS rules.

<x-foo>
    <h2 part="title" part-allow="color, background-color">Access control</h2>
    <slot></slot>
</x-foo>
x-foo::part(title) {
    color: purple; // allowed
    bacgkround-color: grey; // allowed
    height: 100%; // denied
}

In the example below “part='title'” is defined but “color” and “background-color” are locked, all other rules would apply and override the component's default styles.

<x-foo>
    <h2 part="title" part-deny="color, background-color">Access control</h2>
    <slot></slot>
</x-foo>
x-foo::part(title) {
    color: purple; // denied
    background-color: grey; // denied
    height: 100%; // allowed
}

Limited ::theme selector

The current description of the ::theme selector is perhaps a bit too broad for real world usage. However the ability to access any ::part within the context of a component, without elaborate exportparts= chains would be much easier to work with in the context of a design system.

In the example below, a theme context is defined for **x-foo** with the prefix of “foo-. This would grant access to all child parts that match the name within the declared theme's context. This scoping limits the reach of ::theme while avoiding the potentially complex exportparts= chains. Particularly when there's deep composition of components not owned by a single team.

<x-foo theme="foo-">
    <x-bar></x-bar>
    <x-oof></x-oof>
</x-foo>


// x-bar definition
<x-bar>
    <p part="metadata">Posted on: 2019-01-10</p>
</x-bar>

// x-oof definition
<x-oof>
    <svg part="icon"></svg>
</x-oof>
x-foo::theme(foo-metadata) {
    color: grey;
    font-style: italic;
}

Web Component default exportparts=

When building a custom web component via composition not having to explicitly specify exportparts= would improve the experience.

The example below presents a possible solution where, at component creation, exportparts= is defined.

class BarElement extends HTMLElement {
  constructor() {
    super();
    
    const shadowRoot = this.attachShadow({mode: 'closed'});
    
    shadowRoot.innerHTML = `
        <h1 part="header">Headline</h1>
        <p part="metadata">Posted on: 2019-01-10</p>
        <div part="content">...</div>
    `;

    if (!this.hasAttribute('exportparts'))
        this.setAttribute('exportparts', 'header, metadata, content');
  }
}

customElements.define('bar-element', BarElement);
<x-foo>
    <!-- iteration of bar-elements -->
    <!-- since no manual "exportparts=" was specified on each instance
         the defaults are exported -->
    <bar-element></bar-element>
    <bar-element></bar-element>
    ...
</x-foot>
x-foo::part(header) {
    color: green;
}

Questions

Dynamic exportparts=

Would it be possible to dynamically set the value of exportparts=?
The below example show some pseudo-code to illustrate the question.

<x-foo>
    <h1>Component headline</h1>
    
    <template for:each={items} for:item="item" for:index="idx">
        <x-item exportparts="item-header: foo-item-header-{idx}"></x-item>
    </template>
</x-foo>

::before and ::after pseudo elements

It appears the ::before and ::after pseudo elements/selectors do not function with ::part. Is this intentionally blocked, if so why? If not are there plans to add this functionality in the future?

// add an asterisk prefix to the title part
x-foo::part(title)::before {
    content: '*';
    color: red;
    margin-right: 0.25rem;
}

@frivoal
Copy link
Collaborator

frivoal commented Jan 14, 2019

This spec is not my main area of expertise, so I'll refrain from commenting on the substance until I've studied it further, but a comment on the form: usually things are much easier to process when there's one "issue" per github issue. If you want to have a master issue that links to all of them, that's fine, and we can cross link as needed, but splitting each topic into its own issue lets the CSSWG get to the bottom of each one by one, track their status independently, assign them, schedule them for discussion in teleconfs, etc.

I've reposted each point from @stefsullrew's comment (#3467 (comment)) into separate issues:

@stefsullrew
Copy link

stefsullrew commented Jan 14, 2019

Thanks so much, Florian.

@fergald
Copy link
Contributor Author

fergald commented Jan 15, 2019

Thanks @frivoal I understand your point about having separate issues and thanks for analyzing the content and creating them. The reason I created this general issue is that I was trying to get as much feedback as possible, including feedback that was purely supportive of the existing spec (for purposes of launching). I think it's easier for people to leave feedback (especially positive feedback) in a more narrative and less precise form. A github issue isn't the ideal way to do this but I'm not sure what would be a better open forum.

@klasjersevi
Copy link

I've been struggling with shadow parts for a little while now in a project with many nested web components that we want to provide external styling for. The current definition requires a lot of bloated extra code for us to achieve external styling possibilities.

exportparts

For nested components, this is very messy way of making sure everything is exported all the way to the root. A general simpler (default) way would increase the developer experience a lot. As a workaround to avoid maintenance hell, we are using a mixin that finds parts and exportparts in the subtree and forwards them on the component if needed.

parts are not selectable within the shadow dom

When defining a part name, why not make it selectable from stylesheets within the shadow dom? To select a part you have to use something like :host::part(my-part) or an attribute selector [part~=my-part] instead of simply just using ::part(my-part). It would also be easier for our third-party component users (developers) if they could just see and use the same selector as they would find in the web inspector to modify a part. It would also be easier to document.

part names vs class names

For us, the part names and our class names have the same semantical meaning and we don't want to repeat the names in two attributes like <my-component class="my-name my-other-name" part="my-name my-other-name"></my-component> so we switched from class names to part names only instead (and use an attribute selector internally). For this case it would have made more sense to just be able to export the class names right away.

Use ShadowRoot mode settings

It would be great if the exportparts were aligned with the mode provided for the shadow root, so that part names were accessible the same way as the shadow dom nodes are accessible in javascript via closed or open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants