JSFiddle - React, Tailwind, and code Playground

by sirisian

HTML

<div>
	<ui-treenode>
		<ui-treenode>
			<ui-treenode2></ui-treenode2>
			<ui-treenode2></ui-treenode2>
			<ui-treenode2></ui-treenode2>
		</ui-treenode>
		<ui-treenode></ui-treenode>
		<ui-treenode></ui-treenode>
	</ui-treenode>
</div>

<div>
	<ui-treenode>
		<ui-treenode>
			<ui-treenode2></ui-treenode2>
			<span slot="test">def</span> <!-- This breaks the global CSS as it ignores slot filtering -->
			<ui-treenode2></ui-treenode2>
			<ui-treenode2></ui-treenode2>
		</ui-treenode>
		<ui-treenode></ui-treenode>
		<ui-treenode></ui-treenode>
	</ui-treenode>
</div>

CSS

* { margin: 0; padding: 0; }
body > div:first-child {
	margin-bottom: 20px;
}

:is(ui-treenode, ui-treenode2) > :is(ui-treenode, ui-treenode2) + :is(ui-treenode, ui-treenode2)::part(text) {
	border-left: 10px solid red;
}
:is(ui-treenode, ui-treenode2) > :is(ui-treenode, ui-treenode2):has(+ :is(ui-treenode, ui-treenode2))::part(text) {
	border-right: 10px solid blue;
}

JavaScript

const uiTreeNodeStyle = new CSSStyleSheet();
uiTreeNodeStyle.replaceSync(`:host {
	display: block;
}
slot:not([name]) {
	display: flex;
	flex-flow: column nowrap;
	padding-left: 20px;
}
`);

class UITreeNode extends HTMLElement {
	constructor() {
		super();
		const $span = document.createElement('span');
		$span.textContent = 'abc';
		$span.part = 'text';
		const $namedSlot = document.createElement('slot');
		$namedSlot.name = 'test';
		$span.appendChild($namedSlot);
		this.attachShadow({mode: 'open'}).append(
			$span,
			document.createElement('slot')
		);
		this.shadowRoot.adoptedStyleSheets.push(uiTreeNodeStyle);
	}
}
customElements.define('ui-treenode', UITreeNode);

class UITreeNode2 extends UITreeNode {
	constructor() {
		super();
	}
}
customElements.define('ui-treenode2', UITreeNode2);