Skip to content

Commit

Permalink
fix(action-button): allow change events to bubble and pierce shadowdom (
Browse files Browse the repository at this point in the history
#3614)

* fix(action-button): allow change events to bubble and pierce shadowdom

* fix(action-group): guarantee one `change` event when children toggle

---------

Co-authored-by: Westbrook Johnson <westbrook.johnson@gmail.com>
  • Loading branch information
nickschaap and Westbrook authored Oct 3, 2023
1 parent b2cd3da commit 3f76e04
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/action-button/src/ActionButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ export class ActionButton extends SizedMixin(ButtonBase, {
const applyDefault = this.dispatchEvent(
new Event('change', {
cancelable: true,
bubbles: true,
composed: true,
})
);
if (!applyDefault) {
Expand Down
16 changes: 16 additions & 0 deletions packages/action-group/src/ActionGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ export class ActionGroup extends SizedMixin(SpectrumElement, {
});
}

private handleActionButtonChange(event: Event): void {
event.stopPropagation();
event.preventDefault();
}

private handleClick(event: Event): void {
const target = event.target as ActionButton;
if (typeof target.value === 'undefined') {
Expand Down Expand Up @@ -339,6 +344,17 @@ export class ActionGroup extends SizedMixin(SpectrumElement, {
if (changes.has('selects')) {
this.manageSelects();
this.manageChildren();
if (!!this.selects) {
this.shadowRoot.addEventListener(
'change',
this.handleActionButtonChange
);
} else {
this.shadowRoot.removeEventListener(
'change',
this.handleActionButtonChange
);
}
}
if (
changes.has('quiet') ||
Expand Down
40 changes: 40 additions & 0 deletions packages/action-group/test/action-group.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,46 @@ describe('ActionGroup', () => {
'Updates value of `selected`'
);
});
it('consumes descendant `change` events when `[selects]`', async () => {
const changeSpy = spy();
const el = await fixture<ActionGroup>(
html`
<sp-action-group
@change=${() => changeSpy()}
label="Selects Single Group"
selects="single"
>
<sp-action-button toggles value="first">
First
</sp-action-button>
<sp-action-button toggles value="second" selected>
Second
</sp-action-button>
<sp-action-button toggles value="third" class="third">
Third
</sp-action-button>
</sp-action-group>
`
);
const thirdElement = el.querySelector('.third') as ActionButton;

await elementUpdated(el);
expect(el.selected.length).to.equal(1);
expect(el.selected.includes('second'));
expect(changeSpy.callCount).to.equal(0);

thirdElement.click();

await elementUpdated(el);

expect(thirdElement.selected, 'third child selected').to.be.true;
expect(changeSpy.callCount).to.equal(1);

await waitUntil(
() => el.selected.length === 1 && el.selected.includes('third'),
'Updates value of `selected`'
);
});
it('does not respond to clicks on itself', async () => {
const el = await fixture<ActionGroup>(
html`
Expand Down

0 comments on commit 3f76e04

Please sign in to comment.