Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Button Toggle: Add ability for consumers to handle toggling pressed state #5154

Merged
merged 3 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions components/button/button-toggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { css, html, LitElement } from 'lit';

/**
* A button container component for button toggles.
* @fires d2l-button-toggle-before-change - Dispatched before pressed state is updated. Can be canceled to allow the consumer to handle toggling pressed state. This is useful if something needs to happen prior to the pressed state being toggled.
*/
class ButtonToggle extends LitElement {

Expand Down Expand Up @@ -79,9 +80,16 @@ class ButtonToggle extends LitElement {
}

async _handleClick(pressed) {
this.pressed = pressed;
await this.updateComplete;
this.focus();
const beforeToggleEvent = new CustomEvent('d2l-button-toggle-before-change', {
detail: {
update: (newPressed) => this._updatePressedState(newPressed)
},
cancelable: true
});
this.dispatchEvent(beforeToggleEvent);
if (beforeToggleEvent.defaultPrevented) return;

this._updatePressedState(pressed);
}

_handleNotPressedClick() {
Expand All @@ -92,6 +100,12 @@ class ButtonToggle extends LitElement {
this._handleClick(false);
}

async _updatePressedState(newPressed) {
this.pressed = newPressed;
await this.updateComplete;
this.focus();
}

}

customElements.define('d2l-button-toggle', ButtonToggle);
20 changes: 20 additions & 0 deletions components/button/demo/button-toggle.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,26 @@ <h2>Toggle Button (disabled)</h2>
</template>
</d2l-demo-snippet>

<h2>Toggle Button (with consumer specifying when to toggle)</h2>

<d2l-demo-snippet>
<template>
<d2l-button-toggle id="toggle-button-icon-promise-delay">
<d2l-button-icon slot="not-pressed" icon="tier1:pin-hollow" text="Unpinned, click to pin."></d2l-button-icon>
<d2l-button-icon slot="pressed" icon="tier1:pin-filled" text="Pinned, click to unpin."></d2l-button-icon>
</d2l-button-toggle>
<script>
document.querySelector('#toggle-button-icon-promise-delay').addEventListener('d2l-button-toggle-before-change', e => {
e.preventDefault();
setTimeout(() => {
e.detail.update(!e.target.pressed);
}, 2000);
});
document.querySelector('#toggle-button-icon-promise-delay').addEventListener('d2l-button-toggle-change', e => console.log(e));
</script>
</template>
</d2l-demo-snippet>

</d2l-demo-page>

</body>
Expand Down
31 changes: 31 additions & 0 deletions components/button/test/button-toggle.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,35 @@ describe('d2l-button-toggle', () => {

});

describe('consumer manages state', () => {

let el;
beforeEach(async() => {
el = await fixture(html`
<d2l-button-toggle>
<d2l-button-icon slot="not-pressed" icon="tier1:pin-hollow" text="Unpinned, click to pin."></d2l-button-icon>
<d2l-button-icon slot="pressed" icon="tier1:pin-filled" text="Pinned, click to unpin."></d2l-button-icon>
</d2l-button-toggle>
`);
});

it('click with no state management', async() => {
el.addEventListener('d2l-button-toggle-before-change', (e) => {
e.preventDefault();
});
await clickElem(el.querySelector('[slot="not-pressed"]'));
expect(el.pressed).to.equal(false);
});

it('click once with state management', async() => {
el.addEventListener('d2l-button-toggle-before-change', (e) => {
e.preventDefault();
e.detail.update(!e.target.pressed);
});
clickElem(el.querySelector('[slot="not-pressed"]'));
const e = await oneEvent(el, 'd2l-button-toggle-change');
expect(e.target.pressed).to.equal(true);
});
});

});
Loading