Skip to content

Commit aa5ea15

Browse files
authored
Howto accordion shadycss (#111)
1 parent a0ff52d commit aa5ea15

File tree

3 files changed

+86
-19
lines changed

3 files changed

+86
-19
lines changed

elements/howto-accordion/demo.html

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@
1111
limitations under the License.
1212
-->
1313
<style>
14-
howto-accordion {
15-
display: flex;
16-
flex-wrap: wrap;
17-
flex-direction: column;
18-
align-items: stretch;
19-
}
2014
/* Headings need a background color so they are not transparent. Otherwise
2115
the content will shine through during the animation. */
2216
howto-accordion-heading {
@@ -30,15 +24,6 @@
3024
padding: 20px;
3125
background-color: lightgray;
3226
}
33-
/* The accordion gets the `animating` class assigned if its children are about
34-
to be animated. The implementation relies on the `transitionend` event, so
35-
this class _must_ define a transition on the `transform` property. */
36-
howto-accordion > *.animating {
37-
transition: transform 0.3s ease-in-out;
38-
}
39-
howto-accordion-panel:not([expanded]) {
40-
display: none;
41-
}
4227
</style>
4328

4429
<howto-accordion>

elements/howto-accordion/howto-accordion.js

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,31 @@
2727
END: 35,
2828
};
2929

30+
/**
31+
* Cloning contents from a &lt;template&gt; 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+
3055
/**
3156
* `HowtoAccordion` is a container element for headings and panels.
3257
*
@@ -36,13 +61,22 @@
3661
class HowtoAccordion extends HTMLElement {
3762
constructor() {
3863
super();
64+
this.attachShadow({mode: 'open'});
65+
this.shadowRoot.appendChild(accordionTemplate.content.cloneNode(true));
3966
}
4067

4168
/**
4269
* `connectedCallback` hooks up the even listeners and considers the
4370
* `expanded` attribute on the headers to adjust their styling accordingly.
4471
*/
4572
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+
4680
// `<howto-accordion-headers>` emit a custom event when the heading is
4781
// instructed to expand.
4882
this.addEventListener('change', this._onChange);
@@ -413,8 +447,8 @@
413447
// Another advantage is focus management. If the button inside ShadowDOM has
414448
// focus, `document.activeElement` returns the containing
415449
// `<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 = `
418452
<style>
419453
:host {
420454
contain: content;
@@ -428,6 +462,10 @@
428462
</style>
429463
<button><slot></slot></button>
430464
`;
465+
// HIDE
466+
// ShadyCSS will rename classes as needed to ensure style scoping.
467+
ShadyCSS.prepareTemplate(accordionHeadingTemplate, 'howto-accordion-heading');
468+
// /HIDE
431469

432470
/**
433471
* `HowtoAccordionHeading` is the element for the headings in the accordion.
@@ -469,9 +507,9 @@
469507
mode: 'open',
470508
delegatesFocus: true,
471509
});
472-
// Import the ShadowDOM template.
510+
// Clone the shadow DOM template.
473511
this.shadowRoot.appendChild(
474-
document.importNode(shadowDOMTemplate.content, true)
512+
accordionHeadingTemplate.content.cloneNode(true)
475513
);
476514
this._shadowButton = this.shadowRoot.querySelector('button');
477515
}
@@ -480,6 +518,13 @@
480518
* `connectedCallback()` sets up the role, event handler and initial state.
481519
*/
482520
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+
483528
if (!this.hasAttribute('role'))
484529
this.setAttribute('role', 'heading');
485530
if (!this.id)
@@ -553,6 +598,25 @@
553598
window.customElements
554599
.define('howto-accordion-heading', HowtoAccordionHeading);
555600

601+
/**
602+
* Cloning contents from a &lt;template&gt; 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+
556620
// `panelIdCounter` counts the number of IDs generated for panels and is used
557621
// to generated new, unique IDs.
558622
let panelIdCounter = 0;
@@ -567,12 +631,23 @@
567631
class HowtoAccordionPanel extends HTMLElement {
568632
constructor() {
569633
super();
634+
this.attachShadow({mode: 'open'});
635+
this.shadowRoot.appendChild(
636+
accordionPanelTemplate.content.cloneNode(true)
637+
);
570638
}
571639

572640
/**
573641
* `connectedCallback()` sets up the role and the ID of the element.
574642
*/
575643
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+
576651
if (!this.hasAttribute('role'))
577652
this.setAttribute('role', 'region');
578653
if (!this.id)

elements/howto-radio-group/howto-radio-group.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@
9292
* defaults just to indcate that they will likely change in the future.
9393
*/
9494
connectedCallback() {
95+
// HIDE
96+
// Shim Shadow DOM styles. This needs to be run in `connectedCallback()`
97+
// because if you shim Custom Properties (CSS variables) the element
98+
// will need access to its parent node.
99+
ShadyCSS.styleElement(this);
100+
// /HIDE
101+
95102
if (!this.hasAttribute('role'))
96103
this.setAttribute('role', 'radio');
97104
if (!this.hasAttribute('tabindex'))

0 commit comments

Comments
 (0)