|
27 | 27 | END: 35,
|
28 | 28 | };
|
29 | 29 |
|
| 30 | + /** |
| 31 | + * Cloning contents from a <template> element is more performant |
| 32 | + * than using innerHTML because it avoids addtional HTML parse costs. |
| 33 | + */ |
| 34 | + const accordionTemplate = document.createElement('template'); |
| 35 | + accordionTemplate.innerHTML = ` |
| 36 | + <style> |
| 37 | + :host { |
| 38 | + display: flex; |
| 39 | + flex-wrap: wrap; |
| 40 | + flex-direction: column; |
| 41 | + align-items: stretch; |
| 42 | + } |
| 43 | + ::slotted(.animating) { |
| 44 | + transition: transform 0.3s ease-in-out; |
| 45 | + } |
| 46 | + </style> |
| 47 | + <slot></slot> |
| 48 | + `; |
| 49 | + |
| 50 | + // HIDE |
| 51 | + // ShadyCSS will rename classes as needed to ensure style scoping. |
| 52 | + ShadyCSS.prepareTemplate(accordionTemplate, 'howto-accordion'); |
| 53 | + // /HIDE |
| 54 | + |
30 | 55 | /**
|
31 | 56 | * `HowtoAccordion` is a container element for headings and panels.
|
32 | 57 | *
|
|
36 | 61 | class HowtoAccordion extends HTMLElement {
|
37 | 62 | constructor() {
|
38 | 63 | super();
|
| 64 | + this.attachShadow({mode: 'open'}); |
| 65 | + this.shadowRoot.appendChild(accordionTemplate.content.cloneNode(true)); |
39 | 66 | }
|
40 | 67 |
|
41 | 68 | /**
|
42 | 69 | * `connectedCallback` hooks up the even listeners and considers the
|
43 | 70 | * `expanded` attribute on the headers to adjust their styling accordingly.
|
44 | 71 | */
|
45 | 72 | connectedCallback() {
|
| 73 | + // HIDE |
| 74 | + // Shim Shadow DOM styles. This needs to be run in `connectedCallback()` |
| 75 | + // because if you shim Custom Properties (CSS variables) the element |
| 76 | + // will need access to its parent node. |
| 77 | + ShadyCSS.styleElement(this); |
| 78 | + // /HIDE |
| 79 | + |
46 | 80 | // `<howto-accordion-headers>` emit a custom event when the heading is
|
47 | 81 | // instructed to expand.
|
48 | 82 | this.addEventListener('change', this._onChange);
|
|
413 | 447 | // Another advantage is focus management. If the button inside ShadowDOM has
|
414 | 448 | // focus, `document.activeElement` returns the containing
|
415 | 449 | // `<howto-accordion-heading>` element rather than the button itself.
|
416 |
| - const shadowDOMTemplate = document.createElement('template'); |
417 |
| - shadowDOMTemplate.innerHTML = ` |
| 450 | + const accordionHeadingTemplate = document.createElement('template'); |
| 451 | + accordionHeadingTemplate.innerHTML = ` |
418 | 452 | <style>
|
419 | 453 | :host {
|
420 | 454 | contain: content;
|
|
428 | 462 | </style>
|
429 | 463 | <button><slot></slot></button>
|
430 | 464 | `;
|
| 465 | + // HIDE |
| 466 | + // ShadyCSS will rename classes as needed to ensure style scoping. |
| 467 | + ShadyCSS.prepareTemplate(accordionHeadingTemplate, 'howto-accordion-heading'); |
| 468 | + // /HIDE |
431 | 469 |
|
432 | 470 | /**
|
433 | 471 | * `HowtoAccordionHeading` is the element for the headings in the accordion.
|
|
469 | 507 | mode: 'open',
|
470 | 508 | delegatesFocus: true,
|
471 | 509 | });
|
472 |
| - // Import the ShadowDOM template. |
| 510 | + // Clone the shadow DOM template. |
473 | 511 | this.shadowRoot.appendChild(
|
474 |
| - document.importNode(shadowDOMTemplate.content, true) |
| 512 | + accordionHeadingTemplate.content.cloneNode(true) |
475 | 513 | );
|
476 | 514 | this._shadowButton = this.shadowRoot.querySelector('button');
|
477 | 515 | }
|
|
480 | 518 | * `connectedCallback()` sets up the role, event handler and initial state.
|
481 | 519 | */
|
482 | 520 | connectedCallback() {
|
| 521 | + // HIDE |
| 522 | + // Shim Shadow DOM styles. This needs to be run in `connectedCallback()` |
| 523 | + // because if you shim Custom Properties (CSS variables) the element |
| 524 | + // will need access to its parent node. |
| 525 | + ShadyCSS.styleElement(this); |
| 526 | + // /HIDE |
| 527 | + |
483 | 528 | if (!this.hasAttribute('role'))
|
484 | 529 | this.setAttribute('role', 'heading');
|
485 | 530 | if (!this.id)
|
|
553 | 598 | window.customElements
|
554 | 599 | .define('howto-accordion-heading', HowtoAccordionHeading);
|
555 | 600 |
|
| 601 | + /** |
| 602 | + * Cloning contents from a <template> element is more performant |
| 603 | + * than using innerHTML because it avoids addtional HTML parse costs. |
| 604 | + */ |
| 605 | + const accordionPanelTemplate = document.createElement('template'); |
| 606 | + accordionPanelTemplate.innerHTML = ` |
| 607 | + <style> |
| 608 | + :host(:not([expanded])) { |
| 609 | + display: none; |
| 610 | + } |
| 611 | + </style> |
| 612 | + <slot></slot> |
| 613 | + `; |
| 614 | + |
| 615 | + // HIDE |
| 616 | + // ShadyCSS will rename classes as needed to ensure style scoping. |
| 617 | + ShadyCSS.prepareTemplate(accordionPanelTemplate, 'howto-accordion-panel'); |
| 618 | + // /HIDE |
| 619 | + |
556 | 620 | // `panelIdCounter` counts the number of IDs generated for panels and is used
|
557 | 621 | // to generated new, unique IDs.
|
558 | 622 | let panelIdCounter = 0;
|
|
567 | 631 | class HowtoAccordionPanel extends HTMLElement {
|
568 | 632 | constructor() {
|
569 | 633 | super();
|
| 634 | + this.attachShadow({mode: 'open'}); |
| 635 | + this.shadowRoot.appendChild( |
| 636 | + accordionPanelTemplate.content.cloneNode(true) |
| 637 | + ); |
570 | 638 | }
|
571 | 639 |
|
572 | 640 | /**
|
573 | 641 | * `connectedCallback()` sets up the role and the ID of the element.
|
574 | 642 | */
|
575 | 643 | connectedCallback() {
|
| 644 | + // HIDE |
| 645 | + // Shim Shadow DOM styles. This needs to be run in `connectedCallback()` |
| 646 | + // because if you shim Custom Properties (CSS variables) the element |
| 647 | + // will need access to its parent node. |
| 648 | + ShadyCSS.styleElement(this); |
| 649 | + // /HIDE |
| 650 | + |
576 | 651 | if (!this.hasAttribute('role'))
|
577 | 652 | this.setAttribute('role', 'region');
|
578 | 653 | if (!this.id)
|
|
0 commit comments