-
Notifications
You must be signed in to change notification settings - Fork 310
Namedslots support for web_components #1185
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
Comments
I started prototyping this: Besides the implementation being pretty non-trivial, there's also an open question of how it will actually work. For example: with multi_slot_web_component() as c:
with c.header():
me.text("header")
with c.footer():
me.text("footer-child1")
me.text("footer-child2") Because web component slots must have exactly one element (see MDN docs), this means that we'd need to have some kind of element (probably a div) to wrap the two children components (footer-child1, footer-child2). I don't like creating wrapper elements because if someone is doing flexbox styling, then adding an intermediate DOM element disrupts it (and because this is a "synthetic" component, the app developer can't really customize it either). So, then we'd need enforce that for named slots (at least for >1) web components, it must have a single child, which feels a little weird to me since we don't enforce this anywhere else in Mesop. I think we can punt on this for a while because you can technically get away with one slot and just manipulate with the children in that one slot (it's hacky, but possible): <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Footer-Header Component</title>
</head>
<body>
<!-- Example usage:
The first child will be rendered as the footer,
and the second child as the header. -->
<footer-header>
<div>First Child: Will be rendered as the footer</div>
<div>Second Child: Will be rendered as the header</div>
</footer-header>
<script>
class FooterHeader extends HTMLElement {
constructor() {
super();
// Attach a shadow root.
this.attachShadow({ mode: "open" });
// Create header and footer containers.
this._header = document.createElement("header");
this._footer = document.createElement("footer");
// Create a single slot for light DOM content.
this._slot = document.createElement("slot");
// Append containers and slot to the shadow root.
// Note: The final order will be header on top, slot (which will end up empty), then footer.
this.shadowRoot.appendChild(this._header);
this.shadowRoot.appendChild(this._slot);
this.shadowRoot.appendChild(this._footer);
}
connectedCallback() {
this.manipulateSlots();
}
manipulateSlots() {
// Get the slotted elements.
const nodes = this._slot.assignedElements();
for (const node of nodes) {
node.remove();
}
// For the first child element, move it into the footer container.
if (nodes.length > 0) {
this._footer.appendChild(nodes[0]);
}
// For the second child element, move it into the header container.
if (nodes.length > 1) {
this._header.appendChild(nodes[1]);
}
}
}
// Define the custom element.
customElements.define("footer-header", FooterHeader);
</script>
</body>
</html> |
Discussed in #1178
Originally posted by jmfk January 7, 2025
I noticed namedslots isn't implemented for web_components. It is definitely on my wish list for the future.
Since sending UI events via the server just isn't viable implementing things in web_components seems like the best solution.
But just having a single slot is a bit limiting when building UI components. I'm currently building a resizable layout component, and I want to pass sidebar, content and other pane content to it. The component it self would only handle the resize events and render the other components.
The text was updated successfully, but these errors were encountered: