Upgrade to Pro — share decks privately, control downloads, hide ads and more …

HTML Web Components

HTML Web Components

While Web Components have been around for years, they're seeing a bit of a renaissance thanks to an emerging approach for authoring them: ditch the shadow DOM and progressively enhance existing HTML.

In this talk, we look at what Web Components, how the "HTML Web Component" approach works, why it's awesome, and some tips, tricks, and gotchas when working with them.

Chris Ferdinandi

May 08, 2024
Tweet

More Decks by Chris Ferdinandi

Other Decks in Technology

Transcript

  1. // Create the Shadow DOM this.root = this.attachShadow({ mode: 'closed'

    }); // Inject HTML into it this.root.innerHTML = `<button aria-live="polite"> Clicked 0 Times </button>`;
  2. // Add styles to the Shadow DOM let stylesheet =

    new CSSStyleSheet(); stylesheet.replaceSync( `button { background-color: #08c; border: 1px solid #08c; color: #fff; }` ); this.root.adoptedStyleSheets = [stylesheet];
  3. Try not to bring React’s mindset with you… Do you

    really need to invent an entirely new component from scratch? Or can you use HTML up until it reaches its limit and then enhance the markup? — Jeremy Keith https://adactio.com/journal/20618
  4. <accordion-group> <h2>Merlin</h2> <p>Beard & books</p> <h2>Ursula</h2> <p>Really wants to sing</p>

    <h2>Radagast</h2> <p>Prefers dogs over people</p> </accordion-group>
  5. =*(

  6. constructor () { // Always run first super(); // Define

    properties this.count = 0; this.btn = this.querySelector('button'); }
  7. /* JS is loaded! */ count-up:defined { /* ... */

    } /* No JS yet */ count-up:not(:defined) { /* ... */ }
  8. constructor () { // ... 
 // Define properties this.count

    = 0; this.btn = this.querySelector('button'); // Listen for click events this.btn.addEventListener('click', this); }
  9. // Handle events handleEvent (event) { this[`on${event.type}`](event); } // Handle

    click events onclick (event) { console.log('clicked!'); }
  10. constructor () { // Always run first super(); // Define

    properties let start = this.getAttribute('start'); this.count = parseFloat(start) || 0; this.btn = this.querySelector('button'); }
  11. // Runs when the value of // an attribute is

    changed on the component attributeChangedCallback (name, oldVal, newVal) { this.btn.removeEventListener('click', this); } // Define the attributes to observe static observedAttributes = ['pause'];
  12. attributeChangedCallback (name, oldVal, newVal) { if (newVal === null) {

    this.btn.addEventListener('click', this); } else { this.btn.removeEventListener('click', this); } }
  13. // Instantiate the component constructor () { // Run first

    super(); // Define properties this.btn = this.querySelector('button'); this.content = this.btn.nextElementSibling; }
  14. constructor () { // ... // Define properties this.btn =

    this.querySelector('button'); this.content = this.btn.nextElementSibling; // Set initial UI this.btn.setAttribute('aria-expanded', false); this.content.setAttribute('hidden', ''); }
  15. constructor () { // ... // Set initial UI this.btn.setAttribute('aria-expanded',

    false); this.content.setAttribute('hidden', ''); // Listen for click events this.btn.addEventListener('click', this); }
  16. handleEvent (event) { // If the content is expanded, hide

    it // Otherwise, show it if (this.btn.getAttribute('aria-expanded') === 'true') { // ... } else { // ... } }
  17. handleEvent (event) { // If the content is expanded, hide

    it // Otherwise, show it if (this.btn.getAttribute('aria-expanded') === 'true') { this.btn.setAttribute('aria-expanded', false); this.content.setAttribute('hidden', ''); } else { this.btn.setAttribute('aria-expanded', true); this.content.removeAttribute('hidden'); } }
  18. show-hide button { background-color: #08c; border: 1px solid #08c; color:

    #fff; } show-hide button[aria-expanded="true"] { background-color: #343d4d; border: 1px solid #343d4d; }
  19. <accordion-group> <h2>Merlin</h2> <p>Beard & books</p> <h2>Ursula</h2> <p>Really wants to sing</p>

    <h2>Radagast</h2> <p>Prefers dogs over people</p> </accordion-group>