Skip to content

Commit 3e9d785

Browse files
authored
fix(select): change event deep shadow (#2791)
1 parent fbe1b87 commit 3e9d785

File tree

3 files changed

+82
-4
lines changed

3 files changed

+82
-4
lines changed

.changeset/little-bags-post.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
"@patternfly/elements": patch
3+
---
4+
`<pf-select>`: prevent bug when select is in a deeply nested in shadow root

elements/pf-select/pf-select.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ export class PfSelect extends LitElement {
306306
this.#expandedChanged();
307307
}
308308
if (changed.has('value')) {
309-
this.dispatchEvent(new Event('change', { bubbles: true, cancelable: true }));
309+
this.dispatchEvent(new PfSelectChangeEvent());
310310
}
311311
// whether select has removable chips for selected items
312312
// NOTE: revisit this in v5
@@ -382,7 +382,6 @@ export class PfSelect extends LitElement {
382382
.filter(x => !!x)
383383
.map(x => x!.value)
384384
.join();
385-
this.dispatchEvent(new PfSelectChangeEvent());
386385
switch (this.variant) {
387386
case 'single':
388387
this.hide();
@@ -404,8 +403,7 @@ export class PfSelect extends LitElement {
404403
case 'checkbox':
405404
if (this.expanded) {
406405
const root = this.getRootNode();
407-
if (root instanceof ShadowRoot
408-
|| root instanceof Document
406+
if ((root instanceof ShadowRoot || root instanceof Document)
409407
&& !this.options.includes(event.relatedTarget as PfOption)
410408
) {
411409
this.hide();

elements/pf-select/test/pf-select.spec.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,82 @@ describe('<pf-select>', function() {
529529
});
530530
});
531531

532+
describe('in a deep shadow root', function() {
533+
let element: PfSelect;
534+
const focus = () => element.focus();
535+
const updateComplete = () => element.updateComplete;
536+
beforeEach(async function() {
537+
const fixture = await createFixture(html`
538+
<shadow-root>
539+
<template shadowrootmode="open">
540+
<shadow-root>
541+
<template shadowrootmode="open">
542+
<pf-select variant="single"
543+
accessible-label="Choose a number"
544+
placeholder="Choose a number">
545+
<pf-option value="1">1</pf-option>
546+
<pf-option value="2">2</pf-option>
547+
<pf-option value="3">3</pf-option>
548+
<pf-option value="4">4</pf-option>
549+
<pf-option value="5">5</pf-option>
550+
<pf-option value="6">6</pf-option>
551+
<pf-option value="7">7</pf-option>
552+
<pf-option value="8">8</pf-option>
553+
</pf-select>
554+
</template>
555+
</shadow-root>
556+
</template>
557+
</shadow-root>`);
558+
559+
function attachShadowRoots(root?: Document | ShadowRoot) {
560+
root?.querySelectorAll<HTMLTemplateElement>('template[shadowrootmode]').forEach(template => {
561+
const mode = template.getAttribute('shadowrootmode') as 'open' | 'closed';
562+
const shadowRoot = template.parentElement?.attachShadow?.({ mode });
563+
shadowRoot?.appendChild(template.content);
564+
template.remove();
565+
attachShadowRoots(shadowRoot);
566+
});
567+
}
568+
attachShadowRoots(document);
569+
570+
const select = fixture.shadowRoot?.firstElementChild?.shadowRoot?.querySelector('pf-select');
571+
if (select) {
572+
element = select;
573+
await element?.updateComplete;
574+
} else {
575+
throw new Error('no element!');
576+
}
577+
});
578+
describe('expanding', function() {
579+
beforeEach(focus);
580+
beforeEach(press('Enter'));
581+
describe('pressing ArrowDown', function() {
582+
beforeEach(press('ArrowDown'));
583+
beforeEach(updateComplete);
584+
it('remains expanded', function() {
585+
expect(element.expanded).to.be.true;
586+
});
587+
describe('pressing ArrowDown', function() {
588+
beforeEach(press('ArrowDown'));
589+
beforeEach(updateComplete);
590+
it('remains expanded', function() {
591+
expect(element.expanded).to.be.true;
592+
});
593+
describe('pressing Space', function() {
594+
beforeEach(press(' '));
595+
beforeEach(updateComplete);
596+
it('closes', function() {
597+
expect(element.expanded).to.be.false;
598+
});
599+
it('sets value', function() {
600+
expect(element.value).to.equal('2');
601+
});
602+
});
603+
});
604+
});
605+
});
606+
});
607+
532608
// try again when we implement activedescendant
533609
describe.skip('variant="typeahead"', function() {
534610
beforeEach(async function() {

0 commit comments

Comments
 (0)