fix(button): remove active when mouse/key up on other element (fix #210)
This commit is contained in:
parent
471d662cb2
commit
f3303ae014
2 changed files with 84 additions and 31 deletions
|
|
@ -138,12 +138,12 @@ export class LionButton extends DisabledWithTabIndexMixin(
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
this.__setupDelegation();
|
this.__setupEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectedCallback() {
|
disconnectedCallback() {
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
this.__teardownDelegation();
|
this.__teardownEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
_redispatchClickEvent(oldEvent) {
|
_redispatchClickEvent(oldEvent) {
|
||||||
|
|
@ -180,42 +180,50 @@ export class LionButton extends DisabledWithTabIndexMixin(
|
||||||
this.addEventListener('click', this.__clickDelegationHandler, true);
|
this.addEventListener('click', this.__clickDelegationHandler, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
__setupDelegation() {
|
__setupEvents() {
|
||||||
this.addEventListener('mousedown', this.__mousedownDelegationHandler);
|
this.addEventListener('mousedown', this.__mousedownHandler);
|
||||||
this.addEventListener('mouseup', this.__mouseupDelegationHandler);
|
this.addEventListener('keydown', this.__keydownHandler);
|
||||||
this.addEventListener('keydown', this.__keydownDelegationHandler);
|
this.addEventListener('keyup', this.__keyupHandler);
|
||||||
this.addEventListener('keyup', this.__keyupDelegationHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__teardownDelegation() {
|
__teardownEvents() {
|
||||||
this.removeEventListener('mousedown', this.__mousedownDelegationHandler);
|
this.removeEventListener('mousedown', this.__mousedownHandler);
|
||||||
this.removeEventListener('mouseup', this.__mouseupDelegationHandler);
|
this.removeEventListener('keydown', this.__keydownHandler);
|
||||||
this.removeEventListener('keydown', this.__keydownDelegationHandler);
|
this.removeEventListener('keyup', this.__keyupHandler);
|
||||||
this.removeEventListener('keyup', this.__keyupDelegationHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__mousedownDelegationHandler() {
|
__mousedownHandler() {
|
||||||
this.active = true;
|
this.active = true;
|
||||||
}
|
const mouseupHandler = () => {
|
||||||
|
|
||||||
__mouseupDelegationHandler() {
|
|
||||||
this.active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
__keydownDelegationHandler(e) {
|
|
||||||
if (e.keyCode === 32 /* space */ || e.keyCode === 13 /* enter */) {
|
|
||||||
e.preventDefault();
|
|
||||||
this.active = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__keyupDelegationHandler(e) {
|
|
||||||
// Makes the real button the trigger in forms (will submit form, as opposed to paper-button)
|
|
||||||
// and make click handlers on button work on space and enter
|
|
||||||
if (e.keyCode === 32 /* space */ || e.keyCode === 13 /* enter */) {
|
|
||||||
e.preventDefault();
|
|
||||||
this.active = false;
|
this.active = false;
|
||||||
|
document.removeEventListener('mouseup', mouseupHandler);
|
||||||
|
};
|
||||||
|
document.addEventListener('mouseup', mouseupHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
__keydownHandler(e) {
|
||||||
|
if (!this.__isKeyboardClickEvent(e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.active = true;
|
||||||
|
const keyupHandler = keyupEvent => {
|
||||||
|
if (this.__isKeyboardClickEvent(keyupEvent)) {
|
||||||
|
this.active = false;
|
||||||
|
document.removeEventListener('keyup', keyupHandler, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener('keyup', keyupHandler, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
__keyupHandler(e) {
|
||||||
|
if (this.__isKeyboardClickEvent(e)) {
|
||||||
|
// redispatch click
|
||||||
this.shadowRoot.querySelector('.click-area').click();
|
this.shadowRoot.querySelector('.click-area').click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line class-methods-use-this
|
||||||
|
__isKeyboardClickEvent(e) {
|
||||||
|
return e.keyCode === 32 /* space */ || e.keyCode === 13 /* enter */;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,21 @@ describe('lion-button', () => {
|
||||||
expect(el.hasAttribute('active')).to.be.false;
|
expect(el.hasAttribute('active')).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('updates "active" attribute on host when mousedown on button and mouseup anywhere else', async () => {
|
||||||
|
const el = await fixture(`<lion-button>foo</lion-button>`);
|
||||||
|
const topEl = getTopElement(el);
|
||||||
|
|
||||||
|
down(topEl);
|
||||||
|
expect(el.active).to.be.true;
|
||||||
|
await el.updateComplete;
|
||||||
|
expect(el.hasAttribute('active')).to.be.true;
|
||||||
|
|
||||||
|
up(document.body);
|
||||||
|
expect(el.active).to.be.false;
|
||||||
|
await el.updateComplete;
|
||||||
|
expect(el.hasAttribute('active')).to.be.false;
|
||||||
|
});
|
||||||
|
|
||||||
it('updates "active" attribute on host when space keydown/keyup on button', async () => {
|
it('updates "active" attribute on host when space keydown/keyup on button', async () => {
|
||||||
const el = await fixture(`<lion-button>foo</lion-button>`);
|
const el = await fixture(`<lion-button>foo</lion-button>`);
|
||||||
const topEl = getTopElement(el);
|
const topEl = getTopElement(el);
|
||||||
|
|
@ -92,6 +107,21 @@ describe('lion-button', () => {
|
||||||
expect(el.hasAttribute('active')).to.be.false;
|
expect(el.hasAttribute('active')).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('updates "active" attribute on host when space keydown on button and space keyup anywhere else', async () => {
|
||||||
|
const el = await fixture(`<lion-button>foo</lion-button>`);
|
||||||
|
const topEl = getTopElement(el);
|
||||||
|
|
||||||
|
keyDownOn(topEl, 32);
|
||||||
|
expect(el.active).to.be.true;
|
||||||
|
await el.updateComplete;
|
||||||
|
expect(el.hasAttribute('active')).to.be.true;
|
||||||
|
|
||||||
|
keyUpOn(document.body, 32);
|
||||||
|
expect(el.active).to.be.false;
|
||||||
|
await el.updateComplete;
|
||||||
|
expect(el.hasAttribute('active')).to.be.false;
|
||||||
|
});
|
||||||
|
|
||||||
it('updates "active" attribute on host when enter keydown/keyup on button', async () => {
|
it('updates "active" attribute on host when enter keydown/keyup on button', async () => {
|
||||||
const el = await fixture(`<lion-button>foo</lion-button>`);
|
const el = await fixture(`<lion-button>foo</lion-button>`);
|
||||||
const topEl = getTopElement(el);
|
const topEl = getTopElement(el);
|
||||||
|
|
@ -106,6 +136,21 @@ describe('lion-button', () => {
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
expect(el.hasAttribute('active')).to.be.false;
|
expect(el.hasAttribute('active')).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('updates "active" attribute on host when enter keydown on button and space keyup anywhere else', async () => {
|
||||||
|
const el = await fixture(`<lion-button>foo</lion-button>`);
|
||||||
|
const topEl = getTopElement(el);
|
||||||
|
|
||||||
|
keyDownOn(topEl, 13);
|
||||||
|
expect(el.active).to.be.true;
|
||||||
|
await el.updateComplete;
|
||||||
|
expect(el.hasAttribute('active')).to.be.true;
|
||||||
|
|
||||||
|
keyUpOn(document.body, 13);
|
||||||
|
expect(el.active).to.be.false;
|
||||||
|
await el.updateComplete;
|
||||||
|
expect(el.hasAttribute('active')).to.be.false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('a11y', () => {
|
describe('a11y', () => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue