Skip to content

Instantly share code, notes, and snippets.

@kristoferjoseph
Last active May 2, 2024 18:04
Show Gist options
  • Save kristoferjoseph/483d62a7e8d27be8e3dfb1af3b8a7664 to your computer and use it in GitHub Desktop.
Save kristoferjoseph/483d62a7e8d27be8e3dfb1af3b8a7664 to your computer and use it in GitHub Desktop.
Default content for unnamed slot with a declarative shadow dom quirks
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Decalarative Shadow DOM default slot with default content</title>
</head>
<body>
<!-- This specific markup is needed to render the default content in the unnamed slot inside the template shadowroot. -->
<!-- adding any spaces or new lines between 'my-button' and 'template' will cause the default slot content not to render. -->
<!-- This works -->
<my-button><template shadowrootmode="open">
<button>
<slot>Submit</slot>
</button>
</template></my-button>
<!-- Remember whitespace is significant -->
<!-- This does not -->
<my-button> <template shadowrootmode="open">
<button>
<slot>Submit</slot>
</button>
</template></my-button>
<!-- A proposed solution is this 🤷🏻‍♀️ feels hacky -->
<my-button><!-- DO NOT DELETE THIS COMMENT
--><template shadowrootmode="open">
<button>
<slot>Submit</slot>
</button>
</template><!-- DO NOT DELETE THIS COMMENT
--></my-button>
<my-button label="return"><template shadowrootmode="open">
<button>
<slot>Submit</slot>
</button>
</template>enter</my-button>
<!-- This will never show the default slot content of "Submit" -->
<my-button label="Get up">
<template shadowrootmode="open">
<button>
<slot>Submit</slot>
</button>
</template>
Get down
</my-button>
<script type="module">
customElements.define(
"my-button",
class MyButton extends HTMLElement {
constructor() {
super()
// the other tidbit that caught me off guard is that `connectedcallback` is not called when using dsd
// all setup needs to either happen in the `constructor` or `attributechangedcallback`.
// interesting to note that you can access the shadowroot in the constructor as it is set by the browser.
console.log('constructor')
const button = this.shadowRoot.querySelector('button')
console.log(button)
this.addEventListener('click', () => {
const label = button.textContent.trim()
console.log(`you clicked ${label}!`)
})
}
static get observedAttributes() {
return ['label']
}
attributeChangedCallback(name, oldValue, newValue) {
console.log('attributechanged')
if(oldValue === newValue) return
if (name === 'label') {
this.shadowRoot.querySelector('button').textContent = newValue
}
}
}
)
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment